【问题标题】:Converting an Image Bitmap to a binary image in Android Studio在 Android Studio 中将图像位图转换为二进制图像
【发布时间】:2017-08-21 23:10:01
【问题描述】:

我正在尝试在 LED 矩阵中显示图像/视频,该矩阵具有可以打开或关闭的 LED。因此,我需要将任何图像转换为其二进制(0/1 或真/假)格式,以将值提供给 LED 矩阵。这是通过 Android 应用程序完成的。

您能建议一种快速有效的方法吗?我知道这样做的迭代方式,即

1) 嵌套循环扫描原始位图的高度和宽度

2) 从每个 Pixel 元素中获取 R、G、B 值,并使用一些公式将其与阈值进行比较。 (R+G+B > THRESHOLD 或者灰度公式 0.299R + 0.587G + 0.114B> THRESHOLD)

这个方法确实有效。但是,这非常缓慢。转换一个位图大约需要 2 秒。当我尝试转换具有多个帧(和相应的位图)的视频时,即使是 10 秒的视频也需要很长时间。另一个问题是处理器总是被处理的数据量阻塞。即使将计算放在线程上,我也会收到“丢帧”错误。

必须有更快的方法来做到这一点,因为大多数相机应用程序都提供实时图像过滤器。

确切地说,我需要一种方法来获取位图并获得其二进制等效项。

为了节省内存,最好将结果存储在字节流/数组中。否则,布尔/整数变量每个像素占用一个完整字节。这乘以帧中的像素数和帧数只会占用太多内存,特别是如果我尝试并行线程来完成它。

希望有人能帮我解决这个问题。

【问题讨论】:

  • 你的Bitmaps 有多大?
  • 您可以使用Bitmap.copyPixelsToBuffer将其存储在Buffer
  • @pskink 我正在使用 Bitmap.createScaledBitmap 将我的位图缩放到 358x358(这是我真正的 LED 矩阵的大小)。然后转换开始。所以不是一个巨大的图像。仍然需要 2-3 秒。
  • 我在模拟器上使用了 1280 x 1280 位图,转换需要 15-20 毫秒
  • @Shreyash S Sarnayak 那会完成什么?它仍然将相同的位图存储到缓冲区而不转换为二进制(0/1)图像,对吗?呃..我在这里遗漏了一些明显的观点吗?我对 android 编程很陌生..

标签: android performance bitmap type-conversion processing-efficiency


【解决方案1】:

我认为您可以使用颜色矩阵来实现您想要的。它比遍历 Bitmap 更有效。

下面的示例采用位图并将每个可见 (alpha != 0) 变为透明 (0x0ffffff) 以显示下面的视图。每个不可见像素都设置为黑色 (0xff000000)。我认为您可以对其进行调整以解决您的问题:

public Bitmap convertBitmap(Bitmap bitmap) {
    Bitmap output =  Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    Paint colorFilterMatrixPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    colorFilterMatrixPaint.setColorFilter(new ColorMatrixColorFilter(new float[] {
            0, 0, 0, 255, 0,
            0, 0, 0, 255, 0,
            0, 0, 0, 255, 0,
            0, 0, 0, -255, 255
    }));
    canvas.drawBitmap(bitmap, 0, 0, colorFilterMatrixPaint);
    return output;
}

更新: 我已经进行了一些调整,以使输出成为具有 0 和 1 的字节数组(不是位数组,因为这需要对输入的大小进行一些假设或使用我试图避免的 if 语句)。我正在使用两个通道和 ARGB_4444 位图,也可以对其进行改进以节省速度和内存消耗,但它似乎很快,并且大部分工作都是在硬件中完成的:

public Bitmap convertBitmap(Bitmap input) {
    int width = input.getWidth();
    int height = input.getHeight();
    Bitmap firstPass =  Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
    Bitmap secondPass =  Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
    Canvas firstCanvas = new Canvas(firstPass);
    Paint colorFilterMatrixPaint = new Paint();
    colorFilterMatrixPaint.setColorFilter(new ColorMatrixColorFilter(new float[]{
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            1, 1, 1, -1, 0
    }));

    firstCanvas.drawBitmap(input, 0, 0, colorFilterMatrixPaint);

    Canvas secondCanvas = new Canvas(secondPass);
    Paint colorFilterMatrixPaint2 = new Paint();
    colorFilterMatrixPaint2.setColorFilter(new ColorMatrixColorFilter(new float[]{
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 255, -255
    }));

    secondCanvas.drawBitmap(firstPass, 0, 0, colorFilterMatrixPaint2);

    int pixels[] = new int[width * height];
    byte pixelsMap[] = new byte[width * height];
    secondPass.getPixels(pixels, 0, width, 0, 0, width, height);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            pixelsMap[(x * y) + y] = (byte) ((pixels[(x * y) + y] >> 24) * -1);
        }
    }
    return secondPass;
}

【讨论】:

  • 我对 android 编程有点陌生。那么你能帮我理解一下你的代码吗?
  • 您正在创建一个与原始大小相同的空白位图,并为此创建一个画布。并与过滤器相乘。但我仍然没有得到全部内容或如何将其用于转换为二进制图像。它可能会帮助我获得一个只有 255 和 0 的位图,我仍然需要对其进行迭代并进行比较以获得 0/1 数组
  • 那么想要的输出到底是什么(一个 1/0 位的数组,一个只有 1 和 0 的位图)?
  • 一个 1/0 数组,每个数组对应一个像素。理想情况下是一个字节数组,每个字节存储 8 个像素 (1/0s) 的信息。即每个像素一位。
猜你喜欢
  • 2011-08-05
  • 2013-08-13
  • 2012-02-07
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多