【问题标题】:zzrb.zza resulting in a divide by zero arithmetic exception for every other cameraX analyzer.analyze framezzrb.zza 导致每个其他 cameraX analyzer.analyze 帧除以零算术异常
【发布时间】:2020-04-30 03:08:15
【问题描述】:

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

问题:

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

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

在此之前相当标准的设置(类似于他们在 their example 中使用带有 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. 很酷,所以我们知道这里的方法是: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 除法会向下取整——除非我假设明确覆盖? 反正。 K 我想那是完全有道理的。 好吧,如果我没记错的话,我从现在到它工作时唯一改变的是依赖升级,我实际上降级了,看看这是否会影响它,在查看发行说明后它不应该有。

编辑:所以我发现实际上当我记录我之前所做的事情时,我注意到之前正在分析 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);
}

【问题讨论】:

    标签: android firebase firebase-mlkit android-camerax google-mlkit


    【解决方案1】:

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

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

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

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

    谢谢!

    【讨论】:

    • 您好!我试图在我的 Camera x ImageAnalysis 中使用两个 mlkit api 我想做一个文本识别器和一些图像标签。但是,当我同时使用它们时,我得到 E/ODAutoMLImgLabelerTask: No image data found 如果我尝试为每个 Analysis 提供其自己的 VisionImage 我也会得到错误 java.lang.ArithmeticException: 除以零有什么想法吗?我的基本 ImageAnayser 示例...gist.github.com/aidanmack/a2d1cc2182d38f39e059efe778858b02
    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    相关资源
    最近更新 更多