使用方法

opencv 官方的 SDK 已经有编译好的 so 库,我们可以直接使用,因此我们只需要将平台架构对应的 so 库文件以及头文件提取出来,使用 Android.mk 进行预安装,然后在需要使用 opencv 程序中的 Android.mk 引用头文件和动态链接库即可。

具体步骤

一、下载 opencv sdk 并解压(我这里以 3.4.11 为例)


opencv android uvc 设备文件名_Android

二、提取相应的文件放置在Android源码指定的路径中,并编写 Android.mk 文件

1. 在 Android 源码中的 external 目录下创建 opencv_3.4.11 文件夹,并在 opencv_3.4.11 文件再创建 library 文件夹。

2. 将 opencv-3.4.11-android-sdk\OpenCV-android-sdk\sdk\native\libs 下面的 armeabi、armeabi-v7a、arm64-v8a 拷贝到 external\opencv_3.4.11\library(可以只拷贝适合所使用CPU架构的文件夹)

3. 在该目录下创建 Android.mk 并写入以下内容:(根据所使用的平台来选择用哪一段)

LOCAL_PATH := $(call my-dir)

# 第5代、第6代的ARM处理器
#include $(CLEAR_VARS)
#LOCAL_MODULE := libopencv_java3
#LOCAL_SRC_FILES := library/armeabi/libopencv_java3.so
#LOCAL_MODULE_CLASS := SHARED_LIBRARIES
#LOCAL_MODULE_SUFFIX := .so
#include $(BUILD_PREBUILT)

# 第7代的32位ARM 处理器
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_java3
LOCAL_SRC_FILES := library/armeabi-v7a/libopencv_java3.so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
include $(BUILD_PREBUILT)

# 第8代的64位ARM处理器
#include $(CLEAR_VARS)
#LOCAL_MODULE := libopencv_java3
#LOCAL_SRC_FILES := library/arm64-v8a/libopencv_java3.so
#LOCAL_MODULE_CLASS := SHARED_LIBRARIES
#LOCAL_MODULE_SUFFIX := .so
#include $(BUILD_PREBUILT)

4. 使用 mm 命令编译即可(我这里就不贴出来了),目录结构如下:

opencv android uvc 设备文件名_Android_02

三、编写测试应用程序进行测试

Android.mk

###################### 全局定义 ########################

LOCAL_PATH:= $(call my-dir)

COMMON_C_INCLUDES_FILES	 := bionic external/stlport/stlport 
COMMON_SHARED_LIBRARIES	 := libc libstlport libutils liblog libcutils libskia libandroid_runtime 

COMMON_LOCAL_CFLAGS := -fstack-protector-all -fomit-frame-pointer -Depl_LINUX
COMMON_LOCAL_CPPFLAGS := -std=c++11 

OPENCV_SHARED_LIBRARIES := libopencv_java3
OPENCV_C_INCLUDES_FILES := external/opencv_3.4.11/include

###################### 编译 Exe ########################

include $(CLEAR_VARS)

# 引入公共库
LOCAL_C_INCLUDES := $(COMMON_C_INCLUDES_FILES) $(OPENCV_C_INCLUDES_FILES)
LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) $(OPENCV_SHARED_LIBRARIES)
LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
#LOCAL_CPPFLAGS := $(COMMON_LOCAL_CPPFLAGS)
LOCAL_LDLIBS += -llog -lz -lm

LOCAL_SRC_FILES := bin/main.cpp
LOCAL_MODULE_TAGS := debug eng
LOCAL_MODULE := opencv_test
include $(BUILD_EXECUTABLE)

mian.cpp

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define CV_CXX_STD_ARRAY 0
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" //OpenCV 图像处理头文件 

using namespace cv; // 包含 cv 命名空间
using namespace std;

int main()
{
    // 读取图片
    Mat src = imread("/data/1.jpg", 1);
    Mat dst;

    // 彩色转为灰度图片
    cvtColor(src,dst,CV_BGR2GRAY);
    imwrite("/data/2.jpg",dst);
    
    src.release();
    dst.release();
    
    return 0;
}

编译完成之后,记得要将 libopencv_java3.so 通过 adb push 到设备的 /system/lib/ 目录下,如果编译整个固件烧录就不需要了。 

四、转换效果

opencv android uvc 设备文件名_#include_03

opencv android uvc 设备文件名_头文件_04

过程问题

一、array头文件找不到问题:include/opencv2/core/cvdef.h:639:21: fatal error: array: No such file or directory

opencv android uvc 设备文件名_#include_05

opencv android uvc 设备文件名_Android_06

从编译错误信息和 cvdef.h 源码位置,是因为没有定义 CV_CXX_STD_ARRAY 宏,而包含了 <array> 头文件,由于 Android 源码对 C++ 标准库支持的不是很好,我也花了不少时间去寻找相关资料,暂时未能找到更好的办法,因此我这边的解决方案就是在应用程序包含 opencv 头文件前,先定义 CV_CXX_STD_ARRAY 宏,并设置该宏为 0,使之不走包含 array 头文件的路径。

......
#define CV_CXX_STD_ARRAY 0  // 解决编译时报找不到 array 头文件的错误
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp"
......

二、initializer_list 头文件找不到的问题:include/opencv2/core/matx.hpp:57:28: fatal error: initializer_list: No such file or directory

opencv android uvc 设备文件名_头文件_07

opencv android uvc 设备文件名_#include_08

这个问题也是一样的,只需要将 Android.mk 中的 LOCAL_CPPFLAGS 变量取消掉 -std=c++11 即可。

###################### 全局定义 ########################

LOCAL_PATH:= $(call my-dir)
......
COMMON_LOCAL_CPPFLAGS := -std=c++11 
......

###################### 编译 Exe ########################

include $(CLEAR_VARS)
......
# 注释或者删除下面这一句
#LOCAL_CPPFLAGS := $(COMMON_LOCAL_CPPFLAGS)
......
include $(BUILD_EXECUTABLE)

 

上面的编译报错的这两个问题,都应该与 opencv 本身没有关系,猜测应该是跟 Android 4.4 源码对 C++ 支持不够全的问题,很早之前我就发现 Android 源码去编译自己在 Linux 可以正常编译的 C++ 源代码,就会报很多和上述两个问题类似的缺失头文件错误。虽然源码中搜索能找到 array 头文件定义,但是却不能直接引用,苦寻不得其果,无奈暂且放下。若能解决的话,在 Android 不受限制的使用 C++ 写的源代码,还是非常爽的。