首页 > 学院 > 开发设计 > 正文

C#文档图片自动纠偏

2019-11-17 03:17:53
字体:
来源:转载
供稿:网友

C#文档图片自动纠偏

最近找到一个不错的文档图片自动纠偏跟大家分享一下。

纠偏算法:

  1 public class Deskew  2     {  3         // RePResentation of a line in the image.    4         private class HougLine  5         {  6             // Count of points in the line.  7             public int Count;  8             // Index in Matrix.  9             public int Index; 10             // The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d 11             public double Alpha; 12         } 13  14  15         // The Bitmap 16         public Bitmap _internalBmp; 17  18         // The range of angles to search for lines 19         const double ALPHA_START = -20; 20         const double ALPHA_STEP = 0.2; 21         const int STEPS = 40 * 5; 22         const double STEP = 1; 23  24         // Precalculation of sin and cos. 25         double[] _sinA; 26         double[] _cosA; 27  28         // Range of d 29         double _min; 30  31  32         int _count; 33         // Count of points that fit in a line. 34         int[] _hMatrix; 35  36         // Calculate the skew angle of the image cBmp. 37         public double GetSkewAngle() 38         { 39             // Hough Transformation 40             Calc(); 41  42             // Top 20 of the detected lines in the image. 43             HougLine[] hl = GetTop(20); 44  45             // Average angle of the lines 46             double sum = 0; 47             int count = 0; 48             for (int i = 0; i <= 19; i++) 49             { 50                 sum += hl[i].Alpha; 51                 count += 1; 52             } 53             return sum / count; 54         } 55  56         // Calculate the Count lines in the image with most points. 57         private HougLine[] GetTop(int count) 58         { 59             HougLine[] hl = new HougLine[count]; 60  61             for (int i = 0; i <= count - 1; i++) 62             { 63                 hl[i] = new HougLine(); 64             } 65             for (int i = 0; i <= _hMatrix.Length - 1; i++) 66             { 67                 if (_hMatrix[i] > hl[count - 1].Count) 68                 { 69                     hl[count - 1].Count = _hMatrix[i]; 70                     hl[count - 1].Index = i; 71                     int j = count - 1; 72                     while (j > 0 && hl[j].Count > hl[j - 1].Count) 73                     { 74                         HougLine tmp = hl[j]; 75                         hl[j] = hl[j - 1]; 76                         hl[j - 1] = tmp; 77                         j -= 1; 78                     } 79                 } 80             } 81  82             for (int i = 0; i <= count - 1; i++) 83             { 84                 int dIndex = hl[i].Index / STEPS; 85                 int alphaIndex = hl[i].Index - dIndex * STEPS; 86                 hl[i].Alpha = GetAlpha(alphaIndex); 87                 //hl[i].D = dIndex + _min; 88             } 89  90             return hl; 91         } 92  93  94         // Hough Transforamtion: 95         private void Calc() 96         { 97             int hMin = _internalBmp.Height / 4; 98             int hMax = _internalBmp.Height * 3 / 4; 99 100             Init();101             for (int y = hMin; y <= hMax; y++)102             {103                 for (int x = 1; x <= _internalBmp.Width - 2; x++)104                 {105                     // Only lower edges are considered.106                     if (IsBlack(x, y))107                     {108                         if (!IsBlack(x, y + 1))109                         {110                             Calc(x, y);111                         }112                     }113                 }114             }115         }116 117         // Calculate all lines through the point (x,y).118         private void Calc(int x, int y)119         {120             int alpha;121 122             for (alpha = 0; alpha <= STEPS - 1; alpha++)123             {124                 double d = y * _cosA[alpha] - x * _sinA[alpha];125                 int calculatedIndex = (int)CalcDIndex(d);126                 int index = calculatedIndex * STEPS + alpha;127                 try128                 {129                     _hMatrix[index] += 1;130                 }131                 catch (Exception ex)132                 {133                     System.Diagnostics.Debug.WriteLine(ex.ToString());134                 }135             }136         }137         private double CalcDIndex(double d)138         {139             return Convert.ToInt32(d - _min);140         }141         private bool IsBlack(int x, int y)142         {143             Color c = _internalBmp.GetPixel(x, y);144             double luminance = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114);145             return luminance < 140;146         }147 148         private void Init()149         {150             // Precalculation of sin and cos.151             _cosA = new double[STEPS];152             _sinA = new double[STEPS];153 154             for (int i = 0; i < STEPS; i++)155             {156                 double angle = GetAlpha(i) * Math.PI / 180.0;157                 _sinA[i] = Math.Sin(angle);158                 _cosA[i] = Math.Cos(angle);159             }160 161             // Range of d:            162             _min = -_internalBmp.Width;163             _count = (int)(2 * (_internalBmp.Width + _internalBmp.Height) / STEP);164             _hMatrix = new int[_count * STEPS];165 166         }167 168         private static double GetAlpha(int index)169         {170             return ALPHA_START + index * ALPHA_STEP;171         }172     }
View Code

自己写的调用方法

  1         public static void DeskewImage(string fileName, byte binarizeThreshold)  2         {  3             //打开图像  4             Bitmap bmp = OpenImage(fileName);  5   6             Deskew deskew = new Deskew();  7             Bitmap tempBmp = CropImage(bmp, bmp.Width / 4, bmp.Height / 4, bmp.Width / 2, bmp.Height / 2);  8             deskew._internalBmp = BinarizeImage(tempBmp, binarizeThreshold);  9             double angle = deskew.GetSkewAngle(); 10             bmp = RotateImage(bmp, (float)(-angle)); 11  12             //保存图像(需要再还原图片原本的位深度) 13             SaveImage(bmp, fileName); 14         } 15  16         /// <summary> 17         /// 图像剪切 18         /// </summary> 19         /// <param name="bmp"></param> 20         /// <param name="StartX"></param> 21         /// <param name="StartY"></param> 22         /// <param name="w"></param> 23         /// <param name="h"></param> 24         /// <returns></returns> 25         private static Bitmap CropImage(Bitmap bmp, int StartX, int StartY, int w, int h) 26         { 27             try 28             { 29                 Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format32bppArgb); 30  31                 Graphics g = Graphics.FromImage(bmpOut); 32                 g.DrawImage(bmp, new Rectangle(0, 0, w, h), new Rectangle(StartX, StartY, w, h), GraphicsUnit.Pixel); 33                 g.Dispose(); 34  35                 return bmpOut; 36             } 37             catch 38             { 39                 return null; 40             } 41         } 42  43  44         /// <summary> 45         /// 图像二值化 46         /// </s
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表