I am trying to run inference with tensorflow android on a darkflow yolo model. I could successfully ran on the default tiny-yolo-voc model, but when I change my model (and it's parameters accordingly) to the yolo one, I get the following exception:
java.lang.RuntimeException: Unable to resume activity {com.bendaf.tfdroidtest/com.bendaf.tfdroidtest.MainActivity}: java.lang.IllegalArgumentException: No OpKernel was registered to support Op 'ExtractImagePatches' with these attrs. Registered devices: [CPU], Registered kernels:
<no registered kernels>
[[Node: ExtractImagePatches = ExtractImagePatches[T=DT_FLOAT, ksizes=[1, 2, 2, 1], padding="VALID", rates=[1, 1, 1, 1], strides=[1, 2, 2, 1]](47-leaky)]]
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3841)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3882)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1639)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6780)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.IllegalArgumentException: No OpKernel was registered to support Op 'ExtractImagePatches' with these attrs. Registered devices: [CPU], Registered kernels:
<no registered kernels>
[[Node: ExtractImagePatches = ExtractImagePatches[T=DT_FLOAT, ksizes=[1, 2, 2, 1], padding="VALID", rates=[1, 1, 1, 1], strides=[1, 2, 2, 1]](47-leaky)]]
at org.tensorflow.Session.run(Native Method)
at org.tensorflow.Session.access$100(Session.java:48)
at org.tensorflow.Session$Runner.runHelper(Session.java:295)
at org.tensorflow.Session$Runner.run(Session.java:245)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.run(TensorFlowInferenceInterface.java:143)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.run(TensorFlowInferenceInterface.java:112)
at com.bendaf.tfdroidtest.inference.InferenceRunner.runInference(InferenceRunner.java:44)
at com.bendaf.tfdroidtest.MainActivity.runInferenceWithTiming(MainActivity.java:65)
at com.bendaf.tfdroidtest.MainActivity.onResume(MainActivity.java:59)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1277)
at android.app.Activity.performResume(Activity.java:7094)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3818)
... 10 more
I assume regarding to this issue comment, that the ExtracImagePatches operator was not recognized by tensorflow. But how can I make tensorflow recognize it on my android device?
What I did so far:
- generated the yolo.pb file with darkflow from the yolo.cfg according to this. (With the same command I generated the tiny-yolo-voc.pb):
$ ./flow --model cfg/yolo.cfg --load bin/yolo.weights --savepb --verbalise
- optimized the yolo.pb file according to this possible solution and placed it to my android project's assets folder:
$ bazel-bin/tensorflow/tools/graph_transforms/transform_graph --in_graph=../darkflow/darkflow/built_graph/yolo.pb --out_graph=../android/test/TfDroidTest/app/src/main/assets/optimized_yolo.pb --inputs='input' --outputs='output' --transforms='strip_unused_nodes(type=float, shape="1,2,2,1") fold_constants(ignore_errors=true) fold_batch_norms fold_old_batch_norms'
Modified my
tensorflow/contrib/makefile/tf_op_files.txt
to contain the linetensorflow/core/kernels/extract_image_patches_op.cc
according to this.Rebuilt android tensorflow with these commands:
$ cd tensorflow/contrib/makefile/ && ./build_all_android.sh && cd -
$ ./configure
$ bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so --crosstool_top=//external:android/crosstool --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cpu=arm64-v8a
$ bazel build //tensorflow/contrib/android:android_tensorflow_inference_java
and added the .so and .jar files to my android project.
Rebuilt and deploy my android project with native support. Here is the relevant part of my InferenceRunner.java:
mInferenceInterface.feed(INPUT_NODE, floatValues, 1, mInputSize, mInputSize, 3); mInferenceInterface.run(new String[]{OUTPUT_NODE}); final float[] resu = new float[mGridSize * mGridSize * (mNumOfLabels + 5) * 5]; mInferenceInterface.fetch(OUTPUT_NODE, resu);
the exception is thrown in the second line. As I mentioned above, this works with the tiny-yolo-voc model, but not with the yolo model.
I am on Ubuntu 16.04, android API level 24. If you need any more info, feel free to comment. Thank you for your time!