1

所以我要重新开始一个我几个月没有碰过的项目。几天前我在搞砸它,没有任何问题(至少在我之前的最新帖子之后)。不管出于什么原因,今天我去运行它,我已经为这个问题苦苦挣扎了几个小时......

问题:

我正在创建一个 FIrebaseVisionImage 对象以用于各种 ml 视觉任务。

FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);

在此之前非常标准的设置(类似于他们在使用带有 ImageAnalysis.Analyzer 的 CameraX的示例中的设置。无论出于何种原因,我现在遇到了这个我以前没有遇到的错误。

java.lang.ArithmeticException: divide by zero
    at com.google.android.gms.internal.firebase_ml.zzrb.zza(com.google.firebase:firebase-ml-vision@@24.0.0:55)
    at com.google.android.gms.internal.firebase_ml.zzrb.zza(com.google.firebase:firebase-ml-vision@@24.0.0:48)
    at com.google.firebase.ml.vision.common.FirebaseVisionImage.fromMediaImage(com.google.firebase:firebase-ml-vision@@24.0.0:20)
    at com.divertinc.visiondispositiontesting.MainActivity$4.analyze(MainActivity.java:248)

到目前为止我所做的:

好吧,没问题,让我只是堆栈跟踪。我看到这一行:

int var9 = var2 / var8;

是问题。好的,很酷,让我们找出这些值。

让我们向后工作:

  1. 当我调用 fromMediaImage FirebaseVisionImage 它应该返回这个(基于我的图像):

    return new FirebaseVisionImage(zzrb.zza(var2, var0.getWidth(), var0.getHeight()), (new Builder()).setFormat(17).setWidth(var0.getWidth()).setHeight(var0.getHeight()).setRotation(var1).build())
    
  2. K 酷,所以我们知道这里有问题的方法是: zza(Plane[] var0, int var1, int var2)

  3. K 那么接下来的行(就错误而言)是: zza(var0[0], var1, var2, var4, 0, 1);
  4. 然后调用: zza(Plane var0, int var1, int var2, byte[] var3, int var4, int var5)
  5. 最后调用: int var9 = var2 / var8

现在,我是一个 Android Studio 新手,所以我不知道如何在跟踪时获取类文件中的值,所以我回到了创建 FirebaseVisionImage 的位置,就在此之前我这样做了:

Image.Plane var0 = mediaImage.getPlanes()[0];
ByteBuffer var6 = var0.getBuffer();
int var2 = mediaImage.getHeight();
int var8 = (var6.remaining() + var0.getRowStride() - 1) / var0.getRowStride();

Log.d("divide debug: ", String.valueOf(var2));
Log.d("divide debug: ", String.valueOf(var8));
Log.d("divide debug: ", String.valueOf(var6.remaining()));
Log.d("divide debug: ", String.valueOf(var0.getRowStride()));
Log.d("divide debug: ", String.valueOf((var6.remaining() + var0.getRowStride() - 1)));

这导致:

480

0

0

640

639

K 井 639/640 是 0.9.... 现在如果我记得 Java 是如何工作的,int 除法会向下舍入 - 除非我假设明确覆盖?反正。KI 猜想那是完全有道理的。好吧,如果我没记错的话,我从现在到它工作时唯一改变的是依赖升级,我实际上降级了,看看这是否会影响它,在查看发行说明后它不应该有。

编辑:所以我发现实际上当我记录我之前所做的事情时,我注意到之前正在分析 4 帧,结果如下:

日志 1:

480

480

307200

640

307839

日志 2:

480

0

0

640

639

日志 3:

480

480

307200

640

307839

崩溃信息

日志 4:

480

0

0

640

639

我被困在哪里:(

错误发生在第三个日志之后不到 100 毫秒,之后近 300 毫秒,第四个日志被命中。

所以我的假设是缓冲每隔一帧有问题,因为 .remaining() 方法会导致每隔一帧出现 0,这是不应该发生的。不幸的是,我对此知之甚少,所以我想看看是否有人能指出我正确的方向 D:从好的方面来说,我在发布这篇文章的整个过程中学到了很多东西(我在这篇文章上工作了大约45分钟)

下面是我的整个相机功能,我认为它和 D 一样存在很多问题:

private void startCamera() {
    //make sure there isn't another camera instance running before starting
    CameraX.unbindAll();

    /* start preview */
    int aspRatioW = txView.getWidth(); //get width of screen
    int aspRatioH = txView.getHeight(); //get height
    Rational asp = new Rational (aspRatioW, aspRatioH); //aspect ratio
    Size screen = new Size(aspRatioW, aspRatioH); //size of the screen

    //config obj for preview/viewfinder thingy.
    PreviewConfig pConfig = new PreviewConfig.Builder().setTargetResolution(screen).build();
    Preview preview = new Preview(pConfig); //lets build it

    preview.setOnPreviewOutputUpdateListener(
            new Preview.OnPreviewOutputUpdateListener() {
                //to update the surface texture we have to destroy it first, then re-add it
                @Override
                public void onUpdated(Preview.PreviewOutput output){
                    ViewGroup parent = (ViewGroup) txView.getParent();
                    parent.removeView(txView);
                    parent.addView(txView, 0);

                    txView.setSurfaceTexture(output.getSurfaceTexture());
                    updateTransform();
                }
            });

    /* image capture */
            .setTargetRotation(getWindowManager().getDefaultDisplay().getRotation()).build();
    final ImageCapture imgCap = new ImageCapture(imgCapConfig);

    findViewById(R.id.imgCapture).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("image taken", "image taken");
        }
    });

    /* image analyser */

    ImageAnalysisConfig imgAConfig = new ImageAnalysisConfig.Builder().setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE).build();
    ImageAnalysis analysis = new ImageAnalysis(imgAConfig);
    analysis.setAnalyzer(
            Executors.newSingleThreadExecutor(), new ImageAnalysis.Analyzer(){
                @Override
                public void analyze(ImageProxy imageProxy, int degrees){

                    while (weCanAnalyzeFrame) {

                        if (!isMachineLearning) {
                            Log.d("analyze", "just analyzing");
                            if (imageProxy == null || imageProxy.getImage() == null) {
                                Log.d("imageProxy: ", "is null");
                                return;
                            }
                            Image mediaImage = imageProxy.getImage();
                            int rotation = degreesToFirebaseRotation(degrees);
                            Log.d("degrees: ", String.valueOf(degrees));
                            Log.d("rotation: ", String.valueOf(rotation));

                            Image.Plane var0 = mediaImage.getPlanes()[0];
                            ByteBuffer var6 = var0.getBuffer();
                            int var2 = mediaImage.getHeight();
                            int var8 = (var6.remaining() + var0.getRowStride() - 1) / var0.getRowStride();
//                            int var9 = var2 / var8;

                            Log.d("divide debug: ", String.valueOf(var2));
                            Log.d("divide debug: ", String.valueOf(var8));
                            Log.d("divide debug: ", String.valueOf(var6.remaining()));
                            Log.d("divide debug: ", String.valueOf(var0.getRowStride()));
                            Log.d("divide debug: ", String.valueOf((var6.remaining() + var0.getRowStride() - 1)));
                            Log.d("divide debug: ", " ");

                            FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);

                            Log.d("analyze", "isMachineLearning is about to be true");
                            isMachineLearning = true;
                            extractBarcode(image, image.getBitmap());
                        }
                    }
                }
            });

    //bind to lifecycle:
    CameraX.bindToLifecycle(this, analysis, imgCap, preview);
}
4

1 回答 1

0

它看起来像 var6.remaining():yPlane 缓冲区的当前 position() 到 limit() 从崩溃的 mediaImage 为 0。

mediaImage 来自 MLKit 在那里控制的相机。但是,mlkit 绝对应该在除法操作之前检查该值以避免崩溃。我们将对其进行修复。

刚刚从cameraX团队得到确认,这是camerax core beta02中引入的一个错误,修复将在beta04中。

现在,您可以在为 MLKit 创建 InputImage 之前在缓冲区上调用 rewind() 作为解决方法。

谢谢!

于 2020-05-08T17:40:54.340 回答