如何用Image中的其他颜色替换像素颜色?

我有一个图像,我可以使用Martix读取它的所有像素颜色…如何更改任何像素的RGB如果我想将其转换为最接近的颜色(黑色,红色或白色)

我在Matrix中读取图像的代码是:

string sourceimg = @"D:\ProductionTools\Taskes\Image Processing\Test\001.jpg"; //... Bitmap imageoriginal = new Bitmap(sourceimg); int height = imageoriginal.Height; int width = imageoriginal.Width; Color[][] colormatrix = new Color[width][]; for (int i = 0; i < width; i++) { colormatrix[i] = new Color[height]; for (int j = 0; j < height; j++) { colormatrix[i][j] = new Color(); colormatrix[i][j] = imageoriginal.GetPixel(i, j); } } 

正如你的评论所指出的,问题是关于色距,这不是一件小事。 它还涉及您使用的颜色空间,因此我将在此向您展示RGB,HSV,HLS和CIELAB中的示例。 此外,要计算距离,您需要一个公式。 为简单起见,让我们粘贴到欧几里德距离,如同 在此处输入图像描述

然后,为了简单地回答你的问题,你计算从当前颜色q到你拥有的三个目标pi (黑色,红色和白色)的距离。 最小距离表示您替换的颜色。 如果是平局,我保持最早的颜色给出最小距离。

现在,颜色空间在这项任务中也非常重要,因为它确定了欧氏距离的含义。 这是一个示例图像:

在此处输入图像描述

以RGB格式转换:

在此处输入图像描述

在HLS中转换(即,RGB颜色转换为HLS并计算距离):

在此处输入图像描述

HSV:

在此处输入图像描述

CIELAB:

在此处输入图像描述

正如已经指出的,这个问题最难的部分是知道给定的颜色是否“更接近”黑色,白色或红色。 我扔了一些可能对你有用的东西:

 Color GetNearestOfBWR(Color c) { float redness = Math.Abs(180 - c.GetHue()) / 180; float brightness = c.GetBrightness(); float saturation = c.GetSaturation(); 

您现在有三个值,每个值介于0和1之间,其中从0增加到1意味着您越来越接近红色(粗略地说:更多红色/更少绿色和蓝色,更多颜色/更少黑色,更多颜色/更少灰色)。

你现在必须决定一个颜色在什么时候构成“红色”,老实说这是一个判断。 你可以简单地拥有

  double brightColourfulRedness = Math.Sqrt( redness*redness + brightness*brightness + saturation*saturation); if (brightColourfulRedness > 1) return Color.FromArgb(255, 0, 0); // red; 

(简单的欧几里德范数)但您可能希望比另一个更强烈地加权特定属性 – 或者只是修改1阈值。

然后你必须决定什么映射到黑色或白色; 这可能很简单

  if (brightness > 0.5) return Color.FromArgb(255, 255, 255); // white return Color.FromArgb(0, 0, 0); // black } 

大! 因此,现在您可以根据品味将颜色映射为红色,白色或黑色。 剩下的就是将它应用于位图中的每个像素。 如果您很乐意覆盖从文件中加载的Bitmap ,则不需要该arrays; 你可以这样做:

 int height = imageoriginal.Height; int width = imageoriginal.Width; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { Color origC = imageoriginal.GetPixel(i, j); Color newC = GetNearestOfBWR(origC); imageoriginal.SetPixel(i, j, newC); } } 

这可能非常慢,所以您也可以使用DmitryG的LockBits代码,但是您需要在它提供的intGetNearestOfBWR所需的Color之间进行转换。 ( FromArgbToArgb这样做,我相信。)