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;
}