2012-07-17 79 views
1

这是我的源图像(忽略点,他们以后手工添加):如何确定最佳参数cvCanny多边形逼近

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的“最佳”参数,或者至少有一个详细的解释(初学者可以理解)他们做了什么,以便我可以做出有根据的猜测?或者有更好的方法可以完全做到这一点?

回答

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

+0

谢谢,这是更简单和有效! – houbysoft 2012-07-17 16:29:35

6

看来你必须降低阈值。

上迟滞阈值的Canny算子工作:它选择一个轮廓如果至少一个像素被作为最大阈值,较为明亮,需要所有所连接的轮廓象素,如果他们是高于下门限。

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

一些方法来自动确定最佳精明的门槛已经被提出。他们中的大多数依赖于梯度幅度来估计最佳阈值。

步骤:

  • 提取梯度(索贝尔是一个不错的选择)
  • 你可以将它转换为UCHAR。渐变的渐变可以有比255更大的数值,但没关系。 opencv的索贝尔回归祖国。
  • 制作结果图像的直方图。
  • 在您的直方图的第95个百分点处取最大阈值,并将下限定为高/ 3。
  • 你应该根据你的应用程序可能调整百分位值,但效果会比一个硬编码HIG值和低值
  • 更强大

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

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

+0

谢谢你的解释,我现在更好地理解它。 +1。我选择了另一个答案作为接受的答案,因为这对我来说更简单。 – houbysoft 2012-07-17 16:30:02