这标题都是英文,看了一下专业词汇多还真不好写中文。本文的内容是介绍 OpenCV DNN(Deep Neural Networks)模块在 Android 上的使用,运行深度学习模型来做图像的多目标识别。移动设备上基于深度学习的图像识别技术离实际应用还有段距离,不过该技术却有着惊艳的效果。

It's about the network
目标检测

计算机视觉开源软件库 OpenCV 刚升级到了 3.4.1,新版本除了集成了一些补丁和问题修复外,JNI 库也整理得更好了,此外还发现新增了一个使用 Android Camera2 接口的 CameraView (org.opencv.android.JavaCamera2View.java)。但是我在手机上用这个 View 发现画面的色彩不对,想尝鲜的朋友可以调试一下。启用 Camera2 接口应该可以在 Android 上更好的适配硬件加速,将视觉处理大量的浮点计算交给 GPU 去做。

在 Android 手机上(Snapdragon 835 CPU)调用 OpenCV 可以看到以下 logcat 信息,接下来可以参考 OpenCV DNN Toturial 在 App 上使用 DNN。

General configuration for OpenCV 3.4.1 =====================================
  Version control:               3.4.1
  Platform:
    Timestamp:                   2018-02-23T12:15:01Z
    Host:                        Linux 4.13.0-32-generic x86_64
    Target:                      Linux 1 aarch64
    CMake:                       2.8.12.2
    CMake generator:             Ninja
    CMake build tool:            /usr/bin/ninja
    Configuration:               Release
  CPU/HW features:
    Baseline:                    NEON
      requested:                 NEON FP16
      required:                  NEON
      disabled:                  VFPV3
  C/C++:
    ... 此处内容太多已省略
  OpenCV modules:
    To be built:                 calib3d core dnn features2d flann highgui imgcodecs imgproc java java_bindings_generator ml objdetect photo python_bindings_generator shape stitching superres video videoio videostab
    Disabled:                    js world
    Disabled by dependency:      -
    Unavailable:                 cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev python2 python3 ts viz
    Applications:                android_examples
    Documentation:               NO
    Non-free algorithms:         NO
  Android: 
    Android ABI:                 arm64-v8a
    STL type:                    gnustl_static
    Native API level:            android-21
    SDK target:                  android-21
    Android NDK:                 /opt/android/android-ndk-r10e (toolchain: aarch64-linux-android-4.9)
    android tool:                /opt/android/android-sdk-java7/tools/android (Android SDK Tools, revision 25.2.2.)
    ... 后面已省略

OpenCV DNN 模块可以读取多种深度学习框架的网络模型,生成 DNN 的网络对象(DNN 不支持模型训练)。模型文件放到 assets 打包进 APK,运行时复制(一次)到 App 目录后 DNN 就可以读取。Java API 的注释少,这里是打开 C++ API 来看看读取 Caffe 模型的说明。

It's about the network
读取模型
/** @brief Reads a network model stored in <a href="http://caffe.berkeleyvision.org">Caffe</a> framework's format.
    * @param prototxt   path to the .prototxt file with text description of the network architecture.
    * @param caffeModel path to the .caffemodel file with learned network.
    * @returns Net object.
    */
CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String());

在摄像头图像帧里运行模型计算输出,标注识别结果。可以参考官方 Toturial,3.4.1 版本需要做一点小修改,代码如下。

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    // Get a new frame
    Mat frame = inputFrame.rgba();
    Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);

    // Forward image through network.
    Mat blob = Dnn.blobFromImage(frame, IN_SCALE_FACTOR,
            new Size(IN_WIDTH, IN_HEIGHT),
            new Scalar(MEAN_VAL, MEAN_VAL, MEAN_VAL), false, false);
    mNet.setInput(blob);
    Mat detections = mNet.forward();

    ...
}

下面有个演示视频,手机摄像头现实场景的图像识别,输出结果的标注代码稍微改了一下,看起来更加明显一点。MobileNetSSD 模型的物体较少大概 20 个,所以有些目标识别可能会不对,但这不是问题换个模型就可以。

参考资料

MobileNet https://arxiv.org/abs/1704.04861
Caffe https://caffe.berkeleyvision.org/
OpenCV DNN https://github.com/opencv/opencv/tree/master/samples/dnn