下载地址
chmod +x bazel-version-installer-os.sh
/bazel-version-installer-os.sh --user
git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git
进入tensorflow目录并configure, 按照提示选择即可
cd tensorflow
./configure
bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
注意configure之前应当检查LD_LIBRARY_PATH等环境变量,不正确的环境变量可能会导致错误
生成python安装包并安装。如果系统中已安装其他版本的tensorflow,此步骤会覆盖系统版本。如果仅编译Android版本,则此步骤可省略
mkdir /tmp/tensorflow_pkg
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
python -m pip install /tmp/tensorflow_pkg/tensorflow-0.10.0-py2-none-any.whl
修改tensorflow/WORKSPACE,将以下内容注释去掉,并填入正确的Android Studio路径
需要保证sdk和ndk均已正确安装, 并且sdk路径、api的版本、build tool、ndk版本都需要与已安装的版本完全一致
android_sdk_repository(
name = "androidsdk",
api_level = 23,
build_tools_version = "23.0.3",
# Replace with path to Android SDK on your system
path = "/home/yaochuanqi/Android/Sdk",
)
android_ndk_repository(
name="androidndk",
path="/home/yaochuanqi/Android/Sdk/ndk-bundle",
api_level=21)
下载weight文件解压到assets目录
Inceptionv5下载地址
下载后的inceptionv5是用于物体识别分类(TF Classify)的weight,其他两个应用(transfer style、detection)的weight给出的链接并不正确。
使用bazel命令行进行编译,加上–verbose_failures是为了在编译出错时查看详细信息
bazel build --verbose_failures -c opt //tensorflow/examples/android:tensorflow_demo
如果执行成功,则会在生成安装包在bazel-bin/tensorflow/examples/android/tensorflow_demo.apk
首先保证前面的编译均没有问题,也就是能够使用bazel正确编译
然后修改tensorflow/examples/android/build.gradle文件,将bazel的位置填入
def bazel_location = '/home/yaochuanqi/bin/bazel'
使用Android Studio 导入该工程,并打开build.gradle
在task copyNativeLibs处右键,run gradle:copyNativeLibs生成libtensorflow_demo.so,大概需要10分钟时间。
如果编译没有问题的话,就可以正常build apk了。安装后,运行TF Classify可以识别摄像头拍摄到的物体。
如果需要在自己的项目中使用tensorflow,只需要将上一步编译好libtensorfow_demo.so
以及demo程序中的
org/tensorflow/contrib/android/TensorFlowInferenceInterface.java
org/tensorflow/demo/Classifier.java
org/tensorflow/demo/TensorFlowImageClassifier.java
assets/imagenet_comp_graph_label_strings.txt
assets/tensorflow_inception_graph.pb
三个文件加入到工程中的正确目录即可使用tensorflow的图像分类功能。
public class MainActivity extends Activity {
private static final int NUM_CLASSES = 1008;
private static final int INPUT_SIZE = 224;
private static final int IMAGE_MEAN = 117;
private static final float IMAGE_STD = 1;
private static final String INPUT_NAME = "input:0";
private static final String OUTPUT_NAME = "output:0";
private static final String MODEL_FILE = "file:///android_asset/tensorflow_inception_graph.pb";
private static final String LABEL_FILE = "file:///android_asset/imagenet_comp_graph_label_strings.txt";
private Classifier classifier;
private Bitmap cropImageAndResize(Bitmap srcBmp)
{
Bitmap dst;
if (srcBmp.getWidth() >= srcBmp.getHeight()){
dst = Bitmap.createBitmap(
srcBmp,
srcBmp.getWidth()/2 - srcBmp.getHeight()/2,
0,
srcBmp.getHeight(),
srcBmp.getHeight()
);
}else{
dst = Bitmap.createBitmap(
srcBmp,
0,
srcBmp.getHeight()/2 - srcBmp.getWidth()/2,
srcBmp.getWidth(),
srcBmp.getWidth()
);
}
return Bitmap.createScaledBitmap(dst.copy(Bitmap.Config.ARGB_8888,true), INPUT_SIZE, INPUT_SIZE, false);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
classifier =
TensorFlowImageClassifier.create(
getAssets(),
MODEL_FILE,
LABEL_FILE,
NUM_CLASSES,
INPUT_SIZE,
IMAGE_MEAN,
IMAGE_STD,
INPUT_NAME,
OUTPUT_NAME);
} catch (final Exception e) {
throw new RuntimeException("Error initializing TensorFlow!", e);
}
InputStream is = getResources().openRawResource(R.raw.example);
Bitmap bitmap = BitmapFactory.decodeStream(is);
final List results = classifier.recognizeImage(cropImageAndResize(bmp));
if(results.size()>0) {
String title = results.get(0).getTitle();
system.out.println(title);
}
}
}