Оценка классификации изображения TfLite не соответствует, она продолжает увеличиваться для того же изображения, пока не достигнет некоторой насыщенности (фактическая оценка)

С одним и тем же экземпляром оценка "переводчика" увеличивается для того же изображения, пока не достигнет некоторой насыщенности.

Interpreter tflite = new Interpreter(loadModelFile(context));

Создайте экземпляр для ImageClassifier и используйте тот же экземпляр, чтобы классифицировать кадр и выполнить вывод для того же изображения.

ImageClassifier(Activity activity) throws IOException {
    tflite = new Interpreter(loadModelFile(activity));
    labelList = loadLabelList(activity);
    imgData =
        ByteBuffer.allocateDirect(
            DIM_BATCH_SIZE
                * getImageSizeX()
                * getImageSizeY()
                * DIM_PIXEL_SIZE
                * getNumBytesPerChannel());
    imgData.order(ByteOrder.nativeOrder());
    filterLabelProbArray = new float[FILTER_STAGES][getNumLabels()];
    Log.d(TAG, "Created a Tensorflow Lite Image Classifier.");
  }

Классифицирует кадр для того же изображения. Такое же изображение можно получить с SD-карты.

private void classifyImage() {
    if (classifier == null || getActivity() == null || cameraDevice == null) {
      showToast("Uninitialized Classifier or invalid context.");
      return;
    }
    String imgPath =  "/storage/emulated/0/DCIM/test.jpg";
    Log.d("Image Path is %s", imgPath);
    Bitmap bitmap = BitmapFactory.decodeFile(imgPath);
    Bitmap newbitmap = Bitmap.createScaledBitmap(bitmap, 299, 299, false);
    String textToShow = classifier.classifyFrame(newbitmap);
    bitmap.recycle();
    showToast(textToShow);
  }

classify Frame () Метод ImageClassifier.java

String classifyFrame(Bitmap bitmap) {
    if (tflite == null) {
      Log.e(TAG, "Image classifier has not been initialized; Skipped.");
      return "Uninitialized Classifier.";
    }
    convertBitmapToByteBuffer(bitmap);
    // Here's where the magic happens!!!
    long startTime = SystemClock.uptimeMillis();
    runInference();
    long endTime = SystemClock.uptimeMillis();
    Log.d(TAG, "Timecost to run model inference: " + Long.toString(endTime - startTime));

    // Smooth the results across frames.
    applyFilter();

    // Print the results.
    String textToShow = printTopKLabels();
    textToShow = Long.toString(endTime - startTime) + "ms" + textToShow;
    return textToShow;
  }

applyFilter () метод ImageClassifier.java

void applyFilter() {
    int numLabels = getNumLabels();

    // Low pass filter `labelProbArray` into the first stage of the filter.
    for (int j = 0; j < numLabels; ++j) {
      filterLabelProbArray[0][j] +=
          FILTER_FACTOR * (getProbability(j) - filterLabelProbArray[0][j]);
    }
    // Low pass filter each stage into the next.
    for (int i = 1; i < FILTER_STAGES; ++i) {
      for (int j = 0; j < numLabels; ++j) {
        filterLabelProbArray[i][j] +=
            FILTER_FACTOR * (filterLabelProbArray[i - 1][j] - filterLabelProbArray[i][j]);
      }
    }

    // Copy the last stage filter output back to `labelProbArray`.
    for (int j = 0; j < numLabels; ++j) {
      setProbability(j, filterLabelProbArray[FILTER_STAGES - 1][j]);
    }
  }

Печатает метки top-K, которые будут отображаться в пользовательском интерфейсе в качестве результатов.

  private String printTopKLabels() {
    for (int i = 0; i < getNumLabels(); ++i) {
      sortedLabels.add(
          new AbstractMap.SimpleEntry<>(labelList.get(i), getNormalizedProbability(i)));
      if (sortedLabels.size() > RESULTS_TO_SHOW) {
        sortedLabels.poll();
      }
    }
    String textToShow = "";
    final int size = sortedLabels.size();
    for (int i = 0; i < size; ++i) {
      Map.Entry<String, Float> label = sortedLabels.poll();
      textToShow = String.format("\n%s: %4.2f", label.getKey(), label.getValue()) + textToShow;
    }
    return textToShow;
  }

В первый раз, когда приложение запускает счет, классификация изображений равна 0,06, а затем снова, если мы вызвали classifyImage() для какого-то события, клик-рейтинг увеличивается до 0,13, и с тем же процессом он продолжает увеличиваться, пока не достигнет 0,86(насыщение).

Я не уверен, почему это происходит, но это произошло для обоих типов моделей TfLite - V3 и MobileNet.

1 ответ

Результаты фильтруются по applyFilter метод. Это простой фильтр нижних частот, поэтому оценки постепенно приходят к среднесрочному среднему значению. Закомментируйте звонок applyFilter и он должен реагировать мгновенно, но, возможно, слишком нервный для некоторых приложений.

Другие вопросы по тегам