C# GDI 手绘图片转化为电子版处理

C# GDI 手绘图片转化为电子版处理

处理原理

找到图片边缘像素的平均颜色值,以及边缘像素点与均色值之间的最大差值,然后整个图片中只保留颜色差值大于最大差值的点,即可。

源码

Bitmap m = pictureBox1.Image as Bitmap;
            if (m == null) return;

            double targetWidth = 500;
            double scale = targetWidth / m.Width;
            Bitmap newM = new Bitmap((int)(m.Width * scale), (int)(m.Height * scale));
            var g = Graphics.FromImage(newM);
            g.DrawImage(m,
                new Rectangle(0, 0, newM.Width, newM.Height),
                new Rectangle(0, 0, m.Width, m.Height ),
                GraphicsUnit.Pixel);

            //背景平均色
            Color avgColorRow = avgColorInRow(newM, 0, 1, 2, newM.Height - 1, newM.Height - 2, newM.Height - 3);
            Color avgColorCol = avgColorInCol(newM, 0, 1, 2, newM.Width - 1, newM.Width - 2, newM.Width - 3);
            Color avgColor = Color.FromArgb((avgColorRow.R + avgColorCol.R) / 2,
                (avgColorRow.G + avgColorCol.G) / 2,
                (avgColorRow.B + avgColorCol.B) / 2);


            //背景最大差值
            var maxDifferRow = maxAvgColorInRow(newM, avgColor, 0, 1, 2, newM.Height - 1, newM.Height - 2, newM.Height - 3);
            var maxDifferCol = maxAvgColorInCol(newM, avgColor, 0, 1, 2, newM.Width - 1, newM.Width - 2, newM.Width - 3);
            var maxDiffer = Math.Max(maxDifferRow, maxDifferCol);

            //只保留高于最大差值的点
            Dictionary<Point, Color> validPs = new Dictionary<Point, Color>();
            for (int i = 0; i < newM.Width; i++)
            {
                for (int j = 0; j < newM.Height; j++)
                {
                    var clr = newM.GetPixel(i, j);
                    var differ = Math.Abs(clr.R + clr.G + clr.B - avgColor.R - avgColor.G - avgColor.B);
                    if (differ > maxDiffer)
                    {
                        validPs.Add(new Point(i, j), label1.BackColor);
                    }
                }
            }
            //只保留有效区域
            int minX = validPs.Min(a => a.Key.X);
            int maxX = validPs.Max(a => a.Key.X);
            int minY = validPs.Min(a => a.Key.Y);
            int maxY = validPs.Max(a => a.Key.Y);


            Bitmap rstM = new Bitmap(maxX - minX + 1, maxY - minY + 1);
            g = Graphics.FromImage(rstM);

            List<PointColor> objs = new List<PointColor>();
            foreach (var p in validPs)
            {
                rstM.SetPixel(p.Key.X - minX, p.Key.Y - minY, p.Value);
                objs.Add(new PointColor()
                {
                    Color = p.Value,
                    X = p.Key.X - minX,
                    Y = p.Key.Y - minY
                }
                 );
            }
            if (drawObjs.ContainsKey(textBox1.Text))
                drawObjs.Remove(textBox1.Text);
            drawObjs.Add(textBox1.Text, objs);

            pictureBox1.Image = rstM;

       }

 private Color avgColorInRow(Bitmap newM, params int[] rowindex)
        {
            //首行平均色
            int avgR = 0, avgG = 0, avgB = 0;

            for (int r = 0; r < rowindex.Length; r++)
            {
                for (int c = 0; c < newM.Width; c++)
                {
                    var clr = newM.GetPixel(c, rowindex[r]);
                    avgR += clr.R;
                    avgG += clr.G;
                    avgB += clr.B;
                }

            }
            return Color.FromArgb(avgR / (newM.Width * rowindex.Length),
                avgG / (newM.Width * rowindex.Length),
                avgB / (newM.Width * rowindex.Length));
        }
         
        private Color avgColorInCol(Bitmap newM, params int[] colindex)
        {
            //首行平均色
            int avgR = 0, avgG = 0, avgB = 0;
            for (int c = 0; c < colindex.Length; c++)
            {
                for (int r = 0; r < newM.Height; r++)
                {
                    var clr = newM.GetPixel(colindex[c], r);
                    avgR += clr.R;
                    avgG += clr.G;
                    avgB += clr.B;
                }
            }
            return Color.FromArgb(avgR / (newM.Height * colindex.Length),
                avgG / (newM.Height * colindex.Length),
                avgB / (newM.Height * colindex.Length));
        }

        private int maxAvgColorInRow(Bitmap newM, Color avgColor, params int[] rowIndex)
        {
            int maxDiffer = 0;
            for (int r = 0; r < rowIndex.Length; r++)
            {
                for (int c = 0; c < newM.Width; c++)
                {
                    var clr = newM.GetPixel(c, rowIndex[r]);
                    var differ = Math.Abs(clr.R + clr.G + clr.B - avgColor.R - avgColor.G - avgColor.B);
                    if (differ > maxDiffer)
                        maxDiffer = differ;
                }
            }
            return maxDiffer;
        }

        private int maxAvgColorInCol(Bitmap newM, Color avgColor, params int[] colIndex)
        {
            int maxDiffer = 0;
            for (int c = 0; c < colIndex.Length; c++)
            {
                for (int r = 0; r < newM.Height; r++)
                {
                    var clr = newM.GetPixel(colIndex[c], r);
                    var differ = Math.Abs(clr.R + clr.G + clr.B - avgColor.R - avgColor.G - avgColor.B);
                    if (differ > maxDiffer)
                        maxDiffer = differ;
                }
            }
            return maxDiffer;
        }