欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

Android配置OpenCV C++开发环境,

来源: 开发者 投稿于  被查看 19919 次 评论:151

Android配置OpenCV C++开发环境,


网上的OpenCV配置环境大部分都不能正常配置成功,不是编译时报找不到so,就是运行找不到so.本文是我试了不少坑才找到的配置方法.其原理是让AndroidStudio自己根据mk文件自动配置.

1.下载OpenCV

先去OpenCV官网下载OpenCV的Android版本.速度慢的可以用迅雷下载.

OpenCV4.5.5

下载完成之后解压到文件夹

2.AndroidStudio新建C++项目

新建项目选择nativeC++模板.

C++标准选默认就好了

创建完成之后如果以前没配置过NDK可能会报错.

打开 Project Structue

切换到 SDK Location标签下,选择一个已安装的NDK即可.

如果没有NDK可供选择,需要先下载NDK.打开 SDK Manager

选择一个合适的版本下载就好,建议不要下载最新版本.

3.配置OpenCV开发环境

在配置OpenCV开发环境之前,可以安装运行一下看一下有没有报错,第一次运行会有较长加载so库的时间.

3.1配置include头文件

找到之前解压好的opencv-4.5.5-android-sdk文件夹,复制下面的 OpenCV-android-sdk\sdk\native\jni\include文件夹到 src/main/cpp文件夹下.

3.2配置CMakeLists.txt文件

将以下内容复制替换到 cpp/CMakeLists.txt 注意将里面的opencv路径替换为自己电脑上的路径.注意斜杆

cmake_minimum_required(VERSION 3.4.1)

# ##################### OpenCV 环境 ############################
#设置OpenCV-android-sdk路径,替换为自己电脑上的路径,注意是双斜杠或者反斜杠
set( OpenCV_DIR D:\\Develop\\OpenCV\\opencv-4.5.5-android-sdk\\OpenCV-android-sdk\\sdk\\native\\jni )

find_package(OpenCV REQUIRED )
if(OpenCV_FOUND)
    include_directories(${OpenCV_INCLUDE_DIRS})
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
else(OpenCV_FOUND)
    message(FATAL_ERROR "OpenCV library not found")
endif(OpenCV_FOUND)

# ###################### 项目原生模块 ###########################

add_library( native-lib
        SHARED
        native-lib.cpp
)

#jnigraphics是Android bitmap处理库,如果需要在JNI处理bitmap对象,需要添加引用
target_link_libraries( native-lib
	${OpenCV_LIBS}
	log
        jnigraphics)

4.验证OpenCV是否配置成功

4.1验证头文件是否配置成功

重新build之后打开 native-lib.cpp 导入OpenCV的头文件.如果有提示说明头文件配置成功.

4.2验证OpenCV库是否正确链接到

打开 native-lib.cpp 找到默认生成的stringFromJNI方法

extern "C" JNIEXPORT jstring JNICALL
Java_komine_demos_opencvdemo_MainActivity_stringFromJNI(JNIEnv* env,jobject  thiz) {
    //添加这行声明
    cv::Mat mat;
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

运行如果没有报错说明OpenCV配置成功

4.3简单使用OpenCV进行图片处理

首先在 MainActivity中声明一个processImage native方法,新版AndroidStudio再也不需要通过javah去生成头文件了,

直接 Alt + Enter生成native的方法声明,我的AndroidStudio版本是3.6.3,高于3.0的应该都能自动生成.

为了更方便使用OpenCV的类,可以导入cv命名空间

//写在include语句的下方
using namespace cv;

native实现

extern "C"
JNIEXPORT void JNICALL
Java_komine_demos_opencvdemo_MainActivity_processImage(JNIEnv *env, jobject thiz,jstring image_path,jstring outPath) {
    //将jstring转换为const char*
    const char* path = env->GetStringUTFChars(image_path,NULL);
    const char* imageOutPath = env->GetStringUTFChars(outPath,NULL);

    //读取mat对象
    Mat sourceMat = imread(path);
    //灰度mat
    Mat grayMat;

    //将图片转换为灰度图
    cvtColor(sourceMat,grayMat,COLOR_BGR2GRAY);

    //将图片写入到文件
    imwrite(imageOutPath,grayMat);
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical"
	tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	/>

    <Button
        android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="显示灰度图"
	android:onClick="loadGrayImage"
	/>

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ImageView mImageView;
    private String mOutputPath;

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	mImageView = findViewById(R.id.image);

	//注意读写权限,或者将图片upload到files目录
	String sourcePath = Environment.getExternalStorageDirectory() + File.separator + "miku.png";
	mOutputPath = Environment.getExternalStorageDirectory() + File.separator + "miku_gray.png";

	processImage(sourcePath,mOutputPath);
    }

    public void loadGrayImage(View view) {
        mImageView.setImageBitmap(BitmapFactory.decodeFile(mOutputPath));
    }

    public native void processImage(String imagePath,String outPath);
}

效果图

用户评论