Convert all colors other than a specific color to a bitmap to white

I am using the tess-two library, and I want to convert all colors except black in my image to white (black will be text). Thus, for tess-2 it is easier to read the text. I tried various methods, but they take too much time, as they convert pixel by pixel. Is there a way to achieve this with a canvas or anything that gives results faster.

UPDATE

Another problem associated with this algorithm is that the printer does not print with the same BLACK and White as in android. Thus, the algorithm converts the whole picture to white.

The pixel method that I am currently using.

binarizedImage = convertToMutable(cropped);// the bitmap is made mutable int width = binarizedImage.getWidth(); int height = binarizedImage.getHeight(); int[] pixels = new int[width * height]; binarizedImage.getPixels(pixels, 0, width, 0, 0, width, height); for(int i=0;i<binarizedImage.getWidth();i++) { for(int c=0;c<binarizedImage.getHeight();c++) { int pixel = binarizedImage.getPixel(i, c); if(!(pixel == Color.BLACK || pixel == Color.WHITE)) { int index = c * width + i; pixels[index] = Color.WHITE; binarizedImage.setPixels(pixels, 0, width, 0, 0, width, height); } } } 
+6
source share
3 answers

Per, comment by Rishaba. Use a color matrix. Since black is black and RGB (0,0,0,255), it is immune to reproduction. Therefore, if you multiply everything by 255 in all channels, everything will exceed the limit and get compressed to white, except for black, which will remain black.

  ColorMatrix bc = new ColorMatrix(new float[] { 255, 255, 255, 0, 0, 255, 255, 255, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 1, 0, }); ColorMatrixColorFilter filter = new ColorMatrixColorFilter(bc); paint.setColorFilter(filter); 

You can use this paint to paint this bitmap only in the black filter slide of black.

Note. This is a quick and amazing trick, but it will ONLY work for black. Although it is ideal for your use and will turn this long op into something instantaneous, it actually does not match the name of the question "specific color", my algorithm works in whatever color you want as long as it is black.

+1
source

Although @Tatarize's answer was perfect, I had trouble reading the printed image because it was not always black.

This algorithm, which I found while stack overflowing, works great, it actually checks if a particular pixel is close to black or white and converts the pixel to the nearest color. Therefore, providing binarization range. ( fooobar.com/questions/852098 / ... ).

What I'm doing now is to keep the unwanted areas in light colors, and the text in black. This algorithm produces a binarized image after about 20-35 seconds. Still not as fast, but effective.

 private static boolean shouldBeBlack(int pixel) { int alpha = Color.alpha(pixel); int redValue = Color.red(pixel); int blueValue = Color.blue(pixel); int greenValue = Color.green(pixel); if(alpha == 0x00) //if this pixel is transparent let me use TRASNPARENT_IS_BLACK return TRASNPARENT_IS_BLACK; // distance from the white extreme double distanceFromWhite = Math.sqrt(Math.pow(0xff - redValue, 2) + Math.pow(0xff - blueValue, 2) + Math.pow(0xff - greenValue, 2)); // distance from the black extreme double distanceFromBlack = Math.sqrt(Math.pow(0x00 - redValue, 2) + Math.pow(0x00 - blueValue, 2) + Math.pow(0x00 - greenValue, 2)); // distance between the extremes double distance = distanceFromBlack + distanceFromWhite; return ((distanceFromWhite/distance)>SPACE_BREAKING_POINT); } 

If the return value is true, we will convert the pixel to black, otherwise we will convert it to white.

I know there may be better / faster answers and more answers are welcome :)

0
source

The same thing, but done in renderscript, times about 60-100 ms. You won't even notice the delay.

  Bitmap blackbitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),bitmap.getConfig()); RenderScript mRS = RenderScript.create(TouchEmbroidery.activity); ScriptC_blackcheck script = new ScriptC_blackcheck(mRS); Allocation allocationRaster0 = Allocation.createFromBitmap( mRS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT ); Allocation allocationRaster1 = Allocation.createTyped(mRS, allocationRaster0.getType()); script.forEach_root(allocationRaster0, allocationRaster1); allocationRaster1.copyTo(blackbitmap); 

Whether it has a distribution, uses renderscript to write data to blackbitmap.

 #pragma version(1) #pragma rs java_package_name(<YOUR PACKAGENAME GOES HERE>) void root(const uchar4 *v_in, uchar4 *v_out) { uint32_t value = (v_in->r * v_in->r); value = value + (v_in->g * v_in->g); value = value + (v_in->b * v_in->b); if (value > 1200) { v_out->r = 255; v_out->g = 255; v_out->b = 255; } else { v_out->r = 0; v_out->g = 0; v_out->b = 0; } v_out->a = 0xFF; } 

Please note that 1200 is only the threshold value that I used, there must be all three components less than 20 (or, for example, 0, 0, sqrt (1200) aka (~ 34)). You can set the limit to 1200 respectively up or down.

And to build gradle, you need Renderscript:

 renderscriptTargetApi 22 

Recently, some assembly tools claim that they fixed a bunch of headaches. So it would be wise to do such things in such important places of the mission as yours. 20 seconds to wait too long, 60 milliseconds not.

0
source

All Articles