Replacing Colour Of An Image

前端 未结 3 1345
猫巷女王i
猫巷女王i 2020-12-20 10:37

I am trying to replace the black colours of a picture with white, and vice versa. This is actually so my OCR code can read it on white backgrounds better. It\'s currently ge

相关标签:
3条回答
  • 2020-12-20 11:11

    You can use the ColorMap and ImageAttributes classes from the System.Drawimg.Imaging namespace to directly replace the pixels in your image:

    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;
    }
    
    0 讨论(0)
  • 2020-12-20 11:24

    Another solution using the ColorMatrix class.

    You can use the Graphics.DrawImage overload that accepts an ImageAttributes argument.
    ImageAttributes.SetColorMatrix() sets the color-adjustment matrix, optionally targeting a specific category (Bitmap, Pen, Brush etc.) and can be instructed to skip the Gray Colors, modify the Gray colors only or all Colors.

    The ImageAttributes.SetThreshold() method allows to regulate the Colors cutoff point (threshold) to fine tune the Brightness.
    It accepts values from 0 to 1.
    When set to 0, an image is all white, all black when set to 1 (see the Docs about it).

    Also consider that the "Inversion" depends on the original bitmap color pattern, so try different approaches. Sometimes, inverting the brightness can give you a better result, sometime it doesn't.

    You OCR must be "trained", to verify what values suits it better.

    Take a look at these articles:
    Recoloring (MSDN)
    ASCII Art Generator (CodeProject)

    Brightness Matrix:
    R=Red G=Green B=Blue A=Alpha Channel W=White (Brightness)

    Modify the Brightness component to obtain an "Inversion"

        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;
        }
    }
    
    0 讨论(0)
  • 2020-12-20 11:27

    if your image is B&W, it is very easy in OpenCV:

    // bmp is your bitmap
    var inverted = (255 - bitmap.ToMat()).ToMat().
      .ToBitamp() // or
      .ToWriteableBitmap() // or
      .ToBitmapSource()
    

    OpenCV can be a little overkill if this in your only manipulation in the whole app

    0 讨论(0)
提交回复
热议问题