最近找到一个不错的文档图片自动纠偏跟大家分享一下。
纠偏算法:
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
新闻热点
疑难解答