千家信息网

AndroidStudio中JNI工程及引用OpenCV的示例分析

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,小编给大家分享一下AndroidStudio中JNI工程及引用OpenCV的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解
千家信息网最后更新 2026年11月02日AndroidStudio中JNI工程及引用OpenCV的示例分析

小编给大家分享一下AndroidStudio中JNI工程及引用OpenCV的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1、创建项目
1.1:下载OpenCV的SDK

首先到官网下载OpenCV的Android包

so文件所在: sdk -> native -> libsc++的代码 : sdk -> native -> jni -> include -> opencv2
1.2:创建一个Android Native c++的项目

项目结构如下

1.3:运行第一个项目

结果如下,在中间显示了一行:"Hello from C++"

2.JNI初始项目分析
2.1:MainActivity分析

在静态代码块中使用System.loadLibrary方法加载了native-lib
native方法stringFromJNI()返回一个String并设置到了TextView上

---->[src/main/java/com/toly1994/rec/MainActivity.java]----public class MainActivity extends AppCompatActivity {    static {        System.loadLibrary("native-lib");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView tv = findViewById(R.id.sample_text);        tv.setText(stringFromJNI());    }    /**     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    public native String stringFromJNI();}
2.2:native-lib.cpp分析

引入了jni和string头文件,一个Java_com_toly1994_rec_MainActivity_stringFromJNI函数
函数体中定义了一个sring变量,并通过env指针创建了一个字符串并返回

#include #include extern "C" JNIEXPORT jstring JNICALLJava_com_toly1994_rec_MainActivity_stringFromJNI(        JNIEnv *env,        jobject /* this */) {    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}
2.3:CMakeLists.txt
#指定 cmake 的最小版本cmake_minimum_required(VERSION 3.4.1)# 使用native-lib.cpp文件生成共享库native-libadd_library(native-lib SHARED native-lib.cpp )# 在ndk中查找log库 取别名log-libfind_library(log-lib log )#设置 target 需要链接的库target_link_libraries(native-lib ${log-lib} )

3.集成OpenCV
3.1:库的导入及引用

将需要的库以及so包拷贝到项目中,以及CMakeLists.txt的配置

#指定 cmake 的最小版本cmake_minimum_required(VERSION 3.4.1)include_directories(include)#引入文件夹#编译头文件#定义全局 my_source_path 变量file(GLOB my_source_path ${CMAKE_SOURCE_DIR}/*.cpp ${CMAKE_SOURCE_DIR}/*.c)add_library(tolyCV SHARED ${my_source_path})#添加动态链接库add_library(lib_opencv SHARED IMPORTED)set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java4.so)# 在ndk中查找log库 取别名log-libfind_library(log-lib log)# 在ndk中查找jnigraphics库 取别名jnigraphics-lib# jnigraphics包含图形操作的库find_library(jnigraphics-lib jnigraphics)#设置 target 需要链接的库target_link_libraries(        tolyCV        lib_opencv        ${jnigraphics-lib}        ${log-lib})
3.2:几乎断送我ndk生涯的bug

dlopen failed: library "libc++_shared.so" not found
这个bug如噩梦般卡在我ndk前行的路上,以致我几乎放弃,五天后,终得解法:

---->[app/build.gradle]----android {    defaultConfig {        externalNativeBuild {            cmake {                cppFlags ""                arguments "-DANDROID_STL=c++_shared"//使用c++_shared.so            }        }    }

3.3:创建bitmap的工具类

C++中无法直接操作Android的Bitmap类,所以需要转化为像素矩阵处理,这里先写成头文件。
关于#include <android/xxxxx>的飘红,需要 build --> Refresh Linked C++ Projects

---->[cpp/bitmap_utils.h]----#ifndef REC_UTILS_H#define REC_UTILS_H#include #include using namespace cv;//Matextern "C" {    /**     * Bitmap 转矩阵     * @param env JNI环境     * @param bitmap Bitmap对象     * @param mat 图片矩阵     * @param needPremultiplyAlpha 是否前乘透明度     */void bitmap2Mat(JNIEnv *env, jobject bitmap, Mat *mat, bool needPremultiplyAlpha = false);/** * 矩阵转Bitmap * @param env JNI环境 * @param mat 图片矩阵 * @param bitmap Bitmap对象 * @param needPremultiplyAlpha 是否前乘透明度 */void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap, bool needPremultiplyAlpha = false);/** * * 创建Bitmap * @param env JNI环境 * @param src 矩阵 * @param config Bitmap配置 * @return Bitmap对象 */jobject createBitmap(JNIEnv *env, Mat src, jobject config);}#endif //REC_UTILS_H
4.OpenCV实现灰度图片

4.1:下面是三个方法的具体实现

bitmap2Mat 通过bitmap获取像素矩阵,放入mat中,这样mat就可以在C++中操作
mat2Bitmap 与上面相反,通过将mat矩阵,将矩阵的像素信息置入其中
createBitmap 通过反射获取Android中的createBitmap方法获取对象,在通过mat2Bitmap置入信息。

#include "bitmap_utils.h"void bitmap2Mat(JNIEnv *env, jobject bitmap, Mat *mat, bool needPremultiplyAlpha) {    AndroidBitmapInfo info;    void *pixels = 0;    Mat &dst = *mat;    //获取信息和一些断言    CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);//获取Bitmap信息    CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888//图片格式RGBA_8888 或RGB_565              || info.format == ANDROID_BITMAP_FORMAT_RGB_565);    CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);    CV_Assert(pixels);    dst.create(info.height, info.width, CV_8UC4);    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {        Mat tmp(info.height, info.width, CV_8UC4, pixels);        if (needPremultiplyAlpha) {            cvtColor(tmp, dst, COLOR_mRGBA2RGBA);        } else {            tmp.copyTo(dst);        }    } else {        Mat tmp(info.height, info.width, CV_8UC2, pixels);        cvtColor(tmp, dst, COLOR_BGR5652RGBA);    }    AndroidBitmap_unlockPixels(env, bitmap);}void mat2Bitmap(JNIEnv *env,  Mat mat, jobject bitmap,bool needPremultiplyAlpha) {    AndroidBitmapInfo info;    void *pixels = 0;    CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);//获取Bitmap信息    CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888//图片格式RGBA_8888 或RGB_565              || info.format == ANDROID_BITMAP_FORMAT_RGB_565);    CV_Assert(mat.dims==2&&info.height==(uint32_t)mat.rows && info.width==(uint32_t)mat.cols);    CV_Assert(mat.type()==CV_8UC1||mat.type()==CV_8UC3||mat.type()==CV_8UC4);    CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);    CV_Assert(pixels);    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {        Mat tmp(info.height, info.width, CV_8UC4, pixels);        switch (mat.type()){            case CV_8UC1:                cvtColor(mat,tmp,COLOR_GRAY2RGBA);                break;            case CV_8UC3:                cvtColor(mat,tmp,COLOR_RGB2RGBA);                break;            case CV_8UC4:                cvtColor(mat,tmp,COLOR_RGBA2mRGBA);                if (needPremultiplyAlpha) {                    cvtColor(mat, tmp, COLOR_RGBA2mRGBA);                } else {                    mat.copyTo(tmp);                }                break;            default:break;        }    } else {        Mat tmp(info.height, info.width, CV_8UC2, pixels);        switch (mat.type()){            case CV_8UC1:                cvtColor(mat,tmp,COLOR_GRAY2BGR565);                break;            case CV_8UC3:                cvtColor(mat,tmp,COLOR_RGB2BGR565);                break;            case CV_8UC4:                cvtColor(mat,tmp,COLOR_RGBA2BGR565);                break;            default:break;        }    }    AndroidBitmap_unlockPixels(env, bitmap);}jobject createBitmap(JNIEnv *env, Mat src, jobject config){    jclass java_bitmap_class=(jclass)env->FindClass("android/graphics/Bitmap");//类名    jmethodID mid=env->GetStaticMethodID(java_bitmap_class,"createBitmap",//获取方法            "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");    jobject bitmap=env->CallStaticObjectMethod(java_bitmap_class,mid,src.cols,src.rows,config);    mat2Bitmap(env,src,bitmap, false);    return  bitmap;}
4.2:在MainActivity中的操作:

布局很简单,就不贴了,一个iv_photo的ImageView。
在点击时调用一个opBitmap的native方法使得图片灰度化。

public class MainActivity extends AppCompatActivity {    static {        System.loadLibrary("tolyCV");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ImageView iv = findViewById(R.id.iv_photo);        iv.setOnClickListener(v -> {            tv.setText(stringFromJNI());            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.wy_300x200);            iv.setImageBitmap(opBitmap(bitmap,Bitmap.Config.ARGB_8888));        });    }    public native Bitmap opBitmap(Bitmap bitmap, Bitmap.Config argb8888);}
4.3:C++文件中的处理

将图片的像素信息灰度化盛放在dstMat,再使用dstMat创建一个Bitmap对象,至此一个逻辑就通畅了

---->[cpp/native-lib.cpp]---#include #include #include #include "bitmap_utils.h"extern "C"JNIEXPORT jobject JNICALLJava_com_toly1994_rec_MainActivity_opBitmap(JNIEnv *env, jobject instance, jobject bitmap,                                              jobject argb8888) {    Mat srcMat;    Mat dstMat;    bitmap2Mat(env, bitmap, &srcMat);    cvtColor(srcMat, dstMat, CV_BGR2GRAY);//将图片的像素信息灰度化盛放在dstMat    return createBitmap(env,dstMat,argb8888);//使用dstMat创建一个Bitmap对象}

以上是"AndroidStudio中JNI工程及引用OpenCV的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

矩阵 图片 信息 文件 对象 方法 项目 C++ 分析 像素 灰度 别名 环境 篇文章 链接 工程 示例 最小 代码 内容 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网高科技 美国互联网保险保险科技 互联网科技垄断 高科技与互联网 百单互联网科技有限公司 深圳天众互联网科技公司 互联网金融和金融科技 四个字互联网科技公司取名 中正互联网科技招聘 青岛中康互联网医疗科技有限公司 福建科技产业互联网发展 长沙茂晟互联网科技有限公司 特约风豹互联网科技为什么扣费 区块链结合互联网科技 深圳互联网科技的发展 江苏互联网科技小贷 互联网高科技行业有哪些企业 北京军民互联网科技公司 数字科技和互联网金融哪个好 长沙易易互联网科技有限公司 互联网黑科技 科技创新与互联网经济 朗涯互联网科技 互联网科技股午盘股票涨跌 厦门千工互联网科技有限公司 花神(南京)互联网科技有限公司 迪庆互联网科技招生 深圳互联网科技的发展 广州梦谷互联网科技有限公司领导 科技互联网行业投资研究
0