【问题标题】:sobel operator - false edges natural imagessobel 算子 - 假边缘自然图像
【发布时间】:2012-11-14 01:09:11
【问题描述】:

我在使用 Sobel 算子进行边缘检测时遇到问题:它会产生太多错误边缘,效果如下图所示。 我正在使用 3x3 sobel 运算符 - 首先提取垂直然后水平,最终输出是每个滤波器输​​出的幅度。 合成图像上的边缘被正确提取,但自然图像产生的错误边缘或“噪声”太多,即使图像是通过应用模糊或中值滤波器进行预处理的。 这可能是什么原因?是实现问题(然后:为什么合成图像很好?)还是我需要做更多的预处理?

原文:

输出:

代码:

void imageOp::filter(image8* image, int maskSize, int16_t *mask)
{
    if((image == NULL) || (maskSize/2 == 0) || maskSize < 1)
    {
        if(image == NULL)
        {
            printf("filter: image pointer == NULL \n");
        }
        else if(maskSize < 1)
        {
            printf("filter: maskSize must be greater than 1\n");
        }
        else
        {
            printf("filter: maskSize must be odd number\n");
        }
        return;
    }

    image8* fImage = new image8(image->getHeight(), image->getWidth());
    uint16_t sum = 0;
    int d = maskSize/2;
    int ty, tx;

    for(int x = 0; x < image->getHeight(); x++)         //
    {                                                   // loop over image
        for(int y = 0; y < image->getWidth(); y++)      // 
        {
            for(int xm = -d; xm <= d; xm++)
            {
                for(int ym = -d; ym <= d; ym++)
                {
                    ty = y + ym;
                    if(ty < 0)  // edge conditions
                    {
                        ty = (-1)*ym - 1;
                    }
                    else if(ty >= image->getWidth())
                    {
                        ty = image->getWidth() - ym;
                    }

                    tx = x + xm;
                    if(tx < 0)  // edge conditions
                    {
                        tx = (-1)*xm - 1;
                    }
                    else if(tx >= image->getHeight())
                    {
                        tx = image->getHeight() - xm;
                    }

                    sum += image->img[tx][ty] * mask[((xm+d)*maskSize) + ym + d];
                }
            }

            if(sum > 255)
            {
                fImage->img[x][y] = 255;
            }
            else if(sum < 0)
            {
                fImage->img[x][y] = 0;
            }
            else
            {
                fImage->img[x][y] = (uint8_t)sum;
            }
            sum = 0;
        }
    }


    for(int x = 0; x < image->getHeight(); x++)
    {
        for(int y = 0; y < image->getWidth(); y++)
        {
            image->img[x][y] = fImage->img[x][y];
        }
    }

    delete fImage;
}

【问题讨论】:

  • 问题到底是什么?
  • 您使用的是标准的 3x3 sobel 运算符,大概是?
  • 这可能是什么原因?是实现问题(然后:为什么合成图像很好?)还是我需要做更多的预处理?
  • 是的,标准 3x3 运算符。尝试使用 5x5 但效果相同,“噪音”略小
  • 如果您在使用模糊滤镜后仍会收到如此多的噪音,那么我倾向于责怪您的实施。我可能会考虑将一个快速测试工具放在一起,看看会发生什么。

标签: c++ image-processing


【解决方案1】:

这似乎是由于您的代码中某处出现数学错误。为了跟进我的评论,这是我在此处通过 Sobel 运算符运行您的图像时得到的结果(边缘强度由输出图像的亮度指示):

我使用 GLSL 片段着色器来生成这个:

 precision mediump float;

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 void main()
 {
    float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
    float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
    float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
    float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
    float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
    float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
    float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
    float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
    float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
    float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

    float mag = length(vec2(h, v));

    gl_FragColor = vec4(vec3(mag), 1.0);

你没有显示你的掩码值,我假设它包含 Sobel 内核。在上面的代码中,我对 3x3 Sobel 内核中每个像素的红色通道执行的计算进行了硬编码。这纯粹是为了我的平台上的性能。

我在您的代码中没有注意到的一件事(同样,我可能会错过它,就像我将总和设置回 0 一样)是确定 Sobel 运算符的两个部分的向量的大小。如果存在的话,我希望在某处看到平方根运算。

【讨论】:

  • 找到了我的问题的原因:在计算过程中,动态范围变化并超过了用于存储它的变量的宽度,因此出现了噪音和其他伪影。做了一些返工:使用 int 而不是 uint8 或 uint16 同时应用垂直和水平过滤来存储像素值。
猜你喜欢
  • 2020-04-06
  • 2015-08-09
  • 2016-10-03
  • 2021-06-02
  • 2014-10-17
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 2021-02-01
相关资源
最近更新 更多