Reedbeta said:
Think about what happens on the very first iteration of the loop, when ccl = 0. The expressions ccl - nOffset and ccl - 3 will be negative, so you are trying to access memory that is not part of the image. That's why you are getting an error, because the program tries to access invalid memory.
Geometrically, you're trying to look at the pixels above and to the left from the current pixel, but if you're in the first row of the image those don't exist.
A couple other things: if you are at the first pixel in a row, ccl - 3 will give you the last pixel in the previous row, probably not what you want. Also you should be adding or subtracting stride, not nOffset, to get to the next or previous row. stride is the number of bytes in one row in memory, nOffset is just the *difference* between stride and the actual width of the image (in bytes), i.e. the amount of space that's not part of the image.
By the way, the code right before that error, "if (ccl < 0) ccl = 0", is useless. ccl will never be negative, as you can see from the line that calculates it: ccl = y * stride + x, where y, stride, and x are all positive or zero.
Thanks for helping :lol:
My programming skill is bad and I still cannot get rid on my bad habit( keep trying and fixing without analyse ) :sad:
I had change my code a lot, "somehow" that error does not prompt out again ( but I cannot get the effect I want.
public static bool Segmentation(Bitmap img)
{
BitmapData bmpdt = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmpdt.Stride;
System.IntPtr Scan0 = bmpdt.Scan0;
unsafe
{
byte* px = (byte*)(void*)Scan0;
byte* label = (byte*)(void*)Scan0; ;
int nextline = stride - img.Width * 3;
int realWidth = img.Width * 3;
byte newlabelvalue = 100;
for (int y = 0; y < img.Height; y++)
{
//if this is first row, skip scanning
if (y == 0)
{
y += 1;
}
for (int x = 0; x < realWidth; x++)
{
//if this is first column, skip scanning
if (x == 0)
{
x += 1;
}
int ccl = (y * stride) + x;
label[ccl] = (byte)px[ccl];
//if ((byte)px[ccl] == 0) //if current pixel value is 0, keep scanning
//{
// px[ccl] = (byte)px[ccl];
//}
//else
//if ((byte)px[ccl] == 1) //if current pixel value is 1, check top and left neighbour pixel value
//{
//if both top and left value of the current pixel is 0, assign new label to current pixel
if ((byte)label[ccl - stride] == 0 && (byte)label[ccl - 1] == 0)
{
px[ccl] -= newlabelvalue; //place the new value to the previous pixel, so that next pixel can refer on the original pixel value of current pixel
newlabelvalue += 50;
}
//either top or left value of current pixel is 1 and another is 0, keep the label value same as previous one
if ((byte)label[ccl - stride] == 0 && (byte)label[ccl - 1] == 1)
{
px[ccl] = (byte)px[ccl - 1];
}
if ((byte)label[ccl - stride] == 1 && (byte)label[ccl - 1] == 0)
{
px[ccl] = (byte)px[ccl - stride];
}
//if both top and left value of the current pixel is 0, assign the lesser label value to current pixel
if ((byte)label[ccl - stride] == 1 && (byte)label[ccl - 1] == 1)
{
if ((byte)label[ccl - stride] < (byte)label[ccl - 1])
{
px[ccl] = (byte)px[ccl - stride];
}
if ((byte)label[ccl - 1] < (byte)label[ccl - stride])
{
px[ccl] = (byte)px[ccl - 1];
}
}
//}
//++px;
}
//px += nextline;
}
}
img.UnlockBits(bmpdt);
return true;
}
The effect I get is like this( top image is before and bottom image is after):
Beside this, if I add that "if ((byte)px[ccl] == 1)" statement, there is no effect at all...