1

我正在对二元米粒图片应用膨胀操作。当使用的结构元素大小为 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......

4

1 回答 1

2

The culprit is your if statement inside the second nested for loop blocks:

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

The way you are indexing into your structuring element assumes that it is a 3 x 3 mask, because you are expecting that i and j hover from -1 to 1. Mark Ransom is correct in his assessment in that you would have indices with negative values. Try setting m = 15, which is where your problem lies. This means that limit = 7 and then start with the beginning of this loop see what row and column you are accessing as you are trying to access the mask with row-major linear indices.

If limit = 7, that means at the beginning, j = -7, i = -7 and so (j+1)*m = (-7+1)*15 = -90. Also (2*limit) - (i+1) = (2*7) - (-7+1) = 20. This ultimately means that you are trying to access the memory location of SE - 90 + 20 = SE - 70 so you're actually assessing the memory location 70 bytes (assuming unsigned char) away from the origin of your structuring element, and not the top left corner of the structuring element... so are you sure you wrote that code right? I'm surprised you haven't gotten any segmentation faults yet. You may have lucked out with the 9 x 9 because the row offset is negative, but the column offset will be positive and they may be equal in magnitude, so you probably lucked out with accessing all of the structuring elements then, but this certainly won't be true for higher mask sizes.

In order to ensure that you cover all of the mask coefficients, you need to change the offset to +limit, not +1. I also don't understand the 2*limit inside the if statement. You can just access the mask element directly. Therefore, you need to do this:

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

However, if I can suggest something, because you are doing morphological binary dilation, you only have to check to see if any pixels in your structuring element are touching a white pixel. Because this is a square structuring element, this will be even easier. Essentially, in a m x m pixel neighbourhood, if any pixel is non-zero, then you'd set the output to 255 and break out of the loop. A small optimization to your code could be:

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

This obviously won't save anything when you have areas of complete darkness, but when it comes to areas that are completely white, the double nested for loops that run through the structuring element will only iterate once. It may save some clock cycles, but always remember that brute-force morphology has already terrible computational complexity as it is.

于 2015-02-25T16:22:42.580 回答