Как приостановить сканирование штрих-кода в Android-ML-kit при использовании ByteBuffer из SurfaceView - PullRequest
0 голосов
/ 04 июля 2018

Контекст

Я использую Android firebase-ml-vision для сканирования штрих-кодов с использованием SurfaceView с непрерывным ByteBuffer кадров изображений. Я использовал проект быстрого старта ML 100 в качестве отправной точки, и он прекрасно работает.

Цель моего проекта - распознать продукт, связанный со штрих-кодом, и добавить его в список отсканированных предметов.

Задача

Как только камера сфокусируется, процессор штрих-кода обнаружит один и тот же штрих-код несколько раз, поэтому вы будете сканировать 20, а не 1 штрих-код в секунду.

Это javadoc из CamereSource.FrameProcessingRunnable.run

 * 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(...

Решение с использованием Stop & Start

Поскольку я не мог заставить его остановиться, я выбрал остановку и запуск при обнаружении штрих-кода из буфера:

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

Это работает, но перед повторным запуском задержка составляет около 1 секунды, камера начинает фокусировку и может быть обнаружен следующий штрих-код. Без сомнения, этот подход также потребляет ненужные ресурсы. Вы можете сказать, что это хорошо, но в этом видео вы увидите разницу между сканером камеры с Stop & Start и сканером Bluetooth :

Лучший подход

Я ищу решение, которое бы просто отбрасывало любые кадры сразу после кадра с успешным обнаружением и запускалось снова, но пока мне не удалось. Я использую 20 кадров в секунду.

VissionProcessorBase имеет код для регулирования

// 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);

Но это не подходит для моей нужды: (

1 Ответ

0 голосов
/ 19 сентября 2018

Как только камера сфокусируется, процессор штрих-кода обнаружит один и тот же штрих-код несколько раз, поэтому вы будете сканировать 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);



}
...