2014-04-04 46 views
1

我有一个图像,在这里我需要删除不代表检测到的曲线的“白色”伪影。我想保留代表曲线的白色像素,但要去除远离曲线的像素异常值。去除伪影后,我想对图像中的点进行平滑曲线拟合。OpenCV - 从图像中删除“白色”伪影并拟合曲线

这是我的形象:

white detected curve

的图像是只有黑白点的8位灰度图像的图像。 “曲线”中的白色像素是感兴趣的区域,其中大部分仅为单个像素厚。一些白色像素相互连接,但不是全部。一些白色像素散布在两边。我想删除这些白色像素,因为它们对整体形状没有贡献,因为我想为它们拟合光滑的曲线。

到目前为止,我试图做dilation,然后erosion,closingblack hat操作。他们中的任何一个似乎都没有给我预期的结果。 我还尝试遍历图像中的所有点,找到亮点,在围绕该像素的3x3邻域中查找,并将值设置为0,前提是它没有超过两个相同的邻居。

我可以申请什么以达到我想要的效果?另外,一旦我有了最终的“干净”输出,我该如何使图像中的点平滑曲线?

+0

我认为,扩张后更大的侵蚀应该在保持曲线的组成部分的同时去除大部分伪影。为了适应曲线,你可以尝试一些霍夫投票方法。 – ChronoTrigger

+0

@ChronoTrigger不,更糟。被检测的表面或者完全消失,具有比被认为是噪声的必要更多的像素。我正在寻找一种方法来保存检测到的边缘。也许类似于连接组件方法? – Eagle

+0

@ChronoTrigger什么是Hough投票计划?你有几个链接到我可以学习东西的文档/实现? – Eagle

回答

0

我不知道如何拟合曲线,如果在另一个问题中提出这个问题,你会很高兴。


关于噪音:此功能应该做的伎俩,我用它来消除黑色和等待图像中的噪音。 它是一本书一个代码示例:

掌握的OpenCV与实用计算机视觉项目 - 丹尼尔Lelis 巴乔

我的这些包括在哪里这个功能被实例化的头说:

#include "opencv2/opencv.hpp" 
#include <stdio.h> 
#include <iostream> 
#include <vector> 

using namespace cv; 
using namespace std; 

mask是你想要过滤的图像,它可以去掉在分析过的任何5个像素中没有点的点... 希望它有帮助s

void removePepperNoise(Mat &mask) 
{ 
// For simplicity, ignore the top & bottom row border. 
for (int y=2; y<mask.rows-2; y++) { 
    // Get access to each of the 5 rows near this pixel. 
    uchar *pThis = mask.ptr(y); 
    uchar *pUp1 = mask.ptr(y-1); 
    uchar *pUp2 = mask.ptr(y-2); 
    uchar *pDown1 = mask.ptr(y+1); 
    uchar *pDown2 = mask.ptr(y+2); 

    // For simplicity, ignore the left & right row border. 
    pThis += 2; 
    pUp1 += 2; 
    pUp2 += 2; 
    pDown1 += 2; 
    pDown2 += 2; 
    for (int x=2; x<mask.cols-2; x++) { 
     uchar v = *pThis; // Get the current pixel value (either 0 or 255). 
     // If the current pixel is black, but all the pixels on the 2-pixel-radius-border are white 
     // (ie: it is a small island of black pixels, surrounded by white), then delete that island. 
     if (v == 0) { 
      bool allAbove = *(pUp2 - 2) && *(pUp2 - 1) && *(pUp2) && *(pUp2 + 1) && *(pUp2 + 2); 
      bool allLeft = *(pUp1 - 2) && *(pThis - 2) && *(pDown1 - 2); 
      bool allBelow = *(pDown2 - 2) && *(pDown2 - 1) && *(pDown2) && *(pDown2 + 1) && *(pDown2 + 2); 
      bool allRight = *(pUp1 + 2) && *(pThis + 2) && *(pDown1 + 2); 
      bool surroundings = allAbove && allLeft && allBelow && allRight; 
      if (surroundings == true) { 
       // Fill the whole 5x5 block as white. Since we know the 5x5 borders 
       // are already white, just need to fill the 3x3 inner region. 
       *(pUp1 - 1) = 255; 
       *(pUp1 + 0) = 255; 
       *(pUp1 + 1) = 255; 
       *(pThis - 1) = 255; 
       *(pThis + 0) = 255; 
       *(pThis + 1) = 255; 
       *(pDown1 - 1) = 255; 
       *(pDown1 + 0) = 255; 
       *(pDown1 + 1) = 255; 
      } 
      // Since we just covered the whole 5x5 block with white, we know the next 2 pixels 
      // won't be black, so skip the next 2 pixels on the right. 
      pThis += 2; 
      pUp1 += 2; 
      pUp2 += 2; 
      pDown1 += 2; 
      pDown2 += 2; 
     } 
     // Move to the next pixel. 
     pThis++; 
     pUp1++; 
     pUp2++; 
     pDown1++; 
     pDown2++; 
    } 
} 
+0

我不想删除白色像素。我想保留曲线中白色像素的结构,但是我想摆脱那些离曲线很远的白色像素。我不确定你的代码试图做什么,但是,我会尝试看看它是否有效。 – Eagle

+0

该代码从图像中删除5x5块中的单个“黑色像素”(我使用它的时间是我的噪音是黑色的)。我没有注意到你的像素岛的比例与你的线相同。对不起,不好的方法,它不会解决你的问题。 – nico

+0

你的代码指出我正确的方向。我有一个想法之后,寻找横跨对角线的像素,如下所示:http://stackoverflow.com/questions/22898881/opencv-fit-a-curve-to-a-set-of-points。当线段用于近似曲线时,输出看起来很好。然而,理想情况下,我会喜欢光滑的曲线,因为我无法摆脱所有的异常点,而不会冒着检测到的曲线上一堆点的损失风险。除非我能够正确地拟合曲线,否则我现在必须以某种方式进行折衷。 – Eagle