【问题标题】:Android YUV to grayscale performance optimizationAndroid YUV到灰度性能优化
【发布时间】:2020-05-14 20:08:13
【问题描述】:

我正在尝试将 YUV 图像转换为灰度,所以基本上我只需要 Y 值。 为此,我编写了一小段代码(frame 是 YUV 图像):

imageConversionTime = System.currentTimeMillis();
        size = frame.getSize();

        byte nv21ByteArray[] = frame.getImage();

        int lol;

        for (int i = 0; i < size.width; i++) {
            for (int j = 0; j < size.height; j++) {
                lol = size.width*j + i;
                yMatrix.put(j, i, nv21ByteArray[lol]);
            }
        }

        bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(yMatrix, bitmap);


        imageConversionTime = System.currentTimeMillis() - imageConversionTime;

但是,这大约需要 13500 毫秒。我需要它更快(在我的计算机上,python 需要 8.5 毫秒)(我在摩托罗拉 Moto E 4G 第二代上工作,不是超级强大,但它应该足以转换图像吧?)。

有什么建议吗?

提前致谢。

【问题讨论】:

  • 除非您想深入了解 OpenGL 着色器,否则请查看 Android RenderScript,因为示例(RGB 到灰度 RGB)与您想要做的类似。确实需要对 C 有一定的了解,因为 RenderScript 是 C99。
  • 我会看看 OpenGL。谢谢你的回答。

标签: android performance image-processing optimization


【解决方案1】:

首先,我会将size.widthsize.height 分配给一个变量。我不认为编译器会默认优化这个,但我不确定。

此外,创建一个代表结果的byte[],而不是使用Matrix。 然后你可以这样做:

int[] grayScalePixels = new int[size.width * size.height];
int cntPixels = 0;

在你的内部循环集合中

grayScalePixels[cntPixels] = nv21ByteArray[lol];
cntPixels++;

要获得最终图像,请执行以下操作:

Bitmap grayScaleBitmap = Bitmap.createBitmap(grayScalePixels, size.width, size.height, Bitmap.Config.ARGB_8888);

希望它能正常工作(我没有测试过,但至少显示的原理应该适用 -> 依赖于 byte[] 而不是 Matrix)

【讨论】:

    【解决方案2】:

    可能晚了 2 年,但无论如何 ;)

    要转换为灰度,您只需将 u/v 值设置为 128 并保持 y 值不变。请注意,此代码适用于 YUY2 格式。其他格式可以参考this文档。

    private void convertToBW(byte[] ptrIn, String filePath) {
        // change all u and v values to 127 (cause 128 will cause byte overflow)
        byte[] ptrOut = Arrays.copyOf(ptrIn, ptrIn.length);
    
        for (int i = 0, ptrInLength = ptrOut.length; i < ptrInLength; i++) {
            if (i % 2 != 0) {
                ptrOut[i] = (byte) 127;
            }
        }
        convertToJpeg(ptrOut, filePath);
    
    }
    

    对于 NV21/NV12,我认为循环会变为:

    for (int i = ptrOut.length/2, ptrInLength = ptrOut.length; i < ptrInLength; i++) {}
    

    注意:(我自己没试过)

    另外我建议单独分析你的 utils 方法和 createBitmap 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      相关资源
      最近更新 更多