交叉編譯OpenCV的Android版本


交叉編譯OpenCV的Android版本

OpenCV作為一個強大的圖像處理庫,在Android上也有強大的應用。

OpenCV官網提供了SDK的下載,可以直接下載使用

OpenCV官網地址:https://opencv.org/

不過有時候也會有自定義編譯的需求

下面來記錄一下最近在交叉編譯OpenCV所作的筆記

避免以后走彎路。

編譯Host系統是Ubuntu 16.04

准備工作

下載opencv:

1 git clone git@github.com:opencv/opencv.git
2 git checkout 3.4

下載opencv依賴的庫

1 git clone git@github.com:opencv/opencv_contrib.git
2 git checkout 3.4

這里我們使用的版本都是3.4。

 

配置環境:

1. 安裝ant

編譯Java代碼需要用到ant或者gradle

但是我還沒搞清楚怎么配置使用gradle編譯

而且我這次是在服務器上工作,沒有x11環境

沒裝Android Studio,所以,姑且使用ant編譯Java。

修改opencv/CMakeLists.txt文件

激活ant編譯

set(ANDROID_PROJECTS_SUPPORT_ANT ON)
sudo apt-get install ant

2. 安裝ndk

安裝ndk需要翻wall,請自備梯子

這里寫了一個python程序,用於枚舉NDK的版本,

然后手動輸入選擇下載對應的版本,

這里我下載的r17c版本NDK,下載完成之后配置NDK_ROOT環境變量

 1 #!/usr/bin/env python
 2 
 3 import urllib2
 4 import collections
 5 import json
 6 import os
 7 
 8 def init():
 9     """
10     Return name/link dict
11 
12     @return: name-to-link dict
13     """
14     with open('table.json') as data_file:
15         url_table = json.load(data_file)
16 
17     if url_table is None or len(url_table) <= 0:
18         print('\033[91m' + ' There is no item in table.json ' + '\033[0m')
19         os.sys.exit(0)
20 
21     # Sort alphabetically
22     url_table = collections.OrderedDict(sorted(url_table.items()))
23     index = 0
24     for key in url_table:
25         index = index + 1
26         print str(index) + '] ' + key
27 
28     return url_table
29 
30 def getTargetLink(desired_index, url_table):
31     """
32     Return download link
33 
34     @type  desired_index: number
35     @param desired_index: Desired index
36     @type  url_table: dict
37     @param url_table: name-to-link
38 
39     @return: Download link
40     """
41     index = 0
42     for key in url_table:
43         index = index + 1
44         if desired_index == index:
45             return url_table[key]
46     return None
47 
48 def download(url):
49     if url == None:
50         return
51 
52     file_name = url.split('/')[-1]
53     u = urllib2.urlopen(url)
54     f = open(file_name, 'wb')
55     meta = u.info()
56     file_size = int(meta.getheaders("Content-Length")[0])
57     print "Downloading: %s Bytes: %s" % (file_name, file_size)
58 
59     file_size_dl = 0
60     block_sz = 8192
61     while True:
62         buffer = u.read(block_sz)
63         if not buffer:
64             break
65 
66         file_size_dl += len(buffer)
67         f.write(buffer)
68         status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
69         status = status + chr(8)*(len(status)+1)
70         print status,
71 
72     f.close()
73 
74 if __name__ == '__main__':
75     url_table = init()
76     var = raw_input("Please enter the numer you want to download: ")
77     link = getTargetLink(int(var), url_table)
78     download(link)

 

3. 安裝SDK

由於我們需要編譯的android版本,需要用到SDK的build tools和sdk的platform版本庫

這里使用SDK的build tools版本是24.0.3

往上的版本,Google去掉了aidl,會導致沒法編譯Java端的代碼,也無法生成libopencv_java3.so

所以在下載的SDK版本中,build tools只能保留不高於24.0.3的版本

platform版本庫使用android-21

下載SDK的方法:

找一台裝有Android Studio的電腦,使用SDK Manager下載對應的版本即可

然后將SDK拷貝至交叉編譯的電腦上,配置SDK環境變量

export NDK_ROOT=/path/to/android-ndk-r17c
export ANDROID_HOME=path/to/sdk

 

4. 配置SDK tools版本

在我們的SDK中,有個tools目錄

具體的版本,是Android Studio在SDK Manager中配置的

但是OpenCV只能支持到tools_r25.2.5-linux.zip

所以需要手動下載tools_r25.2.5-linux.zip,解壓替換SDK目錄的tools

下載地址:https://dl.google.com/android/repository/tools_r25.2.5-linux.zip 

 

5. 安裝CMake和其它編譯環境

sudo apt-get install cmake
sudo apt-get install build-essential make

 

開始交叉編譯

由於OpenCV需要使用cmake編譯

需要配置很多參數,所以使用bash腳本是最方便的方式

編譯腳本放在opencv和opencv_contrib的同級目錄

#!/bin/bash
NDK_ROOT="${1:-${NDK_ROOT}}"

### ABIs setup
#declare -a ANDROID_ABI_LIST=("armeabi-v7a with NEON")
declare -a ANDROID_ABI_LIST=("armeabi-v7a")

### path setup
SCRIPT=$(readlink -f $0)
WD=`dirname $SCRIPT`
OPENCV_ROOT="${WD}/opencv"
N_JOBS=${N_JOBS:-4}

INSTALL_DIR="${WD}/opencv-build"
rm -rf "${INSTALL_DIR}/opencv"

### Make each ABI target iteratly and sequentially
for i in "${ANDROID_ABI_LIST[@]}"
do
    ANDROID_ABI="${i}"
    echo "Start building ${ANDROID_ABI} version"

    if [ "${ANDROID_ABI}" = "armeabi" ]; then
        API_LEVEL=19
    else
        API_LEVEL=21
    fi

    temp_build_dir="${OPENCV_ROOT}/platforms/build_android_${ANDROID_ABI}"
    ### Remove the build folder first, and create it
    #-DANDROID_TOOLCHAIN_NAME=clang 
    #-DANDROID_TOOLCHAIN_NAME="arm-linux-androideabi-5" \
    #-DANDROID_STL=gnustl_static \
    rm -rf "${temp_build_dir}"
    mkdir -p "${temp_build_dir}"
    cd "${temp_build_dir}"

    cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
          -DCMAKE_TOOLCHAIN_FILE="${OPENCV_ROOT}/platforms/android/android.toolchain.cmake" \
          -DANDROID_NDK="${NDK_ROOT}" \
          -DANDROID_NATIVE_API_LEVEL=${API_LEVEL} \
          -DANDROID_ABI="${ANDROID_ABI}" \
          -DANDROID_CPP_FEATURES="rtti exceptions" \
          -DANDROID_ARM_NEON=TRUE \
          -DANDROID_STL=gnustl_static \
          -DCMAKE_BUILD_TYPE=Release \
          -D BUILD_opencv_java=ON \
          -D BUILD_ANDROID_PROJECTS=ON \
          -D WITH_CUDA=OFF \
          -D WITH_MATLAB=OFF \
          -D BUILD_ANDROID_EXAMPLES=OFF \
          -D BUILD_DOCS=OFF \
          -D BUILD_PERF_TESTS=OFF \
          -D BUILD_TESTS=OFF \
          -DOPENCV_EXTRA_MODULES_PATH="${WD}/opencv_contrib/modules/"  \
          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}/opencv" \
          ../..
    # Build it
    make -j${N_JOBS}
    # Install it
    make install/strip
    ### Remove temp build folder
    cd "${WD}"
    rm -rf "${temp_build_dir}"
    echo "${temp_build_dir}"
    echo "end building ${ANDROID_ABI} version"
done

這里只啟用了armeabi-v7a編譯目標

其它平台可根據需求添加

目前無法使用ANDROID_TOOLCHAIN_NAME來指定clang編譯器

因為OpenCV的makefile在解析clang交叉編譯工具鏈使用的代碼沒做匹配

而我也暫時沒精力自己修改做匹配

有興趣的同學,可以修改

${OPENCV_ROOT}/platforms/android/android.toolchain.cmake

來匹配clang編譯器

STL鏈接使用的是gnu版本的

因為OpenCV用到了C++11

如果使用c++_static版本,因為Google沒做后續支持維護

gcc在這個工具鏈上不支持很多C++和C++11特性

會導致編譯失敗,我嘗試過使用CrystaX NDK

但是在configure階段就失敗了

只能無疾而終

其它編譯選項顧名思義,不做過多解析。

 

備注:

如果需要使用C++14特性編譯

需要修改opencv/CMakeList.txt文件

手動添加,pathch如下所示

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -156,7 +156,11 @@ endif()
 OCV_OPTION(ENABLE_CXX11 "Enable C++11 compilation mode" "${OPENCV_CXX11}")
 include(cmake/OpenCVDetectCXXCompiler.cmake)
 ocv_cmake_hook(POST_DETECT_COMPILER)
-
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_VERBOSE_MAKEFILE ON) +set(ANDROID_PROJECTS_SUPPORT_ANT ON) # Add these standard paths to the search paths for FIND_LIBRARY # to find libraries from these locations first if(UNIX AND NOT ANDROID)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM