首页 > 解决方案 > ML Kit 条码扫描:图像数据大小无效

问题描述

我想在捕获的图像中检测条形码。我使用android的camera2捕捉图像。在此之后,检索图像的元数据并将图像保存到设备。元数据全部传递到下一个活动,这是应用程序尝试检测条形码的地方。

下一个活动从先前保存的文件中创建一个字节[]。接下来,使用随意图传递的数据创建相关的 FirebaseVision 对象。最后,应用程序尝试调用该detectInImage()方法,但会引发错误:

“java.lang.IllegalArgumentException:图像数据大小无效。”

我怀疑这是因为捕获的图像太大,但是我似乎无法弄清楚如何捕获较小的图像,而且我在参考文档中也找不到任何关于允许的最大尺寸的内容。非常感谢有关此错误以及如何解决它的信息。以下是我认为是相关代码的内容。

private final ImageReader.OnImageAvailableListener onImageAvailableListener
        = new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader imageReader) {
        try{
            // Semaphore ensures date is recorded before starting next activity
            storeData.acquire();
            Image resultImg = imageReader.acquireNextImage(); // Image from camera
            imgWidth = resultImg.getWidth();
            imgHeight = resultImg.getHeight();
            ByteBuffer buffer = resultImg.getPlanes()[0].getBuffer();
            data = new byte[buffer.remaining()]; // Byte array with the images data
            buffer.get(data);
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

            // Note: mediaFile directs to Pictures/"ThisProject" folder
            File media = new File(mediaFile.getPath() +
                    File.separator + "IMG_" + timeStamp + ".jpg");

            // Saving the image
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(media);
                fos.write(data);
                uri = Uri.fromFile(media);
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        Log.e(TAG, e.getMessage());
                    }
                }
            }
            resultImg.close();
        } catch (InterruptedException e) {
            Log.e(TAG, e.getMessage());
        }
        storeData.release();

    }
};

这实质上是检索图像的高度和宽度,然后将其写入文件。发送到下一个活动的数据包括:图像宽度、图像高度、图像旋转和指向文件的 Uri。

使用它,我尝试使用 Firebase ML Kit 检测条形码:

// uri is the uri referencing the saved image
File f = new File(uri.getPath());
data = new byte[(int) f.length()];

try{
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
        DataInputStream dis = new DataInputStream(bis);
        dis.readFully(data);
    } catch (IOException e) {
        Log.e(TAG, e.getMessage());
    }

FirebaseVisionBarcodeDetectorOptions options = new FirebaseVisionBarcodeDetectorOptions.Builder().setBarcodeFormats(
            FirebaseVisionBarcode.FORMAT_QR_CODE,
            FirebaseVisionBarcode.FORMAT_DATA_MATRIX
    ).build();

FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options);
FirebaseVisionImage image;

int rotationResult;
        switch (imgRotation) {
            case 0: {
                rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
                break;
            }
            case 90: {
                rotationResult = FirebaseVisionImageMetadata.ROTATION_90;
                break;
            }
            case 180: {
                rotationResult = FirebaseVisionImageMetadata.ROTATION_180;
                break;
            }
            case 270: {
                rotationResult = FirebaseVisionImageMetadata.ROTATION_270;
                break;
            }
            default: {
                rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
                break;
            }
        }

FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
            .setWidth(imgWidth)
            .setHeight(imgHeight)
            .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
            .setRotation(rotationResult)
            .build();

image = FirebaseVisionImage.fromByteArray(data, metadata);

Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)

标签: javaandroidfirebaseandroid-camera2firebase-mlkit

解决方案


一些东西。

  1. 如果您使用 camera2,您的图像格式不应该是 NV21。请参阅此处了解所有 camera2 支持的图像格式: https://developer.android.com/reference/android/media/Image#getFormat() 您的 byte[] 不是 NV21,您指定了 IMAGE_FORMAT_NV21 并导致错误

  2. 与 camera2 最直观的集成如下所示:

    • 实例化 ImageReader 时指定 JPEG 格式。

    • onImageAvailable 会给你一个 android.media.Image,你可以直接使用 FirebaseVisionImage.fromMediaImage(...) 创建一个 FirebaseVisionImage。(您可以在此处找到如何从官方文档计算轮换信息)

  3. android.media.Image如果您必须执行两个活动,那么您需要解决不可包裹的事实。我建议您先将其转换为可打包的位图,然后您可以直接将其设置为 Intent 额外内容(由您决定。从最终用户的角度考虑,看到条形码保存到我的图片库是不常见的。因此,您可能需要考虑跳过将其保存到文件的步骤)。稍后,在您的第二个活动中,您可以使用FirebaseVisionImage.fromBitmap(...).


推荐阅读