【问题标题】:OpenCV - Remove "white" artifacts from image and fit a curveOpenCV - 从图像中删除“白色”伪影并拟合曲线
【发布时间】:2014-05-16 04:07:45
【问题描述】:

我有一张图像,我需要在其中移除不代表检测到的曲线的“白色”伪影。我想保留代表曲线的白色像素,但要删除远离曲线的像素异常值。去除伪影后,我想将平滑曲线拟合到图像中的点。

这是我的图片:

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

到目前为止,我已经尝试执行dilation,然后是erosionclosingblack hat 操作。他们似乎都没有给我我期望的结果。 我还尝试遍历图像中的所有点,找到亮点,查看该像素周围的 3x3 邻域并将值设置为 0,如果它没有两个以上等于自身的邻居。

我可以应用什么来达到我想要的结果?另外,一旦我有了最终的“干净”输出,如何将平滑曲线拟合到图像中的点?

【问题讨论】:

  • 我认为膨胀后更大的腐蚀应该去除大部分伪影,同时保留曲线的分量。为了拟合曲线,您可以尝试一些霍夫投票方法。
  • @ChronoTrigger 不,那更糟。检测到的表面要么完全消失,要么具有比必要更多的像素,这被认为是噪声。我正在寻找一种方法来保留检测到的边缘。可能类似于连接组件方法?
  • @ChronoTrigger 什么是霍夫投票方案?您是否有一些指向文档/实现的链接,我可以从中学习东西?

标签: c++ opencv


【解决方案1】:

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


关于噪点:这个功能应该可以解决问题,我用它来去除黑色和等待图像中的噪点。 这是书中的代码示例:

通过实用的计算机视觉项目掌握 OpenCV - Daniel Lelis 巴乔

我在实例化此函数的标头上添加了这些包含:

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

using namespace cv;
using namespace std;

mask 是您要过滤的图像,它会删除分析图像周围任意 5 个像素中没有点的点... 希望对你有帮助

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++;
    }
}

【讨论】:

  • 我不想删除白色像素。我想保留曲线中白色像素的结构,但是,我想摆脱那些远离曲线的异常白色像素。我不确定您的代码要做什么,但我会尝试看看它是否有效。
  • 该代码从图像中删除了 5x5 块中的单个“黑色像素”(我使用它的时候我的噪点是黑色的)。我没有注意到您的像素岛与您的行中的比例相同。很抱歉这个不好的方法,它不会解决你的问题。
  • 您的代码为我指明了正确的方向。之后我有了一个想法,即在对角线上寻找像素,如下所示:stackoverflow.com/questions/22898881/…。当使用线段逼近曲线时,输出看起来不错。但是,理想情况下,我想要一条平滑的曲线,因为我无法摆脱所有异常值而不冒丢失检测曲线上的一堆点的风险。我想我现在必须以某种方式进行权衡,除非我真的能正确拟合曲线。
  • 如果您能够找到相邻点的质心,您可以尝试 多项式回归(实际上我认为它适用于您已经知道白色像素位置的图像) . GNU 科学图书馆 可以做到。 (rosettacode.org/wiki/Polynomial_regression#C)
  • 我不明白您所说的“相邻点质心”是什么意思?你的意思是左右两边都有白色像素的点吗?
猜你喜欢
  • 2020-02-06
  • 2020-12-05
  • 2015-12-22
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
相关资源
最近更新 更多