android 我需要将一个位图标准化并存储在TensorImage中,有什么方法可以做到这一点吗?

ki1q1bka  于 2023-01-07  发布在  Android
关注(0)|答案(5)|浏览(87)

位图只保存整数值(0-255)。我需要将每个像素值除以255。位图被转换为TensorImage,然后在将其传递给预测输出的解释器时调用getBuffer()。(tflite.run())在中间的某个位置,我必须将每个RGB像素除以255。我担心还有另一个缺点,因为getBuffer()函数返回字节缓冲区。我找不到太多关于TensorFlow lite函数的文档。所以我不确定tflite.run()是否只能接受字节缓冲区。我是用Java编写的,对Android AppD不熟悉。请帮助我,因为这种规范化对于预测正确的值至关重要。
这是在调整大小后将位图转换为tensorimage的代码。在这里我需要将每个像素值除以255,但我被难住了。

private TensorImage resizePic(Bitmap bp) {
        ImageProcessor imageProcessor =
                new ImageProcessor.Builder()
                        .add(new ResizeOp(60, 60, ResizeOp.ResizeMethod.BILINEAR))
                        .build();
        TensorImage tImage = new TensorImage(DataType.FLOAT32);
        tImage.load(bp);
        tImage = imageProcessor.process(tImage);
        return tImage;
    }

下面是运行模型的行

tflite.run(tImage.getBuffer(), probabilityBuffer.getBuffer());

probabilityBuffer保存输出。

umuewwlo

umuewwlo1#

我可以使用以下链接构建合适的函数-

  1. Converting Bitmap to ByteBuffer (float) in Tensorflow-lite Android
  2. https://heartbeat.fritz.ai/image-classification-on-android-with-tensorflow-lite-and-camerax-4f72e8fdca79
    第二个链接在Kotlin,代码如下:
private ByteBuffer convertBitmapToByteBuffer(Bitmap bp) {
        ByteBuffer imgData = ByteBuffer.allocateDirect(Float.BYTES*60*60*3);
        imgData.order(ByteOrder.nativeOrder());
        Bitmap bitmap = Bitmap.createScaledBitmap(bp,60,60,true);
        int [] intValues = new int[60*60];
        bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

        // Convert the image to floating point.
        int pixel = 0;

        for (int i = 0; i < 60; ++i) {
            for (int j = 0; j < 60; ++j) {
                final int val = intValues[pixel++];

                imgData.putFloat(((val>> 16) & 0xFF) / 255.f);
                imgData.putFloat(((val>> 8) & 0xFF) / 255.f);
                imgData.putFloat((val & 0xFF) / 255.f);
            }
        }
        return imgData;
    }

这里,60是我要求输入的图像高度和宽度,而且,该方法不需要使用TensorImage,因此www.example.com()的最后一次调用tflite.run如下所示:

tflite.run(convertBitmapToByteBuffer(bp), probabilityBuffer.getBuffer());

这里,bp是位图图像。

nszi6y05

nszi6y052#

当你训练模型时,不要归一化图像。所以当你部署你的应用程序时,没有必要归一化位图图像。

fykwrbwg

fykwrbwg3#

你的第一篇参考文献给出了一个使用OpenCV进行转换的例子,下面是我得出的工作原理:

private ByteBuffer getImageDataForTfliteModelOpencv(Bitmap input) {
    if (input == null) {
        return null;
    }
    // Allocate output ByteBuffer
    ByteBuffer output = ByteBuffer.allocateDirect(1 * TFL_IMAGE_SIZE *
            TFL_IMAGE_SIZE * 3 * Float.BYTES);
    //
    output.order(ByteOrder.nativeOrder());
    output.rewind();

    Mat bufmat = new Mat();
    Mat newmat = new Mat(TFL_IMAGE_SIZE, TFL_IMAGE_SIZE, CvType.CV_32FC3);

    Utils.bitmapToMat(input, bufmat);
    Imgproc.cvtColor(bufmat, bufmat, Imgproc.COLOR_RGBA2RGB);
    bufmat.convertTo(newmat, CvType.CV_32FC3, 1.0/255.0);
    //
    // Write the image float data to the output ByteBuffer
    float buf[] = new float[TFL_IMAGE_SIZE * TFL_IMAGE_SIZE * 3];
    newmat.get(0,0, buf); // Get the float data
    output.asFloatBuffer().put(buf); // Write it as a stream of bytes
    return output;
}

返回的ByteBuffer可以很容易地加载到TensorBuffer中。我测试了这两种方法,对于112X112的图像,这个OpenCV方法大约快了50毫秒。

iqxoj9l9

iqxoj9l94#

正如这里提到的,使用here中的以下代码将位图转换为ByteBuffer(float32)

private ByteBuffer convertBitmapToByteBuffer(Bitmap bitmap) {
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * BATCH_SIZE * inputSize * inputSize * PIXEL_SIZE);
    byteBuffer.order(ByteOrder.nativeOrder());
    int[] intValues = new int[inputSize * inputSize];
    bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
    int pixel = 0;
    for (int i = 0; i < inputSize; ++i) {
        for (int j = 0; j < inputSize; ++j) {
            final int val = intValues[pixel++];
            byteBuffer.putFloat((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
            byteBuffer.putFloat((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
            byteBuffer.putFloat((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
        }
    }
    return byteBuffer;
}
d7v8vwbk

d7v8vwbk5#

我找到了答案:

private TensorImage resizePic(Bitmap bp) {
    ImageProcessor imageProcessor =
            new ImageProcessor.Builder()
                    .add(new ResizeOp(60, 60, ResizeOp.ResizeMethod.BILINEAR))
                    .add(new NormalizeOp(0f, 255f))
                    .build();
    TensorImage tImage = new TensorImage(DataType.FLOAT32);
    tImage.load(sourceBitmap);
    System.out.println("tensorImage0: " + tImage.getTensorBuffer().getFloatArray()[0]);
    tImage = imageProcessor.process(tImage);
    System.out.println("tensorImage1: " + tImage.getTensorBuffer().getFloatArray()[0]);
    return tImage;
}

终端:

System.out: tensorImage0: 232.0
System.out: tensorImage1: 0.9254902

相关问题