距離上次寫博客又很長(zhǎng)時(shí)間了,這個(gè)驗(yàn)證碼識(shí)別模塊其實(shí)自己早寫出來(lái)就是懶的寫博客,現(xiàn)在離職了有時(shí)間把它拿出來(lái)。 總體說(shuō)來(lái)這個(gè)驗(yàn)證碼還是有一定難度的:字母數(shù)量不固定、位置不固定、帶傾斜角度、帶粘連、有噪點(diǎn)和干擾線。所以識(shí)別率還是比較低的,有個(gè)十分之一吧,但是識(shí)別出來(lái)就可以了,反正是軟件識(shí)別,又不是人識(shí)別。這個(gè)驗(yàn)證碼識(shí)別模塊是專門針對(duì)此類驗(yàn)證碼優(yōu)化的,所以如果想識(shí)別其他驗(yàn)證碼估計(jì)稍改一下源碼就行。
源代碼
首先看界面:

界面有很多按鈕,我按照順序說(shuō)一下,其實(shí)就是識(shí)別的順序
1、獲取驗(yàn)證碼(動(dòng)態(tài)從某網(wǎng)址獲取)
2、去背景
3、去干擾
4、二值化
5、分割
6、識(shí)別
7、如果識(shí)別錯(cuò)誤,同時(shí)某字母有識(shí)別的價(jià)值,就對(duì)應(yīng)分割字母的順序找到下面對(duì)應(yīng)的框填上正確的字母,然后點(diǎn)擊學(xué)習(xí)。下次再出現(xiàn)類似字母就可以正確識(shí)別了。

比如這次識(shí)別h錯(cuò)誤,那就可以在對(duì)應(yīng)的框中填寫h然后點(diǎn)擊學(xué)習(xí)。但是這個(gè) h字母左上角有個(gè)黑色干擾塊,沒(méi)有學(xué)習(xí)的價(jià)值。
下面貼上一些源代碼,大家也可以點(diǎn)擊上面的鏈接下載源代碼查看,注意不能刪除Debug下的Sample文件夾。代碼里面都有注釋:
1、去背景代碼:
原理:把圖片中顏色數(shù)量最多的一部分看成背景并替換為白色,相當(dāng)于去除背景。
1 /// <summary> 2 /// 去背景 3 /// 把圖片中最多的一部分顏色視為背景色 選出來(lái)后替換為白色 4 /// </summary> 5 /// <param name="sender"></param> 6 /// <param name="e"></param> 7 PRivate void btnDropBG_Click(object sender, EventArgs e) 8 { 9 if (picbox.Image == null)10 {11 return;12 }13 Bitmap img = new Bitmap(picbox.Image);14 //key 顏色 value顏色對(duì)應(yīng)的數(shù)量15 Dictionary<Color, int> colorDic = new Dictionary<Color, int>();16 //獲取圖片中每個(gè)顏色的數(shù)量17 for (var x = 0; x < img.Width; x++)18 {19 for (var y = 0; y < img.Height; y++)20 {21 //刪除邊框22 if (y == 0 || y == img.Height)23 {24 img.SetPixel(x, y, Color.White);25 }26 27 var color = img.GetPixel(x, y);28 var colorRGB = color.ToArgb();29 30 if (colorDic.ContainsKey(color))31 {32 colorDic[color] = colorDic[color] + 1;33 }34 else35 {36 colorDic[color] = 1;37 }38 }39 }40 //圖片中最多的顏色41 Color maxColor = colorDic.OrderByDescending(o => o.Value).FirstOrDefault().Key;42 //圖片中最少的顏色43 Color minColor = colorDic.OrderBy(o => o.Value).FirstOrDefault().Key;44 45 Dictionary<int[], double> maxColorDifDic = new Dictionary<int[], double>();46 //查找 maxColor 最接近顏色47 for (var x = 0; x < img.Width; x++)48 {49 for (var y = 0; y < img.Height; y++)50 {51 maxColorDifDic.Add(new int[] { x, y }, GetColorDif(img.GetPixel(x, y), maxColor));52 }53 }54 //去掉和maxColor接近的顏色 即 替換成白色55 var maxColorDifList = maxColorDifDic.OrderBy(o => o.Value).Where(o => o.Value < bjfz).ToArray();56 foreach (var kv in maxColorDifList)57 {58 img.SetPixel(kv.Key[0], kv.Key[1], Color.White);59 }60 picbox.Image = img;61 pbNormal.Image = picbox.Image;62 }
2、去干擾代碼、
原理:如果一個(gè)像素和周圍上下左右四個(gè)像素點(diǎn)中的兩面或三面顏色差別都很大,則認(rèn)為這個(gè)點(diǎn)是噪點(diǎn)或干擾線。看到網(wǎng)上資料中有用中值濾波算法的,但是效果不好。
1 /// <summary> 2 /// 去干擾 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void btnDropDisturb_Click(object sender, EventArgs e) 7 { 8 if (picbox.Image == null) 9 { 10 return; 11 } 12 Bitmap img = new Bitmap(picbox.Image); 13 byte[] p = new byte[9]; //最小處理窗口3*3 14 byte s; 15 //去干擾線 16 for (var x = 0; x < img.Width; x++) 17 { 18 for (var y = 0; y < img.Height; y++) 19 { 20 Color currentColor = img.GetPixel(x, y); 21 int color = currentColor.ToArgb(); 22 23 if (x > 0 && y > 0 && x < img.Width - 1 && y < img.Height - 1) 24 { 25 #region 中值濾波效果不好 26 ////取9個(gè)點(diǎn)的值 27 //p[0] = img.GetPixel(x - 1, y - 1).R; 28 //p[1] = img.GetPixel(x, y - 1).R; 29 //p[2] = img.GetPixel(x + 1, y - 1).R; 30 //p[3] = img.GetPixel(x - 1, y).R; 31 //p[4] = img.GetPixel(x, y).R; 32 //p[5] = img.GetPixel(x + 1, y).R; 33 //p[6] = img.GetPixel(x - 1, y + 1).R; 34 //p[7] = img.GetPixel(x, y + 1).R; 35 //p[8] = img.GetPixel(x + 1, y + 1).R; 36 ////計(jì)算中值 37 //for (int j = 0; j < 5; j++) 38 //{ 39 // for (int i = j + 1; i < 9; i++) 40 // { 41 // if (p[j] > p[i]) 42 // { 43 // s = p[j]; 44 // p[j] = p[i]; 45 // p[i] = s; 46 // } 47 // } 48 //} 49 //// if (img.GetPixel(x, y).R < dgGrayValue) 50 //img.SetPixel(x, y, Color.FromArgb(p[4], p[4], p[4])); //給有效值付中值 51 #endregion 52 53 //上 x y+1 54 double upDif = GetColorDif(currentColor, img.GetPixel(x, y + 1)); 55 //下 x y-1 56 double downDif = GetColorDif(currentColor, img.GetPixel(x, y - 1)); 57 //左 x-1 y 58 double leftDif = GetColorDif(currentColor, img.GetPixel(x - 1, y)); 59 //右 x+1 y 60 double rightDif = GetColorDif(currentColor, img.GetPixel(x + 1, y)); 61 //左上 62 double upLeftDif = GetColorDif(currentColor, img.GetPixel(x - 1, y + 1)); 63 //右上 64 double upRightDif = GetColorDif(currentColor, img.GetPixel(x + 1, y + 1)); 65 //左下 66 double downLeftDif = GetColorDif(currentColor, img.GetPixel(x - 1, y - 1)); 67 //右下 68 double downRightDif = GetColorDif(currentColor, img.GetPixel(x + 1, y - 1)); 69 70 ////四面色差較大 71 //if (upDif > threshold && downDif > threshold && leftDif > threshold && rightDif > threshold) 72 //{ 73 // img.SetPixel(x, y, Color.White); 74 //} 75 //三面色差較大 76 if ((upDif > threshold && downDif > threshold && leftDif > threshold) 77 || (downDif > threshold && leftDif > threshold && rightDif > threshold) 78 || (upDif > threshold && leftDif > threshold && rightDif > threshold) 79 || (upDif > threshold && downDif > threshold && rightDif > threshold)) 80 { 81 img.SetPixel(x, y, Color.White); 82 } 83 84 List<int[]> xLine = new List<int[]>(); 85 //去橫向干擾線 原理 如果這個(gè)點(diǎn)上下有很多白色像素則認(rèn)為是干擾 86 for (var x1 = x + 1; x1 < x + 10; x1++) 87 { 88 if (x1
|
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注