简体   繁体   English

如何使用灰度像素值从位图创建 ByteBuffer?

[英]How to create a ByteBuffer from Bitmap using grayscale pixel value?

I am trying to use a tflite model in my android app.我正在尝试在我的 android 应用程序中使用tflite模型。 The problem arises when I have to create a ByteBuffer out of the Bitmap and use it as Input to the model.当我必须从位图创建一个 ByteBuffer 并将其用作模型的输入时,就会出现问题。

Problem: Bitmap is ARGB_8888 (32 bit) whereas I need (8 bit) grayscale image.问题:位图是 ARGB_8888(32 位)而我需要(8 位)灰度图像。

Method to convert Bitmap to ByteBuffer: Bitmap转ByteBuffer的方法:

mImgData = ByteBuffer
                .allocateDirect(4 * 28 * 28 * 1);

private void convertBitmapToByteBuffer(Bitmap bitmap) throws NullPointerException {
    if (mImgData == null) {
        throw new NullPointerException("Error: ByteBuffer not initialized.");
    }

    mImgData.rewind();

    for (int i = 0; i < DIM_IMG_SIZE_WIDTH; i++) {
        for (int j = 0; j < DIM_IMG_SIZE_HEIGHT; j++) {
            int pixelIntensity = bitmap.getPixel(i, j);
            unpackPixel(pixelIntensity, i, j);
            Log.d(TAG, String.format("convertBitmapToByteBuffer: %d -> %f", pixelIntensity, convertToGrayScale(pixelIntensity)));
            mImgData.putFloat(convertToGrayScale(pixelIntensity));
        }
    }

}

private float convertToGrayScale(int color) {
    return (((color >> 16) & 0xFF) + ((color >> 8) & 0xFF) + (color & 0xFF)) / 3.0f / 255.0f;
}

However, all the pixel values are either -1 or -16777216.但是,所有像素值都是 -1 或 -16777216。 Note that that unpackPixel method mentioned here doesn't work, since all values have the same int value anyway.请注意,这里提到的 unpackPixel 方法不起作用,因为无论如何所有值都具有相同的 int 值。 (Posted with changes below for reference.) (在下面发布更改以供参考。)

private void unpackPixel(int pixel, int row, int col) {
    short red,green,blue;
    red = (short) ((pixel >> 16) & 0xFF);
    green = (short) ((pixel >> 8) & 0xFF);
    blue = (short) ((pixel >> 0) & 0xFF);
}

You can call Color.red() or green/blue on the pixel value and it will return the gray intensity.您可以在像素值上调用Color.red()或 green/blue ,它将返回灰度强度。 Then just put it in the byte buffer using putFloat() .然后使用putFloat()将其放入字节缓冲区。 Also getting all pixel values in a single array using bitmap.getPixels() is comparatively faster than bitmap.getPixel(i, j) .使用bitmap.getPixels()获取单个数组中的所有像素值也比bitmap.getPixel(i, j)快。 Here's how I am doing it to load grayscale images in my tflite model:这是我如何在我的 tflite 模型中加载灰度图像:

private ByteBuffer getByteBuffer(Bitmap bitmap){
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    ByteBuffer mImgData = ByteBuffer
            .allocateDirect(4 * width * height);
    mImgData.order(ByteOrder.nativeOrder());
    int[] pixels = new int[width*height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    for (int pixel : pixels) {
        mImgData.putFloat((float) Color.red(pixel));
    }
    return mImgData;
}

If you need normalized values just divide by 255:如果您需要归一化值,只需除以 255:

float value = (float) Color.red(pixel)/255.0f;
mImgData.putFloat(value);

You can then use this in your interpreter as:然后,您可以在解释器中使用它作为:

ByteBuffer input = getByteBuffer(bitmap);
tflite.run(input, outputValue);

Hope this helps people looking for this in the future!希望这可以帮助人们在未来寻找这个!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM