1. 程式人生 > >中國知網(CNKI)驗證碼識別

中國知網(CNKI)驗證碼識別

中國知網(CNKI)是最重要的中文學術資源資料庫,收錄絕大多數中文學術刊物。我們可以檢索論文,也可以匯出檢索結果前6000條論文的題錄資料。

在CNKI檢索結果翻頁10次以上,使用者需要手動輸入驗證碼才能繼續。為了實現自動化題錄資料匯出,我們就需要通過程式識別驗證碼。最終,基於Eugu.CV實現驗證碼識別,正確率在70%以上,能保證自動化匯出過程的連貫。

CNKI驗證碼識別主要分為四個步驟:

1 去掉灰色干擾線

2 去掉干擾點

3 二值化

4 基於Tesseract識別 

 CNKI驗證碼是長這個樣子。

首先,要去掉驗證碼圖片的灰色干擾線,如圖:

去掉干擾線的思路:干擾線都是灰色,而灰色的RGB三色的值相對來說都比較大,所以將RGB三色值均大於150的點的顏色設定成白色。程式碼如下:

            Bitmap bmp = (Bitmap)Image.FromFile(imagePath);

            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    Color color = bmp.GetPixel(i, j);
                    int threshold = 150;
                    if (color.R > threshold && color.G > threshold && color.B > threshold)
                    {
                        Color newColor = Color.FromArgb(255, 255, 255);
                        bmp.SetPixel(i, j, newColor);
                    }
                }
            }

然後,去掉干擾點,如圖:

去掉干擾點的思路很簡單,遍歷每個點,如果它上下左右8個鄰居點,有6個以上是白色的點,就把這個點也設定成白色。

            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    var colorList = GetColorList(bmp, i, j);

                    var count = colorList.Count(x => x.R == 255 && x.G == 255 && x.B == 255);

                    if (count >= 6)
                    {
                        bmp.SetPixel(i, j, Color.FromArgb(255, 255, 255));
                    }
                }
            }

圖片識別前需要二值化,也就是把圖片變成黑白兩色,即把所有的點都變成黑色。

Eugu.CV提供了二值化的方法。

           var gray = new Image<Gray, Byte>(bmp);
            var image = gray.CopyBlank();
            CvInvoke.Threshold(gray, image, 120, 255, ThresholdType.Triangle);

最後,就是用Eugu.CV整合的Tesseract-OCR識別二值化圖片。

Tesseract是非常強大的OCR開源庫,Eumu.CV集成了Tesseract 4.0,可以用lstm識別模式提供識別效率。

            Emgu.CV.OCR.Tesseract ocr = new Emgu.CV.OCR.Tesseract(path, "eng", Emgu.CV.OCR.OcrEngineMode.LstmOnly, whitelist, true);
ocr.PageSegMode = Emgu.CV.OCR.PageSegMode.SingleLine;
var gray = new Image<Gray, Byte>(image);
ocr.SetImage(gray);
if (ocr.Recognize() != 0) throw new Exception("Failed to recognizer image"); var list = ocr.GetCharacters().Select(x => x.Text); textBox.Text = string.Join("", list);

 

如果你對識別結果的精確度不夠滿意,還可以通過Tesseract自己訓練提高識別精