zoukankan      html  css  js  c++  java
  • 模式识别开发之项目---身份证上面的数字识别

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Text;
    using System.Collections;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;

    namespace ReadNum_DividedByZeros_
    {
        class CBitmap
        {
            /**/
            /// <summary>
            /// 生成缩略图
            /// </summary>
            /// <param name="originalImagePath">源图路径(物理路径)</param>
            /// <param name="width">缩略图宽度</param>
            /// <param name="height">缩略图高度</param>

            public static Bitmap MakeThumbnail(string originalImagePath, int width, int height, int potx, int poty)
            {
                System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath);

                int towidth = width;
                int toheight = height;

                int x = potx;
                int y = poty;
                int ow = width;
                int oh = height;

                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(towidth, toheight); //Image=>Bitmap


                //新建一个画板
                System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);

                //设置高质量插值法
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

                //设置高质量,低速度呈现平滑程度
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                //清空画布并以透明背景色填充
                g.Clear(Color.Transparent);

                //在指定位置并且按指定大小绘制原图片的指定部分
                g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel);

                return bitmap;  // creative class Bitmap is here _Jiana
            }
        }


        /// <summary>
        /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// </summary>

        class UnCodebase
        {
            public Bitmap bmpobj;
            public UnCodebase(Bitmap pic)
            {
                bmpobj = new Bitmap(pic);    //转换为Format32bppRgb
            }

            /**/
            /// <summary>
            /// 根据RGB,计算灰度值
            /// </summary>
            /// <param name="posClr">Color值</param>
            /// <returns>灰度值,整型</returns>
            private int GetGrayNumColor(System.Drawing.Color posClr)
            {
                return (posClr.R * 19595 + posClr.G * 38469 + posClr.B * 7472) >> 16;
            }

            /**/
            /// <summary>
            /// 灰度转换,逐点方式
            /// </summary>
            public void GrayByPixels()
            {
                for (int i = 0; i < bmpobj.Height; i++)
                {
                    for (int j = 0; j < bmpobj.Width; j++)
                    {
                        int tmpValue = GetGrayNumColor(bmpobj.GetPixel(j, i));
                        bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue));
                    }
                }
            }

            /**/
            /// <summary>
            /// 去图形边框
            /// </summary>
            /// <param name="borderWidth"></param>
            public void ClearPicBorder(int borderWidth)
            {
                for (int i = 0; i < bmpobj.Height; i++)
                {
                    for (int j = 0; j < bmpobj.Width; j++)
                    {
                        if (i < borderWidth || j < borderWidth || j > bmpobj.Width - 1 - borderWidth || i > bmpobj.Height - 1 - borderWidth)
                            bmpobj.SetPixel(j, i, Color.FromArgb(255, 255, 255));
                    }
                }
            }

            /**/
            /// <summary>
            /// 灰度转换,逐行方式
            /// </summary>
            public void GrayByLine()
            {
                Rectangle rec = new Rectangle(0, 0, bmpobj.Width, bmpobj.Height);
                BitmapData bmpData = bmpobj.LockBits(rec, ImageLockMode.ReadWrite, bmpobj.PixelFormat);// PixelFormat.Format32bppPArgb);
                //    bmpData.PixelFormat = PixelFormat.Format24bppRgb;
                IntPtr scan0 = bmpData.Scan0;
                int len = bmpobj.Width * bmpobj.Height;
                int[] pixels = new int[len];
                Marshal.Copy(scan0, pixels, 0, len);

                //对图片进行处理
                int GrayValue = 0;
                for (int i = 0; i < len; i++)
                {
                    GrayValue = GetGrayNumColor(Color.FromArgb(pixels[i]));
                    pixels[i] = (byte)(Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb();      //Color转byte
                }

                bmpobj.UnlockBits(bmpData);
            }

            /**/
            /// <summary>
            /// 得到有效图形并调整为可平均分割的大小
            /// </summary>
            /// <param name="dgGrayValue">灰度背景分界值</param>
            /// <param name="CharsCount">有效字符数</param>
            /// <returns></returns>
            public void GetPicValidByValue(int dgGrayValue, int CharsCount)
            {
                int posx1 = bmpobj.Width; int posy1 = bmpobj.Height;
                int posx2 = 0; int posy2 = 0;
                for (int i = 0; i < bmpobj.Height; i++)      //找有效区
                {
                    for (int j = 0; j < bmpobj.Width; j++)
                    {
                        int pixelValue = bmpobj.GetPixel(j, i).R;
                        if (pixelValue < dgGrayValue)     //根据灰度值
                        {
                            if (posx1 > j) posx1 = j;
                            if (posy1 > i) posy1 = i;

                            if (posx2 < j) posx2 = j;
                            if (posy2 < i) posy2 = i;
                        };
                    };
                };
                // 确保能整除
                int Span = CharsCount - (posx2 - posx1 + 1) % CharsCount;   //可整除的差额数
                if (Span < CharsCount)
                {
                    int leftSpan = Span / 2;    //分配到左边的空列 ,如span为单数,则右边比左边大1
                    if (posx1 > leftSpan)
                        posx1 = posx1 - leftSpan;
                    if (posx2 + Span - leftSpan < bmpobj.Width)
                        posx2 = posx2 + Span - leftSpan;
                }
                //复制新图
                Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
                bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
            }

            /**/
            /// <summary>
            /// 得到有效图形,图形为类变量
            /// </summary>
            /// <param name="dgGrayValue">灰度背景分界值</param>
            /// <param name="CharsCount">有效字符数</param>
            /// <returns></returns>
            public void GetPicValidByValue(int dgGrayValue)
            {
                int posx1 = bmpobj.Width; int posy1 = bmpobj.Height;
                int posx2 = 0; int posy2 = 0;
                for (int i = 0; i < bmpobj.Height; i++)      //找有效区
                {
                    for (int j = 0; j < bmpobj.Width; j++)
                    {
                        int pixelValue = bmpobj.GetPixel(j, i).R;
                        if (pixelValue < dgGrayValue)     //根据灰度值
                        {
                            if (posx1 > j) posx1 = j;
                            if (posy1 > i) posy1 = i;

                            if (posx2 < j) posx2 = j;
                            if (posy2 < i) posy2 = i;
                        };
                    };
                };
                //复制新图
                Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
                bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
            }

            /**/
            /// <summary>
            /// 得到有效图形,图形由外面传入
            /// </summary>
            /// <param name="dgGrayValue">灰度背景分界值</param>
            /// <param name="CharsCount">有效字符数</param>
            /// <returns></returns>
            public Bitmap GetPicValidByValue(Bitmap singlepic, int dgGrayValue)
            {
                int posx1 = singlepic.Width; int posy1 = singlepic.Height;
                int posx2 = 0; int posy2 = 0;
                for (int i = 0; i < singlepic.Height; i++)      //找有效区
                {
                    for (int j = 0; j < singlepic.Width; j++)
                    {
                        int pixelValue = singlepic.GetPixel(j, i).R;
                        if (pixelValue < dgGrayValue)     //根据灰度值
                        {
                            if (posx1 > j) posx1 = j;
                            if (posy1 > i) posy1 = i;

                            if (posx2 < j) posx2 = j;
                            if (posy2 < i) posy2 = i;
                        };
                    };
                };
                //复制新图
                Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
                return singlepic.Clone(cloneRect, singlepic.PixelFormat);
            }

            /**/
            /// <summary>
            /// 平均分割图片
            /// </summary>
            /// <param name="RowNum">水平上分割数</param>
            /// <param name="ColNum">垂直上分割数</param>
            /// <returns>分割好的图片数组</returns>
            public Bitmap[] GetSplitPics(int RowNum, int ColNum)
            {
                if (RowNum == 0 || ColNum == 0)
                    return null;
                int singW = bmpobj.Width / RowNum;
                int singH = bmpobj.Height / ColNum;
                Bitmap[] PicArray = new Bitmap[RowNum * ColNum];

                Rectangle cloneRect;
                for (int i = 0; i < ColNum; i++)      //找有效区
                {
                    for (int j = 0; j < RowNum; j++)
                    {
                        cloneRect = new Rectangle(j * singW, i * singH, singW, singH);
                        PicArray[i * RowNum + j] = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);//复制小块图
                    }
                }
                return PicArray;
            }

            /**/
            /// <summary>
            /// 返回灰度图片的点阵描述字串,1表示灰点,0表示背景
            /// </summary>
            /// <param name="singlepic">灰度图</param>
            /// <param name="dgGrayValue">背前景灰色界限</param>
            /// <returns></returns>
            public string GetSingleBmpCode(Bitmap singlepic, int dgGrayValue)
            {
                Color piexl;
                string code = "";
                for (int posx = 0; posx < singlepic.Width; posx++)
                    for (int posy = 0; posy < singlepic.Height; posy++)
                    {
                        piexl = singlepic.GetPixel(posx, posy);
                        if (piexl.R < dgGrayValue)    // Color.Black )
                            code = code + "1";
                        else
                            code = code + "0";
                    }
                return code;
            }

            /* The function is used to divide picture by analysing zeros of pixel _Jiana */
            public string[] dividePic(string picPixel, int zerosLength)
            {
                string zeros = "";
                for (int i = 0; i < zerosLength; i++)
                {
                    zeros+='0';
                }
                string[] array = System.Text.RegularExpressions.Regex.Split(picPixel, zeros);
                return array;
            }

            /* The function is used to analyze the pixel's codes and conver them to number _Jiana*/
            public string analyzePixelC(string[] code,int drow)
            {
                long[] sum = new long[drow];
                for (int i = 0; i < drow; i++)
                {
                    for (int j = 0; j < code[i].Length; j++)
                    {
                        char num = code[i][j];
                        int a = (int)num - 48;
                        sum[i] += a;
                    }
                }

                char[] result = new char[drow];

                for (int i = 0; i < drow; i++)
                {
                    // Judge the number _Jiana
                    if (sum[i] >= 63 && sum[i] <= 69) { sum[i] = 66; } // 0
                    if (sum[i] >= 36 && sum[i] <= 38) { sum[i] = 37; } // 1
                    if (sum[i] >= 56 && sum[i] <= 58) { sum[i] = 57; } // 2
                    if (sum[i] >= 57 && sum[i] <= 59) { sum[i] = 58; } // 3
                    if (sum[i] >= 43 && sum[i] <= 45) { sum[i] = 44; } // 4
                    if (sum[i] >= 49 && sum[i] <= 51) { sum[i] = 50; } // 5
                    if (sum[i] >= 58 && sum[i] <= 60) { sum[i] = 59; } // 6
                    if (sum[i] >= 44 && sum[i] <= 46) { sum[i] = 45; } // 7
                    if (sum[i] >= 72 && sum[i] <= 78) { sum[i] = 75; } // 8 
                    if (sum[i] >= 63 && sum[i] <= 65) { sum[i] = 64; } // 9
                }

                for (int i = 0; i < drow; i++)
                {
                    switch (sum[i])
                    {
                        case 66: result[i] = '0'; break;
                        case 37: result[i] = '1'; break;
                        case 57: result[i] = '2'; break;
                        case 58: result[i] = '3'; break;
                        case 44: result[i] = '4'; break;
                        case 50: result[i] = '5'; break;
                        case 59: result[i] = '6'; break;
                        case 45: result[i] = '7'; break;
                        case 75: result[i] = '8'; break;
                        case 64: result[i] = '9'; break;
                        default: result[i] = ' '; break;
                    }
                }

                string returnResult = "";
                for (int i = 0; i < drow; i++)
                {
                    returnResult += result[i];
                }
                return returnResult;
            }
        }

        static class Program
        {
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                //Application.EnableVisualStyles();
                //Application.SetCompatibleTextRenderingDefault(false);
                //Application.Run(new Form1());
                Bitmap mBitmap = CBitmap.MakeThumbnail("E://license2.jpg", 250, 22, 163, 242);
                UnCodebase rgb = new UnCodebase(mBitmap);
                rgb.GrayByPixels();
                int drow = 1, dcol = 1;
                Bitmap[] pics = rgb.GetSplitPics(drow, dcol);
                string[] code = new string[drow];
                for (int i = 0; i < drow; i++)
                {
                    code[i] = rgb.GetSingleBmpCode(pics[i], 128);
                }


                // test: divide by zeros _Jiana
                string piecePic = "";
                int lastOne = 0;
                int flag1=0;
                for (int i = code[0].Length-1; i > 0; i--)
                {
                    if (code[0][i] != '0' && flag1 == 0)
                    {
                        flag1 = 1;
                        lastOne = i;
                    }
                }
                int flag2 = 0;
                for (int i = 0; i < lastOne; i++)
                {
                    if (code[0][i] != '0' && flag2 == 0)
                    {
                        flag2 = 1;
                    }
                    if (flag2 == 1)
                    {
                        piecePic += code[0][i];
                    }
                }

                string[] div = rgb.dividePic(piecePic, 98);
                string number = rgb.analyzePixelC(div, 18);

                System.Console.WriteLine("");
            }
        }
    }

     http://blog.csdn.net/liulina603/article/details/7945544

  • 相关阅读:
    _ 下划线 Underscores __init__
    Page not found (404) 不被Django的exception中间件捕捉 中间件
    从装修儿童房时的门锁说起
    欧拉定理 费马小定理的推广
    线性运算 非线性运算
    Optimistic concurrency control 死锁 悲观锁 乐观锁 自旋锁
    Avoiding Full Table Scans
    批量的单向的ssh 认证
    批量的单向的ssh 认证
    Corrupted MAC on input at /usr/local/perl/lib/site_perl/5.22.1/x86_64-linux/Net/SSH/Perl/Packet.pm l
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/3947171.html
Copyright © 2011-2022 走看看