6

语境

我正在使用 Android firebase-ml-vision使用带有连续 ByteBuffer 相框的 SurfaceView 扫描条形码。我使用ML kit quickstart 项目作为起点,它运行良好。

我的项目的目标是识别与条形码相关的产品并将其添加到扫描项目列表中。

问题

一旦相机对焦,条码处理器将多次检测到同一个条码,因此您将在一秒钟内扫描 20 个而不是 1 个条码。

这是来自CamereSource.FrameProcessingRunnable.run的 javadoc

 * As long as the processing thread is active, this executes detection on frames continuously.
 * The next pending frame is either immediately available or hasn't been received yet. Once it
 * is available, we transfer the frame info to local variables and run detection on that frame.
 * It immediately loops back for the next frame without pausing.

我试图在 FrameProcessingRunnable 中添加一个“暂停”检查,但我仍然得到至少两次识别相同的条形码,因为下一帧/帧已经被输入以进行检测:

private class FrameProcessingRunnable implements Runnable {
private volatile boolean paused = false;
.
.
.
public void pause() {
  synchronized (lock) {
    this.paused = true;
    lock.notifyAll();
  }
}

public void resume() {
  synchronized (lock) {
    this.paused = false;
    lock.notifyAll();
  }
}

public void run() {
.
.
.
synchronized (processorLock) {
        if (!paused) {
          Log.d(TAG, "Process an image");
          frameProcessor.process(...

使用停止和启动的解决方案

因为我无法让它暂停,所以当从缓冲区检测到条形码时,我选择了停止和启动:

private CameraSourcePreview preview;
public void pauseImageProcessing() {
  preview.stop();
  try {
      preview.start(cameraSource, graphicOverlay);
  } catch (IOException e) {
  }
}

这可行,但是在再次启动之前大约有 1 秒的延迟,相机开始对焦并且可以检测到下一个条形码。毫无疑问,这种方法也会消耗不必要的资源。您可能会说这很好,但在本视频中,您将看到带停止和启动的相机扫描仪和蓝牙扫描仪之间的区别

更好的方法

我正在寻找一种解决方案,它可以在成功检测的帧之后立即丢弃任何帧并重新开始,但到目前为止我失败了。我每秒使用 20 帧。

VisionProcessorBase确实有节流代码

// Whether we should ignore process(). This is usually caused by feeding input data faster than
// the model can handle.
private final AtomicBoolean shouldThrottle = new AtomicBoolean(false);

但是对于我的需要还远远不够:(

4

2 回答 2

2

一旦相机对焦,条码处理器将多次检测到同一个条码,因此您将在一秒钟内扫描 20 个而不是 1 个条码。

VisionProcessorBase.java

private void detectInVisionImage(
        FirebaseVisionImage image,
        final FrameMetadata metadata) {

    detectInImage(image)
            .addOnSuccessListener(
                    new OnSuccessListener<T>() {
                        @Override
                        public void onSuccess(final T results) {
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    shouldThrottle.set(false);
                                }
                            },1000);


                            VisionProcessorBase.this.onSuccess(results, metadata);

                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    shouldThrottle.set(false);
                                }
                            },1000);
                            VisionProcessorBase.this.onFailure(e);
                        }
                    });
    // Begin throttling until this frame of input has been processed, either in onSuccess or
    // onFailure.
    shouldThrottle.set(true);



}
于 2018-09-19T10:53:38.180 回答
0

速度减半。

类变量:

private var isLocked = true

扫描:

scanner.process(barcodeImage)
        .addOnSuccessListener { barcodes ->
                isLocked = !isLocked
                if (isLocked) return@addOnSuccessListener //<--return here

            barcodes.forEach { barcode ->
                if (barcode.valueType == Barcode.TYPE_TEXT) {
                    barcode.rawValue?.let { value -> mutableValue.postValue(value) } 
                }
            }
        }
        .addOnCompleteListener {
            image.close()
        }
于 2022-01-25T12:33:08.390 回答