【问题标题】:(Android/Tensorflow) Activity crashes when opening CameraActivity(Android/Tensorflow) 打开CameraActivity时Activity崩溃
【发布时间】:2018-01-30 00:14:43
【问题描述】:

我正在使用 Tensorflow 创建一个 Android 图像分类应用程序。当我尝试运行CameraActivity.java 时,活动崩溃了。我已参考此链接来开发我的应用程序https://github.com/MindorksOpenSource/AndroidTensorFlowMachineLearningExample。我不知道出了什么问题,请问我应该如何解决这个问题?

Logcat 错误:Could not load vendor/lib/egl/libGLES_mali_v2.so from sphal namespace: dlopen failed: library "vendor/lib/egl/libGLES_mali_v2.so" not found.

调试错误:

FATAL EXCEPTION: pool-1-thread-1
              Process: com.example.nicholas.herb_recognition_test, PID: 15136
              java.lang.RuntimeException: Error initializing TensorFlow!
                  at CameraActivity$5.run(CameraActivity.java:122)

调试错误行:classifier = TensorFlowImageClassifier.create

错误:java.util.concurrent.ThreadPoolExecutor.runWorker

CameraActivity.java

public class CameraActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    cameraView = (CameraView) findViewById(R.id.cameraView);
    imageViewResult = (ImageView) findViewById(R.id.imageViewResult);
    textViewResult = (TextView) findViewById(R.id.textViewResult);
    textViewResult.setMovementMethod(new ScrollingMovementMethod());

    btnToggleCamera = (Button) findViewById(R.id.btnToggleCamera);
    btnDetectObject = (Button) findViewById(R.id.btnDetectObject);

    cameraView.setCameraListener(new CameraListener() {
        @Override
        public void onPictureTaken(byte[] picture) {
            super.onPictureTaken(picture);

            Bitmap bitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length);

            bitmap = Bitmap.createScaledBitmap(bitmap, INPUT_SIZE, INPUT_SIZE, false);

            imageViewResult.setImageBitmap(bitmap);

            final List<Classifier.Recognition> results = classifier.recognizeImage(bitmap);

            textViewResult.setText(results.toString());
        }
    });

    btnToggleCamera.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            cameraView.toggleFacing();
        }
    });

    btnDetectObject.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            cameraView.captureImage();
        }
    });

    initTensorFlowAndLoadModel();
}
private void initTensorFlowAndLoadModel() {
    executor.execute(new Runnable() {
        @Override
        public void run() {
            try {
                classifier = TensorFlowImageClassifier.create(
                        getAssets(),
                        MODEL_FILE,
                        LABEL_FILE,
                        INPUT_SIZE,
                        IMAGE_MEAN,
                        IMAGE_STD,
                        INPUT_NAME,
                        OUTPUT_NAME);
                makeButtonVisible();
            } catch (final Exception e) {
                throw new RuntimeException("Error initializing TensorFlow!", e);
            }
        }
    });
}
}

TensorFlowImageClassifier.java

public class TensorFlowImageClassifier implements Classifier {
public static Classifier create(
        AssetManager assetManager,
        String modelFilename,
        String labelFilename,
        int inputSize,
        int imageMean,
        float imageStd,
        String inputName,
        String outputName)
        throws IOException {
    TensorFlowImageClassifier c = new TensorFlowImageClassifier();
    c.inputName = inputName;
    c.outputName = outputName;

    // Read the label names into memory.
    // TODO(andrewharp): make this handle non-assets.
    String actualFilename = labelFilename.split("file:///android_asset/")[1];
    Log.i(TAG, "Reading labels from: " + actualFilename);
    BufferedReader br = null;
    br = new BufferedReader(new InputStreamReader(assetManager.open(actualFilename)));
    String line;
    while ((line = br.readLine()) != null) {
        c.labels.add(line);
    }
    br.close();

    c.inferenceInterface = new TensorFlowInferenceInterface();
    if (c.inferenceInterface.initializeTensorFlow(assetManager, modelFilename) != 0) {
        throw new RuntimeException("TF initialization failed");
    }
    // The shape of the output is [N, NUM_CLASSES], where N is the batch size.
    int numClasses =
            (int) c.inferenceInterface.graph().operation(outputName).output(0).shape().size(1);
    Log.i(TAG, "Read " + c.labels.size() + " labels, output layer size is " + numClasses);

    // Ideally, inputSize could have been retrieved from the shape of the input operation.  Alas,
    // the placeholder node for input in the graphdef typically used does not specify a shape, so it
    // must be passed in as a parameter.
    c.inputSize = inputSize;
    c.imageMean = imageMean;
    c.imageStd = imageStd;

    // Pre-allocate buffers.
    c.outputNames = new String[]{outputName};
    c.intValues = new int[inputSize * inputSize];
    c.floatValues = new float[inputSize * inputSize * 3];
    c.outputs = new float[numClasses];

    return c;
}

@Override
public List<Recognition> recognizeImage(final Bitmap bitmap) {
    // Log this method so that it can be analyzed with systrace.
    Trace.beginSection("recognizeImage");

    Trace.beginSection("preprocessBitmap");
    // Preprocess the image data from 0-255 int to normalized float based
    // on the provided parameters.
    bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
    for (int i = 0; i < intValues.length; ++i) {
        final int val = intValues[i];
        floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd;
        floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd;
        floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd;
    }
    Trace.endSection();

    // Copy the input data into TensorFlow.
    Trace.beginSection("fillNodeFloat");
    inferenceInterface.fillNodeFloat(
            inputName, new int[]{1, inputSize, inputSize, 3}, floatValues);
    Trace.endSection();

    // Run the inference call.
    Trace.beginSection("runInference");
    inferenceInterface.runInference(outputNames);
    Trace.endSection();

    // Copy the output Tensor back into the output array.
    Trace.beginSection("readNodeFloat");
    inferenceInterface.readNodeFloat(outputName, outputs);
    Trace.endSection();

    // Find the best classifications.
    PriorityQueue<Recognition> pq =
            new PriorityQueue<Recognition>(
                    3,
                    new Comparator<Recognition>() {
                        @Override
                        public int compare(Recognition lhs, Recognition rhs) {
                            // Intentionally reversed to put high confidence at the head of the queue.
                            return Float.compare(rhs.getConfidence(), lhs.getConfidence());
                        }
                    });
    for (int i = 0; i < outputs.length; ++i) {
        if (outputs[i] > THRESHOLD) {
            pq.add(
                    new Recognition(
                            "" + i, labels.size() > i ? labels.get(i) : "unknown", outputs[i], null));
        }
    }
    final ArrayList<Recognition> recognitions = new ArrayList<Recognition>();
    int recognitionsSize = Math.min(pq.size(), MAX_RESULTS);
    for (int i = 0; i < recognitionsSize; ++i) {
        recognitions.add(pq.poll());
    }
    Trace.endSection(); // "recognizeImage"
    return recognitions;
}

@Override
public void enableStatLogging(boolean debug) {
    inferenceInterface.enableStatLogging(debug);
}

@Override
public String getStatString() {
    return inferenceInterface.getStatString();
}

@Override
public void close() {
    inferenceInterface.close();
}

}

【问题讨论】:

  • 知道实际的异常是什么吗?您只发布了堆栈跟踪的第一行。
  • @urgentx 我已经更新了我的问题
  • 检查清单您是否添加了权限或在运行时允许>21 api
  • @Manifest 我已添加相机权限
  • 听起来您的操作系统中缺少一些本机库,或者您的处理器架构不受支持:github.com/mari-linhares/mnist-android-tensorflow/issues/1

标签: java android tensorflow


【解决方案1】:

我的模型文件似乎与TensorFlowImageClassifier.java中实现的架构模型存在一些兼容性问题。

【讨论】:

  • 解决办法是什么?
【解决方案2】:

只需将 INPUT_NAME 和 OUTPUT_NAME 更改为:

private static final String INPUT_NAME = "Mul";
private static final String OUTPUT_NAME = "final_result";

它对我有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多