【问题标题】:Replacing colour of an Image替换图像的颜色
【发布时间】:2018-05-11 07:48:55
【问题描述】:

我正在尝试用白色替换图片的黑色,反之亦然。这实际上是为了让我的 OCR 代码可以在白色背景上更好地读取它。它目前正在从剪贴板获取图像

 Image img = Clipboard.GetImage();
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            pictureBox1.Image = img;

我在使用实际位图时看到了一些其他问题,但我如何直接从剪贴板处理它?

【问题讨论】:

  • 传入的图像是黑白的还是可能包含灰色或其他(微妙的)颜色?如果是这样,您希望如何处理?
  • 这是黑白图像吗?
  • 嗯,我怀疑图像是纯黑白的,因为替换其中一种颜色会创建一个空白图像。

标签: c# winforms ocr colormatrix


【解决方案1】:

使用ColorMatrix 类的另一种解决方案。

您可以使用接受ImageAttributes 参数的Graphics.DrawImage 重载。
ImageAttributes.SetColorMatrix() 设置颜色调整矩阵,可选择针对特定类别(位图、钢笔、画笔等)并且可以被指示要跳过灰色,请仅修改灰色或所有颜色。

ImageAttributes.SetThreshold() 方法允许调节颜色截止点(阈值)以微调亮度。
它接受从01 的值。
当设置为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 命名空间中的 ColorMapImageAttributes 类直接替换图像中的像素:

    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 可能有点矫枉过正

    【讨论】:

      猜你喜欢
      • 2010-12-05
      • 2011-07-12
      • 1970-01-01
      • 2016-02-07
      • 2011-05-16
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 2012-04-09
      相关资源
      最近更新 更多