在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 <arm_neon.h>
#include <chrono>
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<std::chrono::duration<double> >(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<n; 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