Im implementing my own function to binarize fingerprint images. In my method i try to work with LockBits
for the first time.
Could you explain me, why i get a lot of artefacts on my images? Eample:
On the left picture i binarize image by Get/SetPixel
and it is working pretty ok, but why i cant get same good result on the right image (a lot of red dots)? Did i forget or dont know about something?
private Bitmap Binarization(Bitmap tempBmp)
{
int threshold = otsuValue(tempBmp); //calculating threshold with Otsu method
unsafe
{
BitmapData bmpData = tempBmp.LockBits(new System.Drawing.Rectangle(0, 0, tempBmp.Width, tempBmp.Height), ImageLockMode.ReadWrite, tempBmp.PixelFormat);
byte* ptr = (byte*)bmpData.Scan0;
int height = tempBmp.Height;
int width = bmpData.Width * 4;
Parallel.For(0, height, y =>
{
byte* offset = ptr + (y * bmpData.Stride); //set row
for (int x = 0; x < width; x = x + 4)
{
//changing pixel value
offset[x] = offset[x] > threshold ? Byte.MaxValue : Byte.MinValue;
offset[x+1] = offset[x+1] > threshold ? Byte.MaxValue : Byte.MinValue;
offset[x+2] = offset[x+2] > threshold ? Byte.MaxValue : Byte.MinValue;
offset[x+3] = offset[x+3] > threshold ? Byte.MaxValue : Byte.MinValue;
}
});
tempBmp.UnlockBits(bmpData);
}
return tempBmp;
}
The same history, when i want to cut a little of bytes from image, but problem looks a little more complex.
Why it dont even get into good "if" statemant?
private Bitmap Binarization(Bitmap tempBmp)
{
int threshold = otsuValue(tempBmp);
unsafe
{
BitmapData bmpData = tempBmp.LockBits(new System.Drawing.Rectangle(0, 0, tempBmp.Width, tempBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
//Format8bpp, not pixel format from image
byte* ptr = (byte*)bmpData.Scan0;
int height = tempBmp.Height;
int width = bmpData.Width; //i cut "* 4" here because of one channel image
Parallel.For(0, height, y =>
{
byte* offset = ptr + (y * bmpData.Stride); //set row
for (int x = 0; x < width; x++)
{
//changing pixel values
offset[x] = offset[x] > threshold ? Byte.MaxValue : Byte.MinValue;
}
});
tempBmp.UnlockBits(bmpData);
}
return tempBmp;
}
Thanks for any advices for improve my functions.
1) The algorithm you use does not guarantee a b/w result.
You are testing the RGB channels separately, so if
R > threshold
butG or B < threshold
it will be turned on butG and/or B
not etc..In fact the real question is why not a lot more artifacts come up. Must have to do with the source image.
Solution: Add all three channels and compare to threshold * 3; then set all to the same black or white value!
2) There is another issue: The code you copied from somewhere blindly assumes the image has 32 bpp. But whiile the image you posted is a
png
it still only has 24 bpp. Therefore your code will do all sorts of funny things..Updated and corrected example: