Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
445 views
in Technique[技术] by (71.8m points)

c# - Replacing Colour Of An Image

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 getting the image from clipboard

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

I've seen some other questions where theyre working with an actual bitmap, but how do I approach it direct from clipboard?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...