如何平滑OpenCV中的曲线(轮廓)?

时间:2011-09-14 12:04:59

标签: opencv curve smoothing

我正在处理黑白图像,就像链接中的第一个一样: http://imageshack.us/g/33/firstwm.png/ 它有很多“噪音”所以我在它上面应用了一个中值滤镜来平滑它,从而获得第二张图片。

cvSmooth(TempImage, TempImage, CV_MEDIAN, 5, 0);

在此之后我得到轮廓并将其绘制在另一个图像上,如链接中的第3张图片。 我的问题是轮廓仍然有点像素化(前卫)。有没有办法平滑B& W图像以获得更好的轮廓?或者也许用轮廓做点什么。 我也尝试过不同内核的Dilate和Erode但问题仍然存在。 感谢您提供的帮助。

编辑: 还尝试过:

cvSmooth(TempImage, TempImage, CV_GAUSSIAN, 9, 9, 3);
cvThreshold(TempImage, TempImage, 127, 255, CV_THRESH_BINARY);

与中值滤波器相同的结果,好的,但仍留下一些像素化的轮廓。

1 个答案:

答案 0 :(得分:8)

enter image description here

如果这是你想要的平滑结果,可以通过高斯模糊,然后进行阈值处理来获得。即使用cvSmoothCV_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