扩张期间不需要的噪音元素

时间:2015-02-25 14:35:07

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

我在二元稻谷图片上应用扩张操作。当使用的结构元素具有9×9的大小时,噪声粒子变大,这是合乎逻辑的。但是当我使用尺寸为15x15的结构元素时,我会在原始噪声粒子附近获得新的噪声粒子。这是令人困惑的,因为我不知道为什么会发生这种情况。结构元素是一个带有全1的nxn矩阵。图片已附上以供参考。

参考图片:
enter image description here

扩张图像(9x9 SE):
enter image description here

扩张图像(15x15 SE):
enter image description here 请帮忙!!

代码:

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 i的指针。 &安培;对于9x9 SE,m为9,对于15x15 SE,m为15 .........

1 个答案:

答案 0 :(得分:2)

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

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在他的评估中是正确的,因为你会得到负值的指数。尝试设置1,这是您的问题所在。这意味着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的内存位置,以便您实际评估内存位置70个字节(假设SE - 90 + 20 = SE - 70)远离结构元素的原点,而不是结构元素的左上角...所以你确定你编写了正确的代码吗?我很惊讶你还没有得到任何分段错误。你可能对unsigned char感到幸运,因为行偏移是负的,但列偏移量是正的,它们的大小可能相等,所以你可能会幸运地访问所有的结构元素,但是这个对于更高的面具尺寸肯定不会成真。

为了确保涵盖所有掩码系数,您需要将偏移量更改为9 x 9,而不是+limit。我也不理解+1声明中的2*limit。您可以直接访问mask元素。因此,您需要这样做:

if

但是,如果我可以提出建议,因为你正在进行形态二进制扩张,你只需要检查你的结构元素中是否有任何像素触及白色像素。因为这是一个方形结构元素,所以这将更容易。基本上,在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; } } } 像素邻域中,如果任何像素不为零,那么您将输出设置为255并跳出循环。对代码进行小规模优化可能是:

m x m

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