替换图像的颜色
Posted
技术标签:
【中文标题】替换图像的颜色【英文标题】:Replacing colour of an Image 【发布时间】:2018-05-11 07:48:55 【问题描述】:我正在尝试用白色替换图片的黑色,反之亦然。这实际上是为了让我的 OCR 代码可以在白色背景上更好地读取它。它目前正在从剪贴板获取图像
Image img = Clipboard.GetImage();
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = img;
我在使用实际位图时看到了一些其他问题,但我如何直接从剪贴板处理它?
【问题讨论】:
传入的图像是黑白的还是可能包含灰色或其他(微妙的)颜色?如果是这样,您希望如何处理? 这是黑白图像吗? 嗯,我怀疑图像是纯黑白的,因为替换其中一种颜色会创建一个空白图像。 【参考方案1】:使用ColorMatrix 类的另一种解决方案。
您可以使用接受ImageAttributes 参数的Graphics.DrawImage 重载。ImageAttributes.SetColorMatrix()
设置颜色调整矩阵,可选择针对特定类别(位图、钢笔、画笔等)并且可以被指示要跳过灰色,请仅修改灰色或所有颜色。
ImageAttributes.SetThreshold()
方法允许调节颜色截止点(阈值)以微调亮度。
它接受从0
到1
的值。
当设置为0
时,图像全白,设置为1
时全黑(参见相关文档)。
还要考虑“反转”取决于原始位图颜色模式,因此请尝试不同的方法。有时,反转亮度可以为您带来更好的结果,但有时却不能。
您的 OCR 必须经过“培训”,以验证哪些值更适合它。
看看这些文章:Recoloring (MSDN)ASCII Art Generator (CodeProject)
亮度矩阵:R=Red G=Green B=Blue A=Alpha Channel W=White (Brightness)
修改亮度组件以获得“反转”
R G B A W
R [1 0 0 0 0]
G [0 1 0 0 0]
B [0 0 1 0 0]
A [0 0 0 1 0]
W [b b b 0 1] <= Brightness
using System.Drawing;
using System.Drawing.Imaging;
// ...
Image colorImage = Clipboard.GetImage();
// Default values, no inversion, no threshold adjustment
var bmpBlackWhite = BitmapToBlackAndWhite(colorImage);
// Inverted, use threshold adjustment set to .75f
var bmpBlackWhite = BitmapToBlackAndWhite(colorImage, true, true, .75f);
// ...
private Bitmap BitmapToBlackAndWhite(Image image, bool invert = false, bool useThreshold = false, float threshold = .5f)
var mxBlackWhiteInverted = new float[][]
new float[] -1, -1, -1, 0, 0,
new float[] -1, -1, -1, 0, 0,
new float[] -1, -1, -1, 0, 0,
new float[] 0, 0, 0, 1, 0,
new float[] 1, 1, 1, 0, 1
;
var mxBlackWhite = new float[][]
new float[] 1, 1, 1, 0, 0,
new float[] 1, 1, 1, 0, 0,
new float[] 1, 1, 1, 0, 0,
new float[] 0, 0, 0, 1, 0,
new float[] -1, -1, -1, 0, 1
;
var bitmap = new Bitmap(image.Width, image.Height);
using (var g = Graphics.FromImage(bitmap))
using (var attributes = new ImageAttributes())
attributes.SetColorMatrix(new ColorMatrix(invert ? mxBlackWhiteInverted : mxBlackWhite));
// Adjust the threshold as needed
if (useThreshold) attributes.SetThreshold(threshold);
var rect = new Rectangle(Point.Empty, image.Size);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
return bitmap;
【讨论】:
【参考方案2】:您可以使用 System.Drawimg.Imaging
命名空间中的 ColorMap 和 ImageAttributes 类直接替换图像中的像素:
Image img = Clipboard.GetImage();
if (img != null)
ColorMap[] cm = new ColorMap[1];
cm[0] = new ColorMap();
cm[0].OldColor = Color.Black;
cm[0].NewColor = Color.White;
ImageAttributes ia = new ImageAttributes();
ia.SetRemapTable(cm);
using (Graphics g = Graphics.FromImage(img))
g.DrawImage(img, new Rectangle(Point.Empty, img.Size), 0, 0, img.Width, img.Height,
GraphicsUnit.Pixel, ia);
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = img;
【讨论】:
是否值得处置以前的pictureBox1
图像?此代码还会将白色映射到黑色吗?
@mjwills 是的。要将白色切换为黑色,只需更改 OldColor 和 NewColor 值。【参考方案3】:
如果你的图片是黑白的,在OpenCV中很容易:
// bmp is your bitmap
var inverted = (255 - bitmap.ToMat()).ToMat().
.ToBitamp() // or
.ToWriteableBitmap() // or
.ToBitmapSource()
如果在整个应用程序中唯一的操作中,OpenCV 可能有点矫枉过正
【讨论】:
以上是关于替换图像的颜色的主要内容,如果未能解决你的问题,请参考以下文章
使用遮罩更改 UIImage 的颜色并将该图像替换为彩色图像