日常我们经常碰到图片去除背景的问题,比如我希望人物的周边背景均替换为背景色,但人物衣服上跟背景色接近的部分不受影响。最典型的例子就是身份证照片更换背景色,这需要用到复杂一点的算法。从图片的上部、左部、右部和下部开始,使用边界检测方法处理,直到遇到与背景颜色不相似的像素为止。程序如下,成品演示详见https://calc.xycost.com/Chatgpt/Changebg.aspx:
public class ImageProcessor
{
public static Bitmap ReplaceSimilarColorsBoundary(string imagePath, Color originalColor, Color replacementColor, int tolerance)
{
Bitmap image = new Bitmap(imagePath);
bool[,] visited = new bool[image.Width, image.Height];
bool IsSimilar(Color color1, Color color2)
{
int diffR = Math.Abs(color1.R - color2.R);
int diffG = Math.Abs(color1.G - color2.G);
int diffB = Math.Abs(color1.B - color2.B);
return (diffR + diffG + diffB) <= tolerance;
}
void FloodFill(int x, int y)
{
Stack<Point> stack = new Stack<Point>();
stack.Push(new Point(x, y));
while (stack.Count > 0)
{
Point current = stack.Pop();
if (current.X < 0 || current.X >= image.Width || current.Y < 0 || current.Y >= image.Height)
continue;
if (visited[current.X, current.Y] || !IsSimilar(image.GetPixel(current.X, current.Y), originalColor))
continue;
visited[current.X, current.Y] = true;
image.SetPixel(current.X, current.Y, replacementColor);
stack.Push(new Point(current.X + 1, current.Y));
stack.Push(new Point(current.X - 1, current.Y));
stack.Push(new Point(current.X, current.Y + 1));
stack.Push(new Point(current.X, current.Y - 1));
}
}
// Start flood fill from the four corners
FloodFill(0, 0);
FloodFill(0, image.Height - 1);
FloodFill(image.Width - 1, 0);
FloodFill(image.Width - 1, image.Height - 1);
return image;
}
}



评论0