将位图中特定颜色以外的所有颜色转换为白色

时间:2016-04-07 11:06:07

标签: android canvas bitmap tesseract

我正在使用tess-two库,我希望将我图像中除黑色以外的所有颜色转换为白色(黑色将是文本)。从而使tess-two更容易阅读文本。我已经尝试了各种方法,但是他们花费了太多时间,因为它们逐像素地转换。有没有办法使用画布或任何可以更快地提供结果的东西来实现这一点。

更新

该算法提出的另一个问题是打印机没有像Android中那样使用相同的BLACK和White进行打印。因此算法将整个图像转换为白色。

我目前使用的逐像素方法。

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

3 个答案:

答案 0 :(得分:1)

Per,Rishabh的评论。使用颜色矩阵。由于黑色是黑色并且是RGB(0,0,0,255),因此它不受乘法影响。因此,如果你在所有通道中将所有东西乘以255,一切都将超过极限并被压缩为白色,除了黑色将保持黑色。

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

您可以使用该绘画在仅有黑色 - 留下 - 黑色的彩色矩阵滤镜荣耀中绘制该位图。

注意:这是一个快速且令人敬畏的技巧,但是,它 ONLY 适用于黑色。虽然它非常适合您的使用,并且会将这种冗长的操作变成即时的,但它实际上并不符合“特定颜色”的标题问题。我的算法可以用你想要的任何颜色,只要它是黑色的。

答案 1 :(得分:0)

虽然@Tata​​rize的答案很完美,但我在阅读打印图像方面遇到了麻烦,因为它并不总是黑色。

我在堆栈溢出时发现的算法工作得很好,它实际上检查特定像素是否更接近黑色或白色并将像素转换为最接近的颜色。因此提供范围的二值化。 (https://stackoverflow.com/a/16534187/3710223)。

我现在正在做的是将不需要的区域保持为浅色,而将文本保持为黑色。该算法在大约20-35秒内给出二值化图像。仍然没那么快但效率高。

column title_column1 new_value vc1
column title_column2 new_value vc2
column title_column3 new_value vc3
select title_column1,title_column2,title_column3 from test_columns;
select &vc1,&vc2,&vc3 from test_data;

如果返回值为true,那么我们将像素转换为黑色,否则我们将其转换为白色。

我知道可以有更好/更快的答案,欢迎更多答案:)

答案 2 :(得分:0)

同样的事情,但在renderscript中完成,时间约60-100ms。你甚至不会注意到延迟。

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

分配是否使用renderscript将数据写入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;
}

注意1200只是我使用的阈值,应该是小于20的所有三个组件(或者,如0,0,sqrt(1200)又名(~34))。您可以相应地向上或向下设置1200限制。

构建gradle需要Renderscript:

renderscriptTargetApi 22

构建工具的最后几件事声称修复了一堆renderscript头痛。因此,在像你这样的关键任务领域做这类事情可能是完全合理的。等待20秒太长,60毫秒不是。