The identification of c#Authentication Code is mainly divided into three steps: preprocessing, segmentation and recognition.
First I download the verification code from the website
The results are as follows:
1. Picture preprocessing, that is, binary pictures
*Sets the gray value of the pixel point on the image to 0 or 255.
The principle is as follows:
The code is as follows:
#region Binary Picture /// <summary> ///Binary Picture ///is to set the gray value of the pixel point on the image to 0 or 255 /// </summary> /// <returns>Authentication code after processing </returns> public Bitmap BinaryZaTion() { for (int x = 0; x < img.Width; x++) { for (int y = 0; y < img.Height; y++) { __c = img.GetPixel(x, y); //Gray value int __tc = (__c.R + __c.G + __c.B) / 3; //Greater than Que Black if (__tc > t) { img.SetPixel(x, y, Color.FromArgb(__c.A, b, b, b)); //Black dots add themselves __blackNum++; } //Greater than Que White else { img.SetPixel(x, y, Color.FromArgb(__c.A, w, w, w)); } } } return img; } #endregion
After binarization, you need to determine the black-to-white ratio of the picture. If there is more black than white, you need to reverse the color of the picture.
The code is as follows:
#Whether region needs inversion /// <summary> ///Need Inversion /// </summary> /// <returns>Need backcolor </returns> public bool IsNeedInverseColor() { if ((__blackNum * 1.0 / (img.Width * img.Height)) > 0.5) { return true; } else { return false; } } #endregion #region Inversion /// <summary> ///Inverse color /// </summary> /// <returns>Authentication code after processing </returns> public Bitmap InverseColor() { for (int x = 0; x < img.Width; x++) { for (int y = 0; y < img.Height; y++) { __c = img.GetPixel(x, y); img.SetPixel(x, y, Color.FromArgb(__c.A, w - __c.R, w - __c.G, w - __c.B)); } } return img; } #endregion
The results are as follows:
2. Picture segmentation
My practice is to first determine if each vertical line is a pure white line, not record the current x-coordinate, and then not horizontally determine if it is a pure white line, so you can go to the area of each number and draw the area.
The code is as follows:
#region Split Picture /// <summary> ///Split Picture /// </summary> /// <returns>Authentication code after processing </returns> public Bitmap CutImg() { //Y-axis Split CutY(); //Number of Areas __count = 0; if (XList.Count > 1) { //x Start Value int __start = XList[0]; //x end value int __end = XList[XList.Count - 1]; //x index int __idx = 0; while (__start != __end) { //Area Width int __w = __start; //Number of Areas Added __count++; while (XList.Contains(__w) && __idx < XList.Count) { //Area Width Adds __w++; //x-index self-addition __idx++; } //Area X-axis coordinates int x = __start; //Area Y-axis coordinates int y = 0; //Area Width int width = __w - __start; //Area Height int height = img.Height; /* * X Axis Split Current Area */ CutX(img.Clone(new Rectangle(x, y, width, height), img.PixelFormat)); if (YList.Count > 1 && YList.Count != img.Height) { int y1 = YList[0]; int y2 = YList[YList.Count - 1]; if (y1 != 1) { y = y1 - 1; } height = y2 - y1 + 1; } //GDI+Drawing Objects Graphics g = Graphics.FromImage(img); g.SmoothingMode = SmoothingMode.HighQuality; g.CompositingMode = CompositingMode.SourceOver; g.PixelOffsetMode = PixelOffsetMode.HighSpeed; g.InterpolationMode = InterpolationMode.HighQualityBicubic; //Draw Authentication Code Area g.DrawRectangle(new Pen(Brushes.Green), new Rectangle(x, y, width, height)); g.Dispose(); //Start value points to next group if (__idx < XList.Count) { __start = XList[__idx]; } else { __start = __end; } } } return img; } #endregion #region Y-axis Character Split Picture /// <summary> ///Get Y-Axis Split Points ///Determine if each vertical line is black ///or add /// </summary> /// <param name="img">Picture to verify </param> private void CutY() { XList.Clear(); for (int x = 0; x < img.Width; x++) { isWhilteLine = false; for (int y = 0; y < img.Height; y++) { __c = img.GetPixel(x, y); if (__c.R == w) { isWhilteLine = true; } else { isWhilteLine = false; break; } } if (!isWhilteLine) { XList.Add(x); } } } #endregion #region X-axis Character Split Picture /// <summary> ///Get X-Axis Split Points ///Determine if each line is black ///or add /// </summary> /// <param name="tempImg">Temporary area</param> private void CutX(Bitmap tempImg) { YList.Clear(); for (int x = 0; x < tempImg.Height; x++) { isWhilteLine = false; for (int y = 0; y < tempImg.Width; y++) { __c = tempImg.GetPixel(y, x); if (__c.R == w) { isWhilteLine = true; } else { isWhilteLine = false; break; } } if (!isWhilteLine) { YList.Add(x); } } tempImg.Dispose(); } #endregion
The results are as follows:
3. Identify
Recognition is extracting the features of a picture
My approach is to divide the digital area of the picture into 4*4 areas one by one, calculate the percentage of black dots in each area, and then compare the calculated results with the previously calculated features to find the minimum Euclidean distance d = sqrt ((x1-x2)^2+ (y1-y2)^2) as the result.
Part of the code is as follows:
#region Black Pixel Ratio Column /// <summary> ///Calculate black pixel ratio column /// </summary> /// <param name="tempimg"></param> /// <returns></returns> private double PixlPercent(Bitmap tempimg) { int temp = 0; int w_h = tempimg.Width * tempimg.Height; for (int x = 0; x < tempimg.Width; x++) { for (int y = 0; y < tempimg.Height; y++) { __c = tempimg.GetPixel(x, y); if (__c.R == b) { temp++; } } } tempimg.Dispose(); double result = temp * 1.0 / w_h; result = result.ToString().Length > 3 ? Convert.ToDouble(result.ToString().Substring(0, 3)) : result; return result; } #endregion
The results are as follows:
This code is for research purposes only.
Novice on the road, contact pigkeli@qq.com for any suggestions or comments.
Reprinted at: https://www.cnblogs.com/riasky/p/3473365.html