从一堆对象中提取一个对象并检测边缘

Gra*_*ant 4 c++ opencv image-processing edge-detection feature-detection

对于我的大学项目,我需要通过检测叶子的边缘来从植物叶子形状中识别出一种植物.(我使用的是OpenCV 2.4.9和C++),但是源图像已经在工厂的真实环境中获取并且具有多个叶子.请参见下面的示例图像.所以在这里我需要提取一个叶子的边缘模式以进一步处理.

在此输入图像描述

使用Canny Edge Detector我可以识别整个图像的边缘.

在此输入图像描述

但我不知道如何从这里开始提取只有一片叶子的边缘图案,可能会更加清晰完整的叶子.我不知道即使这也是可能的.任何人都可以告诉我,如果这是可能的如何提取一片叶子的边缘我只是想知道我需要应用于图像的图像处理步骤.我不想要任何代码示例.我是图像处理和OpenCV的新手,通过实验学习.

提前致谢.

编辑

正如路易斯所说,在使用Canny边缘检测进行边缘检测后,我已经完成了与图像接近的形态学,但似乎仍然很难从图像中找到最大的轮廓.以下是我处理图像所采取的步骤

  1. 应用双边过滤器以减少噪音

    bilateralFilter(img_src, img_blur, 31, 31 * 2, 31 / 2);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过直方图均衡来调整对比度

    cvtColor(img_blur,img_equalized,CV_BGR2GRAY);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 应用Canny边缘探测器

    Canny(img_equalized, img_edge_detected, 20, 60, 3);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 阈值二进制图像删除一些背景数据

    threshold(img_edge_detected, img_threshold, 1, 255,THRESH_BINARY_INV);
    
    Run Code Online (Sandbox Code Playgroud)
  5. 图像的形态接近

    morphologyEx(img_threshold, img_closed, MORPH_CLOSE, getStructuringElement(MORPH_ELLIPSE, Size(2, 2)));
    
    Run Code Online (Sandbox Code Playgroud)

以下是我得到的结果图像.

这个结果我得到了上面的原始图像

在此输入图像描述

第二张图像的源图像和结果

资源 :

在此输入图像描述

结果:

在此输入图像描述

有没有办法检测最大的轮廓并从图像中提取它?

请注意,我的最终目标是使用真实的环境图像创建植物识别系统,但在这里我不能使用模板匹配或掩盖类似的东西,因为用户必须拍摄图像并上传它,因此系统没有任何先前的想法关于叶子.

这是完整的代码

#include <opencv\cv.h>
#include <opencv\highgui.h>
using namespace cv;

int main()
{
Mat img_src,     img_blur,img_gray,img_equalized,img_edge_detected,img_threshold,img_closed;
//Load original image
img_src = imread("E:\\IMAG0196.jpg");

//Apply Bilateral Filter to reduce noise
bilateralFilter(img_src, img_blur, 31, 31 * 2, 31 / 2);

//Adjust contrast by histogram equaliztion
cvtColor(img_blur,img_equalized,CV_BGR2GRAY);

//Apply Canny edge detector
Canny(img_equalized, img_edge_detected, 20, 60, 3);

//Threshold binary image to remove some background data
threshold(img_edge_detected, img_threshold, 15, 255,THRESH_BINARY_INV);

//Morphological close of the image
morphologyEx(img_threshold, img_closed, MORPH_CLOSE, getStructuringElement(MORPH_ELLIPSE, Size(2, 2)));

imshow("Result", img_closed);
waitKey(0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

小智 6

那里有一个类似的问题:

边缘信息似乎不是图像的良好描述符,如果你想尝试它,我将执行以下步骤:

  1. 加载图像并将其转换为灰度
  2. 检测边缘 - Canny,Sobel尝试它们并找到最适合你的东西
  3. 将阈值设置为消除大多数背景的给定值 - 二值化图像
  4. 关闭图像 - 形态关闭不要关闭窗口!
  5. 计算和识别图像中的对象(Blobs,Watershed)
  6. 检查每个对象的形状(假设您已经描述过之前可以找到的叶子的形状或像椭圆这样的标准形状),例如:
  7. 如果给定的对象具有您描述为叶子的给定形状,那么您检测到了叶子!

我相信给定的图像是在现实世界中拍摄的,这些算法表现不佳,但这是一个开始.嗯希望它有帮助:).

- 编辑06/07

好吧,因为你没有关于叶子的先前信息,我认为我们能做的最好的事情如下:

  • 加载图片
  • 双边过滤器
  • 谨慎的
  • 提取轮廓
  • 假设:周长最大的轮廓是叶子
  • 凸壳3或2个最大轮廓(蓝线是凸壳完成)
  • 使用此凸包在图像上进行图形切割并对其进行分割

如果您执行这些步骤,您最终会得到以下图像:

叶1分割

叶2分割

我不会在这里发布代码,但你可以在我凌乱的github中查看它.我希望你不介意它是用python制作的.

叶 - Github

尽管如此,我还有几件事要做,可以改善结果.路线图将是:

  • 在图形切割中定义蒙版(如文档中所述)
  • 应用区域生长可能会给出更好的凸壳
  • 移除触摸图像边框的所有边缘有助于识别较大的边缘

好吧,再次,我希望它有所帮助