11

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

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

在此之后,我得到轮廓并将它们绘制在另一个图像上,例如链接中的第三张图片。我的问题是轮廓仍然有点像素化(前卫)。有没有办法使黑白图像更加平滑以获得更好的轮廓?或者也许对轮廓做点什么。我也尝试过使用不同内核的 D​​ilate 和 Erode,但问题仍然存在。感谢您提供的任何帮助。

编辑:也试过:

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

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

4

1 回答 1

8

在此处输入图像描述

如果这是您所追求的平滑结果,则可以通过进行高斯模糊,然后进行阈值处理来获得。即使用cvSmoothwithCV_GAUSSIAN作为参数。紧随其后的是一个cvThreshold.

如果你想要一个比阈值更平滑的过渡(像这样),你可以通过调整级别来实现(重新映射颜色范围,以便保留一些边缘过渡)。

更新要解释如何在阈值处理上获得平滑(抗锯齿)边缘,请考虑阈值处理的作用。它基本上处理图像中的每个像素,一次一个。如果像素值低于阈值,则将其设置为黑色 (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 的完整范围的函数。IE

         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
于 2011-09-14T13:03:18.073 回答