如何为多边形逼近确定cvCanny的最佳参数

时间:2012-07-17 01:58:29

标签: c opencv computer-vision feature-detection edge-detection

这是我的源图像(忽略点,稍后手动添加):

enter image description here

我的目标是获得两只手的粗略多边形近似值。像这样:

enter image description here

我对如何做到这一点有一个大概的了解;我想使用cvCanny查找边,cvFindContours查找轮廓,然后cvApproxPoly

我面临的问题是我不知道如何正确使用cvCanny,尤其是我应该对最后3个参数(threshold1& 2,apertureSize)使用什么?我试过了:

cvCanny(source, cannyProcessedImage, 20, 40, 3);

但结果并不理想。左手看起来相对较好,但右手检测得很少:

enter image description here

总的来说,它并不像我想的那么可靠。有没有办法猜测Canny的“最佳”参数,或者至少是一个详细的解释(初学者可以理解)他们做了什么,所以我可以做出有根据的猜测?或者也许还有一种更好的方法可以完成这项工作?

2 个答案:

答案 0 :(得分:6)

似乎你必须降低你的门槛。

Canny算法适用于滞后阈值:如果至少一个像素与最大阈值一样明亮,则选择一个轮廓,如果它们高于下限阈值,则选择所有连接的轮廓像素。

论文建议采用2:1 oe 3:1(例如10和30,或20和60等)的两个阈值。对于某些应用程序,手动和硬编码确定的阈值就足够了。也可能是你的情况。我怀疑如果你降低你的门槛,你会得到很好的结果,因为图像并不复杂。

已经提出了许多自动确定最佳精确阈值的方法。他们中的大多数依靠梯度幅度来估计最佳阈值。

<强>步骤:

  • 提取渐变(Sobel是一个不错的选择)
  • 您可以将其转换为uchar。渐变的渐变可以具有比255更大的数值,但是没关系。 opencv的索贝尔回归uchars。
  • 制作所得图像的直方图。
  • 将最大阈值设置为直方图的第95个百分位数,将较低阈值设置为高/ 3。
  • 您应该根据您的应用调整百分位值,但结果将比硬编码的高值和低值更强大

注意:在Matlab中实现了一个优秀的阈值检测算法。它基于上面的想法,但有点复杂。

注意2 :如果图像区域之间的轮廓和照明变化不大,此方法将起作用。如果轮廓在图像的一部分上更清晰,那么您需要局部自适应阈值,这是另一个故事。但是看着你的照片,情况应该不是这样。

答案 1 :(得分:4)

也许最简单的解决方案之一就是在灰度图像上进行Otsu阈值处理,在二值图像上找到轮廓,然后近似它们。这是代码:

Mat img = imread("test.png"), gray;
vector<Vec4i> hierarchy;
vector<vector<Point2i> > contours;

cvtColor(img, gray, CV_BGR2GRAY);
threshold(gray, gray, 0, 255, THRESH_OTSU);
findContours(gray, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

for(size_t i=0; i<contours.size(); i++)
{
    approxPolyDP(contours[i], contours[i], 5, false);
    drawContours(img, contours, i, Scalar(0,0,255));
}

imshow("result", img);
waitKey();

这就是结果:

enter image description here