/// <summary> /// 切割图片 X坐标 /// </summary> /// <param name="x">图片</param> /// <param name="s">X开始坐标</param> /// <param name="e">X结束坐标</param> /// <returns></returns> public static EffImage CutH(EffImage x, int s, int e) { if (e - s <= 0) { return(null); } if (s > 1) { s -= 1; } if (e < x.Width - 1) { e += 1; } EffImage rt = White(e - s, x.Height); for (int i = s; i < e; i++) { for (int j = 0; j < x.Height; j++) { rt.Set(i - s, j, x.At(i, j)); } } return(rt); }
/// <summary> /// EffImage填充边距 /// </summary> /// <param name="src">源图</param> /// <param name="w">目标宽</param> /// <param name="h">目标高</param> /// <returns></returns> public static EffImage Padding(EffImage src, int w, int h) { using (var bmp = src.Origin) { return(new EffImage(Padding(bmp, w, h))); } }
/// <summary> /// Y方向切割图片 /// </summary> /// <param name="x"></param> /// <param name="s"></param> /// <param name="e"></param> /// <returns></returns> public static EffImage CutV(EffImage x, int s, int e) { if (e - s <= 0) { return(null); } if (s > 1) { s -= 1; } if (e < x.Height - 1) { e += 1; } EffImage rt = White(x.Width, e - s); for (int j = s; j < e; j++) { for (int i = 0; i < x.Width; i++) { rt.Set(i, j - s, x.At(i, j)); } } return(rt); }
public object Clone() { var img = EffImage.White(Width, Height); img.pixels = this.pixels.Clone() as Color[, ]; return(img); }
/// <summary> /// 旋转图片 /// </summary> /// <param name="degree">度数</param> /// <returns></returns> public EffImage Rotate(int degree) { EffImage rtImg = White(Width, Height); var org = CutV(CutH(this, Left, Right), Top, Bottom); var bmp = org.Origin; var rwid = (org.width + org.height) * 2; Bitmap r = new Bitmap(rwid, rwid); Graphics g = Graphics.FromImage(r); g.Clear(Color.White); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; g.RotateTransform(degree); g.DrawImage(bmp, new Point((rwid / 2) - (org.width / 2), (rwid / 2) - (org.height / 2))); return(new EffImage(r).ValidArea); }
/// <summary> /// 位图填充 /// </summary> /// <param name="src">原图</param> /// <param name="w">目标宽</param> /// <param name="h">目标高</param> /// <returns></returns> public static Bitmap Padding(Bitmap src, int w, int h) { var eimg = new EffImage(src); Bitmap rt = new Bitmap(w, h); Graphics g = Graphics.FromImage(rt); g.Clear(Color.White); int left = eimg.Left; int right = eimg.Right; int top = eimg.Top; int bot = eimg.Bottom; int pwid = right - left; int phei = bot - top; int padleft = (w - pwid) / 2 - 1; int padright = (h - phei) / 2 - 1; var sr = CutV(CutH(eimg, left, right), top, bot); g.DrawImage(sr.Origin, new Point(padleft, padright)); g.Dispose(); return(rt); }
/// <summary> /// 某论文上的细化算法OpenCV改EffImage版 /// </summary> /// <param name="iter"></param> private static void thiniter(byte iter, EffImage img) { int convertColor(Color c) { return(c.R < 100 ? 1 : 0); } for (int i = 1; i < img.Width - 1; i++) { for (int j = 1; j < img.Height - 1; j++) { int p2 = convertColor(img.At(i - 1, j)); int p3 = convertColor(img.At(i - 1, j + 1)); int p4 = convertColor(img.At(i, j + 1)); int p5 = convertColor(img.At(i + 1, j + 1)); int p6 = convertColor(img.At(i + 1, j)); int p7 = convertColor(img.At(i + 1, j - 1)); int p8 = convertColor(img.At(i, j - 1)); int p9 = convertColor(img.At(i - 1, j - 1)); int A = Convert.ToInt32((p2 == 0 && p3 == 1)) + Convert.ToInt32((p3 == 0 && p4 == 1)) + Convert.ToInt32((p4 == 0 && p5 == 1)) + Convert.ToInt32((p5 == 0 && p6 == 1)) + Convert.ToInt32((p6 == 0 && p7 == 1)) + Convert.ToInt32((p7 == 0 && p8 == 1)) + Convert.ToInt32((p8 == 0 && p9 == 1)) + Convert.ToInt32((p9 == 0 && p2 == 1)); int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8); int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8); if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) { img.Set(i, j, Color.White); } } } }
/// <summary> /// 缩放 /// </summary> /// <param name="img"></param> /// <param name="w">目标宽</param> /// <param name="h">目标高</param> /// <param name="keepRatio">是否保持原始比例</param> /// <returns></returns> public static EffImage Resize(EffImage img, int w, int h, bool keepRatio = true) { Bitmap bmp = new Bitmap(w, h); Graphics g = Graphics.FromImage(bmp); g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; g.Clear(Color.White); var src = img.Origin; var dstRect = new Rectangle(0, 0, w, h); var srcRect = new Rectangle(0, 0, img.width, img.height); // 保持原始比例 if (keepRatio) { var wRatio = (double)img.width / (double)w; var hRatio = (double)img.height / (double)h; // 选一个 var r = Math.Max(wRatio, hRatio); var dstW = img.width / r; var dstH = img.height / r; var padL = (w - dstW) / 2; var padT = (h - dstH) / 2; dstRect = new Rectangle((int)padL, (int)padT, (int)dstW, (int)dstH); } g.DrawImage(src, dstRect, srcRect, GraphicsUnit.Pixel); var rt = new EffImage(bmp); g.Flush(); g.Dispose(); src.Dispose(); bmp.Dispose(); return(rt); }
/// <summary> /// 去掉杂点(适合杂点/杂线粗为1) /// NOTE: 没什么用 /// </summary> public static void ClearNoise(this EffImage img, int MaxNearPoints) { Color piexl; int nearDots = 0; int dgGrayValue = 50; // int XSpan, YSpan, tmpX, tmpY; //逐点判断 for (int i = 0; i < img.Width; i++) { for (int j = 0; j < img.Height; j++) { piexl = img.At(i, j); if (piexl.R < dgGrayValue) { nearDots = 0; //判断周围8个点是否全为空 if (i == 0 || i == img.Width - 1 || j == 0 || j == img.Height - 1) //边框全去掉 { img.Set(i, j, Color.FromArgb(255, 255, 255)); } else { if (img.At(i - 1, j - 1).R < dgGrayValue) { nearDots++; } if (img.At(i, j - 1).R < dgGrayValue) { nearDots += 2; } if (img.At(i + 1, j - 1).R < dgGrayValue) { nearDots += 2; } if (img.At(i - 1, j).R < dgGrayValue) { nearDots++; } if (img.At(i + 1, j).R < dgGrayValue) { nearDots++; } if (img.At(i - 1, j + 1).R < dgGrayValue) { nearDots += 2; } if (img.At(i, j + 1).R < dgGrayValue) { nearDots += 2; } if (img.At(i + 1, j + 1).R < dgGrayValue) { nearDots += 2; } } if (nearDots < MaxNearPoints) { img.Set(i, j, Color.FromArgb(255, 255, 255)); //去掉单点 && 粗细小3邻边点 } } else //背景 { img.Set(i, j, Color.FromArgb(255, 255, 255)); } } } }
/// <summary> /// 边缘提取 /// </summary> public static void Contouring(this EffImage image) { image.ConvolutionFilter(Laplacian3x3, 1, 0); }
/// <summary> /// 细化 /// </summary> public static void Thining(this EffImage image) { thiniter(0, image); thiniter(1, image); }
/// <summary> /// 卷积运算 /// </summary> /// <param name="filterMatrix">矩阵</param> /// <param name="factor">因子</param> /// <param name="bias">偏移</param> public void ConvolutionFilter(double[,] filterMatrix, double factor = 1, int bias = 0) { EffImage rt = EffImage.White(width, height); double blue = 0.0; double green = 0.0; double red = 0.0; int filterWidth = filterMatrix.GetLength(1); int filterHeight = filterMatrix.GetLength(0); int filterOffset = (filterWidth - 1) / 2; // TODO : PADDING边角 for (int x = filterOffset; x < Width - filterOffset; x++) { for (int y = filterOffset; y < Height - filterOffset; y++) { blue = green = red = 0d; for (int filterX = -filterOffset; filterX <= filterOffset; filterX++) { for (int filterY = -filterOffset; filterY <= filterOffset; filterY++) { var color = At(x + filterX, y + filterY); red += color.R * filterMatrix[filterY + filterOffset, filterX + filterOffset]; green += color.G * filterMatrix[filterY + filterOffset, filterX + filterOffset]; blue += color.B * filterMatrix[filterY + filterOffset, filterX + filterOffset]; } } red = red * factor + bias; green = green * factor + bias; blue = blue * factor + bias; if (red > 255) { red = 255; } else if (red < 0) { red = 0; } if (green > 255) { green = 255; } else if (green < 0) { green = 0; } if (blue > 255) { blue = 255; } else if (blue < 0) { blue = 0; } rt.Set(x, y, Color.FromArgb((int)red, (int)green, (int)blue)); } } this.pixels = rt.pixels; }