最近要寫一個條碼識別的程式,在CodeProject上得到一些代碼能夠識別基本的Code39碼,但是它需要二值化的黑白映像,而由於其他原因,我們的原圖只能是彩色或者是灰階圖,所以需要一個轉換。
二值化有很多演算法,我沒有去研究。步驟如下:
1. 首先灰階化,簡單把三色相加除以3
2. 二值化,將一個點周圍8個點全部相加,除以9 ,然後根據一個閥值決定是黑還是白,我用160
3. 一定要用LockBit,直接處理映像資料,速度才能快
代碼如下:
int n = 3;
/// <summary>
/// 轉化普通映像到2值映像
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
Bitmap ConvertImageTo2Value(Bitmap bmp)
{
int w = bmp.Width;
int h = bmp.Height;
BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
unsafe
{
// 將原始圖片變成灰階二位元組
byte* p = (byte*)data.Scan0;
byte[,] vSource = new byte[w, h];
int offset = data.Stride - w * n;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
vSource[x, y] = (byte)(((int)p[0] + (int)p[1] + (int)p[2]) / 3);
p += n;
}
p += offset;
}
bmp.UnlockBits(data);
// 將灰階二位元組變成二值映像
Bitmap bmpDest = new Bitmap(w, h, PixelFormat.Format24bppRgb);
BitmapData dataDest = bmpDest.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly,
PixelFormat.Format24bppRgb);
p = (byte*)dataDest.Scan0;
offset = dataDest.Stride - w * n;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
//p[0] = p[1] = p[2] = (int)vSource[x, y] > 160 ? (byte)255 : (byte)0;
p[0] = p[1] = p[2] = (int)GetAverageColor(vSource, x, y, w, h) > 120 ? (byte)255 : (byte)0;
p += n;
}
p += offset;
}
bmpDest.UnlockBits(dataDest);
// return
return bmpDest;
}
}
byte GetAverageColor(byte[,] vSource, int x, int y, int w, int h)
{
int rs = vSource[x, y]
+ (x == 0 ? 255 : (int)vSource[x - 1, y])
+ (x == 0 || y == 0 ? 255 : (int)vSource[x - 1, y - 1])
+ (x == 0 || y == h - 1 ? 255 : (int)vSource[x - 1, y + 1])
+ (y == 0 ? 255 : (int)vSource[x, y - 1])
+ (y == h - 1 ? 255 : (int)vSource[x, y + 1])
+ (x == w - 1 ? 255 : (int)vSource[x + 1, y])
+ (x == w - 1 || y == 0 ? 255 : (int)vSource[x + 1, y - 1])
+ (x == w - 1 || y == h - 1 ? 255 : (int)vSource[x + 1, y + 1]);
return (byte)(rs / 9);
}
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/ssdjmcj8048/archive/2007/09/19/1790895.aspx