对于相同的“解释器”实例,相同图像的分数会增加,直到达到某种饱和度。
Interpreter tflite = new Interpreter(loadModelFile(context));
为 ImageClassifier 创建实例并使用相同的实例对 Frame 进行分类并为同一图像运行推理。
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);
}
ClassifyFrame() 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;
}
ImageClassifier.java 的 applyFilter() 方法
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]);
}
}
打印前 K 个标签,作为结果显示在 UI 中。
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,然后如果我们在某些事件上调用分类图像(),点击得分再次增加到 0.13,并且在相同的过程中它不断增加,直到达到 0.86(饱和度)。
我不确定它为什么会发生,但它发生在两种类型的 TfLite 模型 inceptionV3 和 MobileNet 上。