【问题标题】:Unwanted Noise element during dilation膨胀期间不需要的噪声元素
【发布时间】:2015-04-27 14:32:39
【问题描述】:

我正在对二元稻谷图片应用膨胀操作。当使用的结构元素大小为 9x9 时,噪声粒子会变大,这是合乎逻辑的。但是当我使用大小为 15x15 的结构元素时,我会得到与原始噪声粒子相邻的新噪声粒子。这很令人困惑,因为我不知道为什么会这样。结构元素是一个全为 1 的 nxn 矩阵。图片已附上供参考。

参考图片:

放大图像(9x9 SE):

放大图像(15x15 SE):
请帮忙!!

代码:

void DilateBinary(Mat Image, Mat& op, double* SE, int m){
op=Image.clone();
double pixelvalue;

int limit=(m-1)/2;
for(int y = limit; y < (Image.rows - limit); y++)
            {
                for(int x = limit; x < (Image.cols - limit); x++)
                {
                    double max=0.0;
                    //printf("Input pixel: %u \n",Image.at<unsigned char>(y,x));
                    for(int j = -limit; j <=limit ; j++)
                    {
                        for(int i = -limit; i <=limit ; i++)
                        {
                            if(*(SE + (j+1)*m + (i+1) ) > 0)
                            {
                                pixelvalue = (*(SE + (j+1)*m + ((2*limit)-(i+1)) )) * (Image.at<unsigned char>(y+j,x+i));
                                //printf("%f",pixelvalue);
                                if (pixelvalue>127)
                                    max=255.0;
                            }
                        }
                    }
                    op.at<uchar>(y,x) = max;
                    //printf("Output pixel: %u \n",op.at<unsigned char>(y,x));
                    //printf("Modified pixel= %f %d\n",pixelvalue,cvRound(pixelvalue));

                }
            }

注意:SE 是指向我正在使用的掩码/SE 的指针。 & m 对于 9x9 SE 是 9,对于 15x15 SE 是 15......

【问题讨论】:

  • 那么您的问题到底是什么?为什么会发生这种情况或如何摆脱它们?还请标记您正在使用的编程语言。是matlab吗?谢谢!
  • 我认为这不应该发生。如果它是正确的,那么它为什么会发生。如果错了,那是怎么回事,我该如何纠正。
  • 我用的是C,代码已经插入到语句中了。
  • 掩码中的索引看起来不对,你会得到负索引。
  • 我很确定索引是正确的。它给出了高达 9x9 SE 的正确结果。我只收到 15x15 SE 的错误(如果是一个)。

标签: c image image-processing mathematical-morphology image-morphology


【解决方案1】:

罪魁祸首是您在第二个嵌套的 for 循环块中的 if 语句:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        if(*(SE + (j+1)*m + (i+1) ) > 0) {
            pixelvalue = (*(SE + (j+1)*m + ((2*limit)-(i+1)) ))  (Image.at<unsigned char>(y+j,x+i));
            if (pixelvalue>127)
                max=255.0;
        }
    }
}

索引到结构元素的方式假定它是 3 x 3 掩码,因为您期望 ij-1 悬停到 1。 Mark Ransom 在他的评估中是正确的,因为您会有负值的索引。尝试设置m = 15,这就是您的问题所在。这意味着limit = 7 然后从该循环的开头开始,查看您正在访问的行和列,因为您尝试使用行主要线性索引访问掩码。

如果是limit = 7,则表示开头是j = -7, i = -7,所以是(j+1)*m = (-7+1)*15 = -90。还有(2*limit) - (i+1) = (2*7) - (-7+1) = 20。这最终意味着您正在尝试访问 SE - 90 + 20 = SE - 70 的内存位置,因此您实际上是在评估距离结构元素的原点 70 个字节(假设为 unsigned char)的内存位置,而不是左上角结构化元素...所以你确定你写的代码是对的吗?我很惊讶你还没有遇到任何分段错误。您可能幸运地使用了9 x 9,因为行偏移量为负数,但列偏移量将为正数并且它们的大小可能相等,因此您可能很幸运地访问了所有结构元素,但这肯定会赢对于更大的掩码尺寸,情况并非如此。

为了确保覆盖所有的掩码系数,您需要将偏移更改为+limit,而不是+1。我也不明白if 语句中的2*limit。您可以直接访问掩码元素。因此,您需要这样做:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        if(*(SE + (j+limit)*m + (i+limit) ) > 0) {
            pixelvalue = (*(SE + (j+limit)*m + (i+limit) )) * (Image.at<unsigned char>(y+j,x+i));
            if (pixelvalue>127)
                max=255.0;
        }
    }
}

但是,如果我可以提出一些建议,因为您正在进行形态二元膨胀,您只需检查结构元素中是否有任何像素接触到白色像素。因为这是一个方形结构元素,这将更加容易。本质上,在m x m 像素邻域中,如果任何像素不为零,那么您将输出设置为 255 并跳出循环。对您的代码的一个小优化可能是:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        pixelValue = (*(SE + (j+limit)*m + (i+limit) )); // Get structuring element value
        pixelValue *= (Image.at<unsigned char>(y+j,x+i)); // Obtain corresponding intensity
        if (pixelValue != 0) { // If non-zero, set output to max and break
            max = 255.0;
            i = limit + 1; j = limit + 1; // break out of loop
        }
    }
}

当你有完全黑暗的区域时,这显然不会保存任何东西,但是当涉及到完全白色的区域时,贯穿结构元素的双嵌套 for 循环只会迭代一次。它可能会节省一些时钟周期,但请始终记住,蛮力形态已经具有可怕的计算复杂性。

【讨论】:

  • 修正有效。感谢您指出。即使我想知道我怎么没有分段错误!在这种情况下,优化最终将运行时间减少了 50% 以上。好建议!
  • @avr - 啊,这就是分配内存的东西哈哈。这是一项棘手的业务。有时在该未定义位置访问该元素有效,有时则无效。如果该数组存储在堆栈中(即在编译时声明一个已知大小的数组),而不是堆(即在运行时动态分配数组),您肯定会得到错误。
  • @rayryeng,您似乎对图像处理感兴趣-您能否帮助我们打开这个专门的小组:area51.stackexchange.com/proposals/66531/computer-vision/72084 只需对不到 10 票的问题进行投票。谢谢。
  • @Drazick - 看起来不是这样吗?不久前,我投票支持 CV StackExchange 提案并为问题投票。只等它获得批准!
  • @rayryeng,你回答了很多人,你会建议他们也帮忙吗?帮助我制作图像处理和计算机视觉论坛怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
相关资源
最近更新 更多