[c#]圖片二值化初探
阿新 • • 發佈:2018-12-10
0.序言
研究文字識別遇到二值化問題,看了看原理,覺得好玩,就試了試,沒有參考成熟的方法,完全是自學研究,由於用到了灰度閾值矩陣,就暫時叫做矩陣法二值化。基本步驟:讀取源圖片->生成灰度圖->計算灰度圖灰度閾值矩陣->利用灰度閾值矩陣生成二值化圖。
生成灰度圖: 圖片二值化:
1.程式基本程式碼
1.1.圖片灰度化
public static unsafe Bitmap Img2Gray(Bitmap curBitmap) { int width = curBitmap.Width; int height = curBitmap.Height; Bitmap back = new Bitmap(width, height); byte temp; Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); //這種速度最快 BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);//24位rgb顯示一個畫素,即一個畫素點3個位元組,每個位元組是BGR分量。Format32bppRgb是用4個位元組表示一個畫素 byte* ptr = (byte*)(bmpData.Scan0); for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { //ptr[2]為r值,ptr[1]為g值,ptr[0]為b值 temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]); back.SetPixel(i, j, Color.FromArgb(temp, temp, temp)); ptr += 3; //Format24bppRgb格式每個畫素佔3位元組 } ptr += bmpData.Stride - bmpData.Width * 3;//每行讀取到最後“有用”資料時,跳過未使用空間XX } curBitmap.UnlockBits(bmpData); return back; }
1.2.灰度閾值矩陣位置索引計算(Sensibility為全域性變數,為灰度閾值矩陣大小,值越大,閾值矩陣越大,圖片分割槽越多,但是速度越慢)
public int GetIndex(int location, int length)
{
return location * Sensibility / length;
}
1.3.灰度圖二值化處理
public Bitmap Gray2Binaryzation(Bitmap GrayImg) { int width = GrayImg.Width; int height = GrayImg.Height; Bitmap back = new Bitmap(width, height); //灰度矩陣初始化 Int64[,] GrayScale = new Int64[Sensibility, Sensibility]; for (int i = 0; i < Sensibility; i++) { for (int j = 0; j < Sensibility; j++) { GrayScale[i,j] = 0; } } //計算灰度矩陣閾值,17/20為閾值調整,取0.85時效果最好; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { GrayScale[GetIndex(i, width), GetIndex(j, height)] += GrayImg.GetPixel(i, j).R; } } for (int i = 0; i < Sensibility; i++) { for (int j = 0; j < Sensibility; j++) { GrayScale[i, j] = GrayScale[i, j] / width * Sensibility / height * Sensibility * 17 / 20; } } //二值化賦值,大於灰度矩陣閾值的描黑,否則描白。 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (GrayImg.GetPixel(i, j).R >= GrayScale[GetIndex(i, width), GetIndex(j, height)]) back.SetPixel(i, j, Color.FromArgb(255, 255, 255)); else back.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } return back; }