java - ML Kit Vision - 使用内存图像中的camerax进行条形码检测会导致由于 'int android.graphics.Bitmap.getWidth()'而导致空指针异常

标签 java android firebase android-camerax

当我尝试检测内存图像中的条形码时,出现以下错误。 enter image description here

我的相机配置有问题吗?我仍然需要对图像捕获进行一些优化,但我想让条形码检测正常工作。似乎成功捕获图像,并且是 FireBaseVisionImage.FromMediaImage 支持的 jpeg 格式。

相机/扫描仪 Activity

package com.example.kusdinventoryscanner;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;


public class ScannerActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = ScannerActivity.class.getSimpleName();
    private static final int PERMISSIONS_REQUEST_CODE = 42;
    private ImageAnalyzer imageAnalyzer;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private ImageCapture imageCapture;
    private ExecutorService exec;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scanner);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_DENIED)
            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CODE);

        imageAnalyzer = new ImageAnalyzer();
        exec = Executors.newSingleThreadExecutor();

        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                bindPreview(cameraProvider);
            } catch (ExecutionException | InterruptedException e) {
                // No errors need to be handled for this Future.
                // This should never be reached.
            }
        }, ContextCompat.getMainExecutor(this));

        imageCapture =
                new ImageCapture.Builder()
                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                        .build();
    }

    void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
        Preview preview = new Preview.Builder()
                .build();

        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build();

        Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, imageCapture, preview);
        PreviewView previewView = (PreviewView) findViewById(R.id.preview_view);
        preview.setSurfaceProvider(previewView.createSurfaceProvider(camera.getCameraInfo()));
    }

    @Override
    @androidx.camera.core.ExperimentalGetImage
    public void onClick(View v) {
        if (v.getId() == R.id.scan_barcode) {
            Log.d(TAG, "ENTERED CLICK HANDLER");
            imageCapture.takePicture(exec,  new ImageCapture.OnImageCapturedCallback() {
                @Override
                public void onCaptureSuccess(ImageProxy image) {
                    Log.d(TAG, "SUCCESS: Image captured successfully.");
                    imageAnalyzer.analyze(image);
                }
                public void onError(ImageCaptureException e) {
                    Log.d(TAG, "CAPTURE ERROR: " +  e.toString());
                }
            });
        }
    }

    @Override
    protected void onStop() {
        super.onStop();

        exec.shutdown();
    }
}

activity_scanner.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ScannerActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/container"
        android:layout_width="394dp"
        android:layout_height="318dp"
        android:layout_marginTop="32dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.47"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.camera.view.PreviewView
            android:id="@+id/preview_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <Button
        android:id="@+id/scan_barcode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="272dp"
        android:onClick="onClick"
        android:text="@string/scan_image"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/container" />

</androidx.constraintlayout.widget.ConstraintLayout>

分析器

package com.example.kusdinventoryscanner;

import android.media.Image;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetectorOptions;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata;

import java.util.List;

public class ImageAnalyzer implements ImageAnalysis.Analyzer {
    private static final String TAG =  ImageAnalyzer.class.getSimpleName();
    private FirebaseVisionBarcodeDetectorOptions barcodeOptions;

    public ImageAnalyzer() {
        barcodeOptions =
            new FirebaseVisionBarcodeDetectorOptions.Builder()
                    .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_CODE_39)
                    .build();

    }

    private int degreesToFirebaseRotation(int degrees) {
        switch (degrees) {
            case 0:
                return FirebaseVisionImageMetadata.ROTATION_0;
            case 90:
                return FirebaseVisionImageMetadata.ROTATION_90;
            case 180:
                return FirebaseVisionImageMetadata.ROTATION_180;
            case 270:
                return FirebaseVisionImageMetadata.ROTATION_270;
            default:
                throw new IllegalArgumentException(
                        "Rotation must be 0, 90, 180, or 270.");
        }
    }

    @Override
    @androidx.camera.core.ExperimentalGetImage
    public void analyze(ImageProxy imageProxy) {
        if (imageProxy == null || imageProxy.getImage() == null) {
            return;
        }
        Image mediaImage = imageProxy.getImage();
        int rotation = degreesToFirebaseRotation(imageProxy.getImageInfo().getRotationDegrees());
        FirebaseVisionImage image =
                FirebaseVisionImage.fromMediaImage(mediaImage, rotation);

        FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance()
                .getVisionBarcodeDetector(barcodeOptions);

        Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)
                .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>() {
                    @Override
                    public void onSuccess(List<FirebaseVisionBarcode> barcodes) {
                        // Task completed successfully
                        // ...
                        for (FirebaseVisionBarcode barcode: barcodes) {
                            String asset = barcode.getRawValue();
                            Log.d(TAG, "Barcode is: " + asset);
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.d(TAG, "Detect failed.");
                    }
                });
    }
}

最佳答案

我明白了。我必须在 ImageCapture 构建器中将缓冲区格式设置为 YUV_420_888。但它确实给出了关于 Builder.setBufferFormat 只能从同一库组内调用的警告。

imageCapture =
                new ImageCapture.Builder()
                        .setBufferFormat(ImageFormat.YUV_420_888)
                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                        .build();

关于java - ML Kit Vision - 使用内存图像中的camerax进行条形码检测会导致由于 'int android.graphics.Bitmap.getWidth()'而导致空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61752335/

相关文章:

java - Spring Boot 从我的模型和存储库类创建一个库

java - 如何停止textView滚动?

Android 推送通知,当应用程序关闭时,我得到不同的样式

android - 获取太多数据时如何摆脱卡住屏幕

Java 整数与字符串?

java - Maven 找不到本地安装的包

java - 设置简单的struts 1.3项目,在ant范围内找不到bean

android - 如何在android Material 组件中更改工具栏后退按钮图标

android - 按钮和 GLSurfaceView

javascript - 如何阅读 Firebase Node.js 模块?