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

  • 相关阅读:
    视频上云解决方案EasyCVR支持接入海康SDK吗?
    视频上云网关EasyCVR程序数据库内数据会丢失吗?
    视频上云解决方案EasyCVR打包软件在linux下解压后台无法运行问题排查
    视频上云解决方案EasyCVR发布linux版本
    视频流媒体平台EasyNVR使用Vue.js开发报[Vue warn]错误问题解决方案
    监控现场无固定IP及公有云服务器如何通过手机查看视频直播?
    幼儿园EasyNVR能力层安防监控平台调用视频直播流报404错误解决方案
    海康NVR的RTSP视频流能否在EasyNVR流媒体平台中正常播放?
    视频云端流媒体平台EasyNVR存储的录像为什么呈现每小时一段录像?
    如何查看EasyNTS智能云组网硬件终端内的资源使用情况?
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/3947171.html
Copyright © 2011-2022 走看看