这是我的源图(忽略点,它们是后来手动添加的):
我的目标是获得两只手的粗略多边形近似值。像这样:
我对如何做到这一点有一个大概的想法;我想用 cvCanny
寻找边缘,cvFindContours
找到轮廓,然后 cvApproxPoly
.
我面临的问题是我不知道如何正确使用 cvCanny
,特别是我应该为最后 3 个参数(阈值 1 和 2、光圈大小)使用什么?我尝试这样做:
cvCanny(source, cannyProcessedImage, 20, 40, 3);
但结果并不理想。左手看起来还不错,但右手检测的很少:
总的来说,它并不像我希望的那样可靠。有没有办法猜测 Canny 的“最佳”参数,或者至少有详细的解释(初学者可以理解)他们所做的,以便我可以做出有根据的猜测?或者也许有更好的方法来完全做到这一点?
最佳答案
看来你必须降低阈值。
Canny 算法在滞后阈值上工作:如果至少有一个像素与最大阈值一样亮,它会选择一个轮廓,如果它们高于下阈值,则采用所有连接的轮廓像素。
论文建议采用 2:1 或 3:1 比例的两个阈值(例如 10 和 30,或 20 和 60 等)。对于某些应用程序,手动确定并硬编码的阈值就足够了。这也可能是你的情况。我怀疑如果你降低阈值,你会得到好的结果,因为图像并没有那么复杂。
已经提出了许多自动确定最佳精明阈值的方法。他们中的大多数依靠梯度大小来估计最佳阈值。
步骤:
- 提取梯度(Sobel 是一个不错的选择)
- 您可以将其转换为 uchar。梯度理论上可以具有比 255 更大的数值,但这没关系。 opencv 的 sobel 返回 uchars。
- 制作结果图像的直方图。
- 在直方图的第 95 个百分位处取最大阈值,较低的阈值为 high/3。
- 您可能应该根据您的应用调整百分位数值,但结果会比硬编码的高值和低值更稳健
注意:在Matlab中实现了一个优秀的阈值检测算法。它基于上述想法,但更复杂一些。
注意 2:如果图像区域之间的轮廓和光照变化不大,则此方法会起作用。如果图像的某个部分的轮廓更清晰,那么您需要局部自适应阈值,那就是另一回事了。但是看你的照片,应该不是这样的。
关于c - 如何确定用于多边形近似的 cvCanny 的最佳参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11515072/