使用opencv-dnn移植caffe-model到安卓手机上

opencv3.3.0+添加了dnn模块,支持常用的深度学习框架,如caffe、tf、torch、mxnet等,本博客主要是使用opencv的dnn模块,移植训练好的caffe model到安卓手机上,主要参照官放教程,以及自己的一些改动,https://docs.opencv.org/3.4.0/d0/d6c/tutorial_dnn_android.html。

在进行移植之前,需要做几个准备工作:

1.选择一个移动端的深度学习框架,如ncnn、mace、tf-lite等,这里我使用的是opencv-android,需要下载opencv-android-sdk,https://github.com/opencv/opencv/releases;

2.pc上训练好的网络模型,这里我使用的是caffe版的ssd_mobilenet_v1,下载地址https://github.com/chuanqi305/MobileNet-SSD;

3.ubuntu下安卓的开发环境配置。

实现步骤如下:

1.打开Android Studio,新建一个工程,Let's call it opencv_mobilenet,默认设置;

2.添加opencv库,File->New->Import module,路径unpacked_OpenCV_package/sdk/java,

使用opencv-dnn移植caffe-model到安卓手机上_第1张图片

  • 打开如下两个文件:

    1. AndroidStudioProjects/opencv_mobilenet/app/build.gradle
    2. AndroidStudioProjects/opencv_mobilenet/openCVLibrary330/build.gradle

    修改 compileSdkVersionbuildToolsVersion (根据自己的环境修改)

    compileSdkVersion 14 -> compileSdkVersion 26

    buildToolsVersion "25.0.0" -> buildToolsVersion "26.0.1"

  • File->Project Structure. 添加 OpenCV module .

使用opencv-dnn移植caffe-model到安卓手机上_第2张图片

使用opencv-dnn移植caffe-model到安卓手机上_第3张图片

至此,安卓上的opencv环境就配置好了。

3.Make a sample

  • 修改app/src/main/res/layout/activity_main.xml;
  • 将下载好的caffe model, MobileNetSSD_deploy.prototxtMobileNetSSD_deploy.caffemodel 复制到路径app/build/intermediates/assets/debug 下;
  • 修改 /app/src/main/AndroidManifest.xml;
  • 修改java主程序,app/src/main/java/org/opencv/samples/opencv_mobilenet/MainActivity.java

4.编译工程,生成app,就可以安装到手机上了。

以上是官方的教程,如果直接按照以上步骤,会发生,除了自己编译生成的app外,还会在手机上安装opencv package的app,打开自己编译生成的app,会提示找不到opencv package,即使已经安装了opencv package的app,因此,我这里将opencv-android的库文件一起打包到app中,但是这样会导致一个问题,编译生成的app文件会比较大。

具体过程,参照https://blog.csdn.net/tobacco5648/article/details/51615434:

  • 在安卓工程 /app/src/main/ 下创建一个 jniLibs 文件夹,再将 OpenCV Android SDKsdk/native/libs 下的所有文件夹复制到创建的 jniLibs 目录下。( armeabi-v7a,是目前大多数手机支持的架构,app/src/main/jniLibsAndroid Studio 存放jni库的默认目录,可以在app的 build.gradle 文件中通过 jniLibs.srcDir 指定其他目录 )

  • 同步Gradle, 完成配置。

现在我们回头看一下java主程序中的关键代码,MainActivity.java下的public Mat onCameraFrame(CvCameraViewFrame inputFrame)函数,用opencv部署caffe model主要用到了三个主要的函数,Dnn.readNetFromCaffe(proto, weights),读取网络

Dnn.blobFromImage(frame, IN_SCALE_FACTOR,new Size(IN_WIDTH, IN_HEIGHT),new Scalar(MEAN_VAL, MEAN_VAL, MEAN_VAL), false),mat格式的image转blob,net.forward(),前向计算,然后再解析前向计算的结果就ok了。

如果使用的是opencv-3.3.0,会发现结果只识别图像的中间的一部分或者是回归框位置有偏移,左边是pc上的,右边是手机上的,由于手机摄像头有问题,因此就把实时检测改成了检测一张图像,

看下代码,

使用opencv-dnn移植caffe-model到安卓手机上_第4张图片

因为ssd-mobilenet网络的输入是300*300,所以源码中是从中间裁剪出一个300*300的区域进行检测,因此可以先将原始图像缩放到300*300,net.forward()后,解析到检测结果后将坐标框缩放到原来的大小,进行显示就ok了。

当然,如果使用的是opencv-3.4.2,就可以直接对原图进行检测,现在去看一下opencv dnn的源码,

先看下opencv-3.3.0的源码,路径opencv-3.3.0/modules/dnn/src下的dnn.cpp文件,

函数声明

Mat blobFromImages(const std::vector& images_, double scalefactor, Size size,
                   const Scalar& mean_, bool swapRB)

实现:

使用opencv-dnn移植caffe-model到安卓手机上_第5张图片

再看下opencv-3.4.2的源码,路径opencv-3.4.2/modules/dnn/src下的dnn.cpp文件,

函数声明

void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalefactor,
                    Size size, const Scalar& mean_, bool swapRB, bool crop)

实现:

使用opencv-dnn移植caffe-model到安卓手机上_第6张图片

对比3.3.0和3.4.2可以看到blobFromImages函数增加了bool crop参数,因此使用3.4.2的时候直接设置bool crop=false。

这里是将图像缩放到300*300后进行检测的结果。

使用opencv-dnn移植caffe-model到安卓手机上_第7张图片

当然,也可以把ssd-mobilenet换成如ssd-vgg16网络,但是速度会很慢,或者其他的一些目标检测网络。

后期可以考虑使用更小的移动端框架,如腾讯的ncnn、小米的mace等。

 

 

 

你可能感兴趣的:(caffe之旅,移动端深度学习)