【问题标题】:Extract one object from bunch of objects and detect edges从一堆对象中提取一个对象并检测边缘
【发布时间】:2014-08-17 14:04:35
【问题描述】:

对于我的大学项目,我需要通过检测叶子的边缘来从植物叶子的形状中识别出一种植物。 (我使用 OpenCV 2.4.9 和 C++),但源图像是在植物的真实环境中拍摄的,并且有不止一片叶子。请参见下面的示例图像。所以这里我只需要提取一片叶子的边缘图案进行进一步处理。

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

但我不知道如何从这里着手提取仅一片叶子的边缘图案,可能会更清晰完整。我不知道这是否也可能。谁能告诉我这是否可能如何提取一片叶子的边缘我只想知道我需要应用于图像的图像处理步骤。我不想要任何代码示例。我是图像处理和 OpenCV 以及通过实验学习的新手。

提前致谢。

编辑

正如 Luis 所说,在使用 Canny 边缘检测进行边缘检测后,我已经对图像进行了形态学接近,但我似乎仍然很难从图像中找到最大的轮廓。 这是我处理图像所采取的步骤

  1. 应用双边滤波器降低噪音

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

    cvtColor(img_blur,img_equalized,CV_BGR2GRAY);
    
  3. 应用 Canny 边缘检测器

    Canny(img_equalized, img_edge_detected, 20, 60, 3);
    
  4. 阈值二值图像去除一些背景数据

    threshold(img_edge_detected, img_threshold, 1, 255,THRESH_BINARY_INV);
    
  5. 图像的形态接近

    morphologyEx(img_threshold, img_closed, MORPH_CLOSE, getStructuringElement(MORPH_ELLIPSE, Size(2, 2)));
    

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

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

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

来源:

结果:

有什么方法可以检测出最大的轮廓并从图像中提取出来?

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

这是完整的代码

#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;
}

谢谢。

【问题讨论】:

  • 您可能需要采用更模糊的方法。想想不完美的边缘检测可以做什么。 (这似乎也是大部分作业)
  • 您可能会增加阈值以排除背景中的对象,然后查看剩余部分的分割
  • 是的,我可以更改阈值并获得清晰的边缘,但问题是如何获得一片叶子的边缘?
  • @Drew Dormann 你能解释一下什么是模糊方法吗?谢谢你的评论
  • 嗨,@Grant。我建议您不必担心获得一片叶子的完美轮廓,看看您可以对已经生成的图像进行哪些分析。

标签: c++ opencv image-processing feature-detection edge-detection


【解决方案1】:

这里有一个类似的问题:

似乎边缘信息不是一个很好的图像描述符,如果你想尝试一下,我会做以下步骤:

  1. 加载图像并将其转换为灰度
  2. 检测边缘 - Canny、Sobel 尝试并找到最适合您的方法
  3. 将阈值设置为消除大部分背景的给定值 - 图像二值化
  4. 关闭图像 - 形态关闭不要关闭窗口!
  5. 计数和识别图像中的对象(斑点、分水岭)
  6. 检查每个对象的形状(假设您已经描述了之前可以找到的叶子形状或椭圆等标准形状)特征,例如:
  7. 如果给定对象具有您描述为叶子的给定形状,那么您检测到了叶子!。

我相信给定的图像是在现实世界中拍摄的,这些算法的性能会很差,但这是一个开始。好吧,希望它有所帮助:)。

-- POST EDIT 06/07

好吧,既然您没有关于叶子的先验信息,我认为我们能做的最好的事情是:

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

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

这里就不贴代码了,大家可以去我乱七八糟的github看看。我希望你不介意它是用 python 制作的。

Leaf - Github

不过,我还有几件事要完成,可以改善结果。路线图是:

  • 在图形切割中定义掩码(如文档中所述)
  • 应用区域增长可能会产生更好的凸包
  • 移除所有与图像边界接触的边缘有助于识别较大的边缘

好吧,我希望它有帮助

【讨论】:

  • 感谢您的回答。在不使用边缘的情况下,我可以使用哪些其他方法来提取单个对象?
  • 好吧,如果提取的意思是识别叶子并将其从图像中分割出来,其中一些步骤仍然适用,而不是边缘,您可以借助 SIFT 或 SURF 等描述符找到叶子。我相信当前最先进的技术是卷积神经网络(深度学习),但我自己还没有使用过它们,所以我不确定。
  • 你能解释一下我试图做的形态接近,但不幸的是我无法完成叶子的边缘线。谢谢
  • 看看这个stackoverflow.com/questions/18339988/…。如果您在下周编辑您的第一篇文章并向我们展示新结果,将会有所帮助。我会自己实现一些代码并举个例子。
  • 非常感谢您的支持我已经更新了这个问题请看一下。
猜你喜欢
  • 1970-01-01
  • 2020-04-03
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2022-01-22
  • 2020-04-27
相关资源
最近更新 更多