我正在处理黑白图像,就像链接中的第一个一样: http://imageshack.us/g/33/firstwm.png/ 它有很多“噪音”,所以我在它上面应用了一个中值过滤器来平滑它,从而得到第二张图片。
cvSmooth(TempImage, TempImage, CV_MEDIAN, 5, 0);
在此之后,我得到了轮廓并将它们绘制在另一个图像上,例如链接中的第 3 张图片。 我的问题是轮廓仍然有点像素化(前卫)。有没有办法使黑白图像更加平滑以获得更好的轮廓?或者用轮廓做点什么。 我也尝试过使用不同内核的 Dilate 和 Erode,但问题仍然存在。 感谢您提供的任何帮助。
编辑: 也试过:
cvSmooth(TempImage, TempImage, CV_GAUSSIAN, 9, 9, 3);
cvThreshold(TempImage, TempImage, 127, 255, CV_THRESH_BINARY);
与中值滤波器相同的结果,好的,但仍然留下一些像素化的轮廓。
最佳答案
如果这是您想要的平滑结果,可以通过执行高斯模糊,然后进行阈值处理来获得。 IE。使用 cvSmooth
和 CV_GAUSSIAN
作为参数。后跟 cvThreshold
。
如果您想要比阈值化(如 this)更平滑的过渡,您可以通过调整级别(重新映射颜色范围以便保留一些边缘过渡)来实现。
更新 要解释如何在阈值上获得平滑(抗锯齿)边缘,请考虑阈值的作用。它基本上一次处理图像中的每个像素。如果像素值低于阈值,则设置为黑色(0),否则设置为白色(255)。
因此,阈值运算符非常简单,但是,可以使用任何其他通用映射函数。基本上它是一个函数 f(i)
,其中 i
是强度像素值(范围为 0-255),f(i)
是映射值。对于阈值这个函数很简单
f(i) = { 0, for i < threshold
255, for i >= threshold
你得到的是一个平滑的图像(通过 cvSmooth 使用高斯核,它给你“最平滑”的平滑,如果这有意义的话)。因此,您在边缘上有一个软过渡值,范围从 0 到 255。您要做的是使此过渡小得多,以便获得良好的边缘。如果你对它弹道,你直接从 0 到 255,这与你已经完成的二进制阈值相同。
现在,考虑一个函数,它可能将 4 个强度值 (127 +- 4) 的范围映射到 0-255 的整个范围。即
f(i) = { 0, for i < 123
255, for i >= 131
linear mapping, for 123 <= i < 131
然后您将获得所需的输出。我会快速浏览一下,看看它是否已经在 openCV 中实现了。不过,自己编写代码应该不会太难。
更新 2 轮廓版本将是这样的:
f(i) = { 255, for i < 122
linear mapping (255->0), for 122 <= i < 126
0, for 126 <= i < 127
linear mapping (0->255), for 127 <= i < 131
255, for 131 <= i
关于opencv - 我如何平滑 OpenCV 中的曲线(轮廓)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7416025/