FastCVをAndroid Studioでビルドする

FastCVをSnapdragonを搭載したAndroidで使ってみる。ビルドにはAndroid Studioを使った。

# [FastCV](https://developer.qualcomm.com/software/fastcv-sdk)とは
Qualcomm版OpenCVに相当するFastCV Computer Vision SDK。
画像処理に必要な演算がSnapdragonのチップセットに最適化されている。

# 動作確認環境
* FastCV SDK, version 1.7.1
* Android Studio 3.1.3
* Build #AI-173.4819257, built on June 5, 2018
* JRE: 1.8.0_152-release-1024-b01 x86_64
* JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
* macOS High Sierra, version.10.13.6
* Moto G5 Plus, Android 7.0

# セットアップ
1. NDKをインストール
 * Android Studioの"Tools"-"SDK Manager"→ダイアログが開く→"SDK Tools"タブ→"NDK"にチェックしてOKでインストールが開始される。
 * NDKは`~/Library/Android/sdk/ndk-bundle`にインストールされる。
2. [Java for OS X 2017-001 (レガシー Java 6 ランタイム)](https://support.apple.com/kb/DL1572?locale=ja_JP)をダウンロード、インストール
3. [FastCV SDK](https://developer.qualcomm.com/software/fastcv-sdk)をダウンロード・インストール
 * なぜかインストーラが起動しないので、右クリックしてContentsを表示して、fastcv-installer-android-1-7-1.app/Contents/MacOS/fastcv-installer-android-1-7-1 を起動したらインストーラが動いた。
 * `~/Android/Development/fastcv-android-1-7-1`にSDKが保存された。
   
 ```
$ tree -L 2
.
├── ReleaseNotes.pdf
├── inc
│   └── fastcv.h
├── lib
│   ├── Android
│   ├── License.txt
│   ├── Notice.txt
│   ├── VS2010
│   ├── VS2012
│   └── VS2013
└── samples
    ├── fastcorner
    ├── fastcvdemo
    └── loadjpeg
```

# サンプルアプリのビルド

fastcornerをビルドする。

-1. fastcorner Eclipseプロジェクトのインポート

 * Android Studioの"File"-"New"-"Import Project..."から、`~/Android/Development/fastcv-android-1-7-1/samples/fastcorner`をインポートする。ここでは`~/source/fastcorner`に新しいプロジェクトができたものとする。

-2. インポートエラー修正

 * "Messages"タブに出てくる"Add Google Maven repository and sync project"をクリックする。

-3. fastcv.hとlibfastcv.aを新規作成された"~/source/fastcorner"に配置
  
| コピーファイル | コピー元 | コピー先 |
|:------------:|:-----:|:-----:|
| fastcv.h | ~/Android/Development/fastcv-android-1-7-1/inc/fastcv.h | ~/source/fastcorner/app/src/main/jni/fastcv/fastcv.h |
| libfastcv.a (32bit) | ~/Android/Development/fastcv-android-1-7-1/lib/Android/lib32/libfastcv.a | ~/source/fastcorner/app/src/main/libs/armeabi-v7a/libfastcv.a |
| libfastcv.a (64bit) | ~/Android/Development/fastcv-android-1-7-1/lib/Android/lib64/libfastcv.a | ~/source/fastcorner/app/src/main/libs/arm64-v8a/libfastcv.a |

-5. build.gradle (Module: app)のndkを修正

```
ndk {
            moduleName "libfastcvsample"
            abiFilters 'armeabi-v7a', 'arm64-v8a'
}
```

-6. Android.mkを以下のように修正して"Sync Now"

 * LOCAL_SHARED_LIBRARIES := liblog libGLESv2 をコメントアウト
 * include $(CLEAR_VARS) を追加
 * LOCAL_MODULE    := libfastcv を追加
 * LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libfastcv.a を追加
 * LOCAL_LDLIBSから-lfastcvを削除

```
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := libfastcv
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libfastcv.a

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE:= false

# This variable determines the OpenGL ES API version to use:
# If set to true, OpenGL ES 1.1 is used, otherwise OpenGL ES 2.0.

USE_OPENGL_ES_1_1 := false

# Set OpenGL ES version-specific settings.

ifeq ($(USE_OPENGL_ES_1_1), true)
    OPENGLES_LIB  := -lGLESv1_CM
    OPENGLES_DEF  := -DUSE_OPENGL_ES_1_1
else
    OPENGLES_LIB  := -lGLESv2
    OPENGLES_DEF  := -DUSE_OPENGL_ES_2_0
endif

# An optional set of compiler flags that will be passed when building
# C ***AND*** C++ source files.
#
# NOTE: flag "-Wno-write-strings" removes warning about deprecated conversion
#       from string constant to 'char*'

LOCAL_CFLAGS := -Wno-write-strings $(OPENGLES_DEF)

# The list of additional linker flags to be used when building your
# module. This is useful to pass the name of specific system libraries
# with the "-l" prefix.

LOCAL_LDLIBS := \
     -llog $(OPENGLES_LIB)
#      -lfastcv
LOCAL_LDFLAGS:= -Wl,--no-fix-cortex-a8

LOCAL_MODULE    := libfastcvsample
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := \
    About.cpp \
    FastCVSample.cpp \
    FPSCounter.cpp \
    CameraRendererRGB565GL2.cpp \
    CameraUtil.cpp \
    FastCVSampleRenderer.cpp

LOCAL_STATIC_LIBRARIES := libfastcv
#LOCAL_SHARED_LIBRARIES := liblog libGLESv2
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/fastcv/inc \
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/fastcv


LOCAL_MODULE_OWNER := qcom
LOCAL_PROPRIETARY_MODULE := true

include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)

LOCAL_STATIC_JAVA_LIBRARIES :=
LOCAL_JNI_SHARED_LIBRARIES := libfastcvsample
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := FastCVSample

include $(BUILD_PACKAGE)
```

-7. appで右クリックして"Link C++ Project with Gradle"を選択。"ndk-build"を選び、`~/source/fastcorner/app/src/main/jni/Android.mk`を指定する。

-8. AndroidManifest.xmlにPermission追加

```
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```

-9. "Run"-"Debug `app`"でデバッグ。

# まとめ
fastCVはEclipse IDEを想定しているため、Android Studio + gradleでビルドするにはいくつか手順が必要だった。試行錯誤しながら進めたので他の環境では他にも修正が必要かもしれない。サンプル(fastcorner)をビルドして、Moto G5 plus (Snapdragon625)で動作させることができた。

# 参考
* [Forums - FastCV in Android Studio](https://developer.qualcomm.com/forum/qdn-forums/software/fastcv-computer-vision-sdk/33111)
* [Android NDK: Module depends on undefined modules: log](https://stackoverflow.com/questions/50350946/android-ndk-module-depends-on-undefined-modules-log)