如何用源码编译包含有opencl的opencv

在opencv的sdk里面拷贝一个include和lib库,结构如下

~/opencl_sdk
├── include
│   └── CL
│       ├── cl_d3d10.h
│       ├── cl_d3d11.h
│       ├── cl_dx9_media_sharing.h
│       ├── cl_egl.h
│       ├── cl_ext.h
│       ├── cl_gl_ext.h
│       ├── cl_gl.h
│       ├── cl.h
│       ├── cl.hpp
│       ├── cl_platform.h
│       └── opencl.h
├── lib
│   └── libOpenCL.so

在~下创建一个opencv目录,然后将我们的opencv的源码拷贝进去

mkdir opencv

cd opencv

cp -a  ~/opencv-3.3.0 .

mkdir build

在~/.bashrc里面加上ndk和cmake的环境变量

export ANDROID_NDK=/opt/android-ndk-r14b

export PATH=$PATH:/opt/android-ndk-r14b:/opt/arm-linux-androideabi/bin:~/android/prebuilts/sdk/tools/linux/bin:/usr/bin/:/usr/local/cmake-3.0.1/bin

export OPENCL_SDK=~/opencl_sdk
保存后source一下

source ~/.bashrc

然后进入到build目录下进行配置

cd ~/opencv/build

cmake -Wno-dev \

-DCMAKE_CXX_FLAGS=-std=c++11 \
-DCMAKE_TOOLCHAIN_FILE=../opencv-3.3.0/platforms/android/android.toolchain.cmake \
-DANDROID_ABI="arm64-v8a" \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DBUILD_SHARED_LIBS=ON \
-DINSTALL_ANDROID_EXAMPLES=OFF \
-DWITH_OPENCL=YES \
-DANDROID_OPENCL_SDK=$OPENCL_SDK \
-DANDROID_NATIVE_API_LEVEL=14 \
-DANDROID_SDK_TARGET=24 \

../opencv-3.3.0

配置完后编译

make -j8

最后安装

make install

在~/opencv/build/install/sdk/native/libs/arm64-v8a下就会生成动态库

但是生成的动态库里面并没有发现libopencv_java3.so

在CMakeLists.txt里面查看Java的部分如下

# ========================== java ==========================
status("")
status("  Java:")
status("    ant:"           ANT_EXECUTABLE      THEN "${ANT_EXECUTABLE} (ver ${ANT_VERSION})"                    ELSE NO)
if(NOT ANDROID)
  status("    JNI:"         JNI_INCLUDE_DIRS    THEN "${JNI_INCLUDE_DIRS}"                                       ELSE NO)
endif()
status("    Java wrappers:" HAVE_opencv_java                                                            THEN YES ELSE NO)
status("    Java tests:"    BUILD_TESTS AND opencv_test_java_BINARY_DIR                                 THEN YES ELSE NO)

这里可以知道编译生成libopencv_java.so需要满足ANT_EXECUTABLE      

究其原因是因为我们没有安装ant

安装ant比较简单我就不介绍了

装好后查看一下ant版本号,一定要大于1.09

archermind@flm:~/test/jni$ ant -version
Apache Ant(TM) version 1.10.1 compiled on February 2 2017

archermind@flm:~/opencv/build$ gedit cvconfig.h &


/* OpenCL Support */
#define HAVE_OPENCL
/* #undef HAVE_OPENCL_STATIC */
/* #undef HAVE_OPENCL_SVM */

从配置文件中我们可以知道当前配置是支持opencl的

archermind@flm:~/opencv/build$ gedit CMakeDownloadLog.txt&

use_cache "/home/archermind/opencv/opencv-3.3.0/.cache"
do_unpack "4.4.3.tar.gz" "8e3e39e1fdfb3f7c3a5ac8ec1afe186e" "https://github.com/01org/tbb/archive/4.4.3.tar.gz" "/home/archermind/opencv/build/3rdparty/tbb"
#check_md5 "/home/archermind/opencv/opencv-3.3.0/.cache/tbb/8e3e39e1fdfb3f7c3a5ac8ec1afe186e-4.4.3.tar.gz"
#remove_unpack "/home/archermind/opencv/build/3rdparty/tbb"
#mkdir "/home/archermind/opencv/build/3rdparty/tbb"
#unpack "/home/archermind/opencv/build/3rdparty/tbb" "/home/archermind/opencv/opencv-3.3.0/.cache/tbb/8e3e39e1fdfb3f7c3a5ac8ec1afe186e-4.4.3.tar.gz"

这里的log是一份正常的log,但是我之前遇到的问题是这里的下载失败,不支持ssl协议。

因为ssl协议会关系到https协议,所以不支持的话,是不能下载成功的,所以我们需要重新安装ssl

在安装ssl之前我重新安装了一下cmake,并重新配置了环境变量

  cd ~/;wget --no-check-certificate https://cmake.org/files/v3.9/cmake-3.9.0.tar.gz
  sudo tar xzvf ~/cmake-3.9.0.tar.gz .
  sudo tar xzvf ~/cmake-3.9.0.tar.gz -C .
  cd cmake-3.9.0/

然后我们在~/.bashrc中export这个cmake的bin路径

接着安装ssl

   sudo apt-get  install libcurl4-openssl-dev
  ./bootstrap --system-curl
   sudo ./bootstrap --system-curl
   make
   sudo make install
   curl --version

安装成功的话会出现下面的打印

curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

从Protocols: dict file ftp ftps gopher http https  可知这个curl支持https了

在.bashrc文件中的环境变量设置如下

export ANDROID_NDK=/opt/android-ndk-r14b
export NDK_TOOLCHAINS=/opt/arm-linux-androideabi/bin
export ANDROID_SDK_TOOLCHAINS=~/android/prebuilts/sdk/tools/linux/bin
export CMAKE_DIR=~/cmake-3.9.0/bin

export PATH=$PATH:$ANDROID_NDK:$NDK_TOOLCHAINS:$CMAKE_DIR

export OPENCL_SDK=~/opencl_sdk
export OPENCV_ANDROID_SDK=~/opencv/build


export ANT_HOME=/usr/local/apache-ant

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64

export PATH=$JAVA_HOME/bin:$PATH:$ANT_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib

然后重新编译

  cd build/
   rm -fr *
   rm -fr ../opencv-3.3.0/.cache/

安装TBB的支持


然后执行下面的cmake编译

cmake -Wno-dev \
-DCMAKE_CXX_FLAGS=-std=c++11 \
-DCMAKE_C_FLAGS="-ffunction-sections -fdata-sections -fvisibility=hidden -O3" \
-DCMAKE_TOOLCHAIN_FILE=../opencv-3.3.0/platforms/android/android.toolchain.cmake \
-DANDROID_ABI="arm64-v8a" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DINSTALL_ANDROID_EXAMPLES=OFF \
-DWITH_OPENCL=YES \
-DWITH_TBB=ON \
-DANDROID_OPENCL_SDK=$OPENCL_SDK \
-DANDROID_NATIVE_API_LEVEL=14 \
-DANDROID_SDK_TARGET=24 \
../opencv-3.3.0

这里配置了支持opencl,引用了$OPENCL_SDK下的64位的libOpenCL.so

配置完后编译安装

 make -j8
 make install
 find -iname *.so
 cp ./install/sdk/native/libs/arm64-v8a/libopencv_java3.so /mnt/hgfs/share/

然后将libopencv_java3.so push到开发板的/system/lib64/下面,库生效的话需要adb reboot

下面就是编译一个执行文件,调用我们生成的libopencv_java3.so

archermind@flm:~/test/jni$ ls
Android.mk  Application.mk   test.cpp
archermind@flm:~/test/jni$ cat Android.mk
LOCAL_PATH:= $(call my-dir)  
include $(CLEAR_VARS)  
NDK_APP_DST_DIR := $(LOCAL_PATH)
include ~/opencv/build/install/sdk/native/jni/OpenCV.mk
LOCAL_SRC_FILES := test.cpp
LOCAL_CFLAGS := -D__cpusplus -g -mfloat-abi=hard -mfpu=neon-vfpv4 -march=armv8-a -mtune=cortex-a53
TARGET_ARCH_ABI :=arm64-v8a 
LOCAL_ARM_MODE := arm

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
LOCAL_ARM_NEON := true 
endif   
LOCAL_MODULE := test     
include $(BUILD_EXECUTABLE)

test.cpp内容如下

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/ocl.hpp"
#include
#include

class q_timer { 
public: 
void start()
{
m_start = std::chrono::steady_clock::now();
}
double stop()
{
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
return  std::chrono::duration_cast >(end - m_start).count();
}
void time_display(const char *disp = "", int nr_frame = 1)
{
printf("Running time (%s) is: %5.5f Seconds.\n", disp, stop() / nr_frame);
}
void fps_display(const char *disp = "", int nr_frame = 1)
{
printf("Running time (%s) is: %5.5f frame per second.\n", disp, (double)nr_frame / stop());
}
private: 
std::chrono::steady_clock::time_point m_start;
 };

using namespace cv;
void neon_convert(uint8_t * __restrict dest, uint8_t * __restrict src, int n)
{
int i;
uint8x8_t rfac = vdup_n_u8(77);       // 转换权值  R      
uint8x8_t gfac = vdup_n_u8(151);    // 转换权值  G      
uint8x8_t bfac = vdup_n_u8(28);      // 转换权值  B      


n /= 8;

for (i = 0; i{
uint16x8_t  temp;
uint8x8x3_t rgb = vld3_u8(src);
uint8x8_t result;

temp = vmull_u8(rgb.val[0], rfac);       // vmull_u8 每个字节(8bit)对应相乘,结果为每个单位2字节(16bit)      
temp = vmlal_u8(temp, rgb.val[1], gfac);  // 每个比特对应相乘并加上      
temp = vmlal_u8(temp, rgb.val[2], bfac);

result = vshrn_n_u16(temp, 8);  // 全部移位8位      
vst1_u8(dest, result);   // 转存运算结果      
src += 8 * 3;
dest += 8;
}
}

int main()
{
if( cv::ocl::haveOpenCL())

   printf("have opencl");

Mat src = imread("cap1.png", 1);
Mat dst;
q_timer time;time.start();
bilateralFilter(src, dst, 20, 20, 20);
time.time_display("process mat");
cv::UMat usrc, udst;
time.start();
src.copyTo(usrc);
  time.time_display("copy umat");
time.start();
bilateralFilter(usrc, udst, 20, 20, 20);
        time.time_display("process umat");
time.start();
udst.copyTo(dst);
  time.time_display("copy umat");
}

这样在~/test/jni/路径下用ndk-build就可以生成一个执行文件test

我们将这个test push到我们的开发板并执行test

结果如下

amt6757_wifi_n:/data # ./test
have opencl

Running time (process mat) is: 7.87340 Seconds.
Running time (copy umat) is: 0.06674 Seconds.
Running time (process umat) is: 0.47743 Seconds.
Running time (copy umat) is: 8.84810 Seconds.


注意:我把下载源码的网址给改了,配置时,发现哈希码(commit的版本号)不匹配,于是我将打印中的哈希码拷贝到我的cmake里面,重新配置就好了

在~/opencv/opencv-3.3.0/3rdparty/tbb/CMakeLists.txt里面修改https为"https://github.com/01org/tbb/archive/"

set(tbb_src_dir "${OpenCV_BINARY_DIR}/3rdparty/tbb")
ocv_download(FILENAME ${tbb_filename}
             HASH ${tbb_md5}
             URL
               "${OPENCV_TBB_URL}"
               "$ENV{OPENCV_TBB_URL}"
               "https://github.com/01org/tbb/archive/"
             DESTINATION_DIR ${tbb_src_dir}
             ID TBB
             STATUS res
             UNPACK RELATIVE_URL)

下载之前设置哈希码

set(tbb_md5 "8e3e39e1fdfb3f7c3a5ac8ec1afe186e")


参考链接

http://blog.csdn.net/bloodfeast/article/details/77824713

https://stackoverflow.com/questions/44593680/building-opencv4android-from-source-does-not-output-libopencv-java-so

你可能感兴趣的:(工具)