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.