zoukankan      html  css  js  c++  java
  • 交叉编译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('33[91m' + ' There is no item in table.json ' + '33[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)
  • 相关阅读:
    Kubernetes 命令行工具之kubctl
    新一代数据库之Etcd 简介
    算法题 打家劫舍(动态规划)
    算法题 位1的个数
    Class强制类型转换
    算法题 阶乘后的零
    算法题 Excel表列序号
    多数元素
    有序数组两数之和
    一杯果汁和一杯水的故事
  • 原文地址:https://www.cnblogs.com/jojodru/p/10025658.html
Copyright © 2011-2022 走看看