一个最简单、免搭建的Android OpenCV开源库

GitHub:https://github.com/AnJiaoDe/OpenCVAndroidNiubility

CSDN:https://blog.csdn.net/confusing_awakening/article/details/113355609

使用方法

注意:该轮子只包含了arm64-v8a架构的so库,因为目前的手机,基本上都支持到了arm64-v8a,再适配到armeabi-v7a意义不大了

1.工程目录下的build.gradle中添加代码:

注意:如果轮子死活下载不下来,说明maven地址有毛病,你需要找到jitpack的官网首页,查看最新的官网地址

allprojects {
		repositories {
			        maven { url 'https://www.jitpack.io' }
		}
	}

2.直接在需要使用的模块的build.gradle中添加代码:

dependencies {
    api 'com.github.AnJiaoDe:OpenCVAndroidNiubility:V1.0.1'//基于OpenCV4.5.1
}

3.混淆已配置到库内部,无需做混淆配置

注意:记得去gayhub查看最新版本,最新版本最niubility

详细使用如下

初始化

在Application初始化

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        OpenCVUtils.init();
    }
}

或者在使用之前init即可

举例图像边缘检测
在这里插入图片描述

 Mat mat_src = new Mat();
 Mat mat_blur = new Mat();
 Mat mat_dst = new Mat();
 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.man_ls);
 iv_normal.setImageBitmap(bitmap);

 Utils.bitmapToMat(bitmap, mat_src);

 Bitmap bitmap_deal = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
 Imgproc.blur(mat_src, mat_blur, new Size(3, 3));
 Imgproc.Canny(mat_blur, mat_dst, 30, 30 * 3, 3);
 Utils.matToBitmap(mat_dst, bitmap_deal);
 iv_deal.setImageBitmap(bitmap_deal);

举例图像变灰
在这里插入图片描述

Mat mat_src = new Mat();
Mat mat_dst = new Mat();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gou_1);
iv_normal.setImageBitmap(bitmap);

Utils.bitmapToMat(bitmap, mat_src);

Bitmap bitmap_deal = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
Imgproc.cvtColor(mat_src, mat_dst, Imgproc.COLOR_BGR2GRAY);
Utils.matToBitmap(mat_dst, bitmap_deal);
iv_deal.setImageBitmap(bitmap_deal);

举例图像腐蚀
在这里插入图片描述

Mat mat_src = new Mat();
Mat mat_dst = new Mat();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gou_2);
iv_normal.setImageBitmap(bitmap);

Utils.bitmapToMat(bitmap, mat_src);

Bitmap bitmap_deal = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
Imgproc.erode(mat_src, mat_dst, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(15, 15)));
Utils.matToBitmap(mat_dst, bitmap_deal);
iv_deal.setImageBitmap(bitmap_deal);

如果实现功能的时候不知道用什么API,往往需要去看OpenCV JAVA函数的注释
但是如果实在不知道用什么函数的时候,或者函数不灵的时候,
但是又知道C/C++函数怎么用的时候,我们可以通过JNI

自己写C/C++调用OpenCV实现

引入OpenCV C/C++的头文件

头文件可以从我的gayhub上下载demo即可获取
在这里插入图片描述
配置CmakeLists.txt

关联libc++_shared.so和libopencv_java4.so

依赖轮子之后,so库何在?

找到你的工程目录中的External Libraries
在这里插入图片描述
往下找到OpengCVAndroidNiubility aar
在这里插入图片描述
右击classes.jar 点击show in explorer,可以看到gayhub上的轮子被下载到了电脑C
在这里插入图片描述
往上层目录找到so
在这里插入图片描述
在这里插入图片描述
这样就拿到了so库的路径

set(path_so C:\Users\Administrator\.gradle\caches\transforms-2\files-2.1\60c200c3babcd2085e13876e25905724
\jetified-OpenCVAndroidNiubility-V1.0.0\jni\arm64-v8a)
cmake_minimum_required(VERSION 3.4.1)

#配置路径
set(path_so C:\Users\Administrator\.gradle\caches\transforms-2\files-2.1\60c200c3babcd2085e13876e25905724
\jetified-OpenCVAndroidNiubility-V1.0.0\jni\arm64-v8a)
# 设置cpp目录路径
include_directories(include)
add_library( # Sets the name of the library.
        native-lib
        # Sets the library as a shared library.
        SHARED
        native-lib.cpp)
find_library( # Sets the name of the path variable.
        log-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

add_library(c++_shared
        SHARED
        IMPORTED)
set_target_properties(c++_shared
        PROPERTIES
        IMPORTED_LOCATION
        ${path_so}/libc++_shared.so)

add_library(opencv_java4
        SHARED
        IMPORTED)
set_target_properties(opencv_java4
        PROPERTIES
        IMPORTED_LOCATION
        ${path_so}/libopencv_java4.so)


target_link_libraries( # Specifies the target library.
        native-lib
        c++_shared
        opencv_java4
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        #操作bitmap需要
#        -ljnigraphics
        )

或者你可以直接从gayhub将工程clone到本地,自行操作

如果你需要用JNI操作bitmap相关,可以关联-ljnigraphics

定义Native方法

public class JniUtils {
    static {
        System.loadLibrary("native-lib");
    }
    public static  native  void gray(long mat_addr_src,long mat_addr_dst);
}

CPP实现JNI方法

#include <jni.h>
#include <opencv2/opencv.hpp>
using namespace cv;

extern "C"
JNIEXPORT void JNICALL
Java_com_cy_opencvandroidniubility_JniUtils_gray(JNIEnv *env, jclass clazz, jlong mat_addr_src,
                                                 jlong mat_addr_dst) {
    Mat *mat_src = (Mat *) mat_addr_src;
    Mat *mat_dst = (Mat *) mat_addr_dst;
    cvtColor(*mat_src, *mat_dst, COLOR_BGR2GRAY);

//    Mat &mat_src = *(Mat *) mat_addr_src;
//    Mat &mat_dst = *(Mat *) mat_addr_dst;
//    cvtColor(mat_src, mat_dst, COLOR_BGR2GRAY);
}

举例图像变灰

在这里插入图片描述

Mat mat_src = new Mat();
Mat mat_dst = new Mat();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gou_1);
iv_normal.setImageBitmap(bitmap);

Utils.bitmapToMat(bitmap, mat_src);

Bitmap bitmap_deal = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
//Imgproc.cvtColor(mat_src, mat_dst, Imgproc.COLOR_BGR2GRAY);
//自定义JNI方法调用
JniUtils.gray(mat_src.nativeObj, mat_dst.nativeObj);
Utils.matToBitmap(mat_dst, bitmap_deal);
iv_deal.setImageBitmap(bitmap_deal);

因为JAVA中的Mat类,提供了nativeObj,也就是对象的地址,这样,我们就可以很方便地从JAVA传递Mat对象给C/C++

错误:Assertion failed ((src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data)

Android调用C/++双边滤波函数bilateralFilter的时候,会出现如下错误:

cv::error(): OpenCV(4.5.1) Error: Assertion failed 
((src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data) in bilateralFilter_8u, 
file /build/master_pack-android/opencv/modules/imgproc/src/bilateral_filter.dispatch.cpp, line 166

libc++abi: terminating with uncaught exception of type cv::Exception: OpenCV(4.5.1) 
/build/master_pack-android/opencv/modules/imgproc/src/bilateral_filter.dispatch.cpp:166: 
error: (-215:Assertion failed) (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data 
in function 'bilateralFilter_8u'

一、概述

这个异常是在用OpenCV做高斯双边滤波做图像美化的时候出现的异常。这个异常信息的意思是图像类型不对。高斯双边滤波只允许CV_8UC1或者CV_8UC3即只能加载单通多的灰色图片或者三通道的彩色图片。

二、产生的原因

原因在于我在做测试的时候直接用BitmapFactory加载了一个Bitmap对象,并把Bitmap对象通过opencv的Uitls工具转换为了Mat对象,然后操作了这个Mat对象。由于Bitmap默认的通道时RGBA,而openCV默认的是GBR,由于通道不一致所以导致了以上的那个错误。

三、解决方法

解决方案也是比较简单,把RGBA色彩控件转换为BGR色彩空间就OK了。具体的转换是通过 Imgproc.cvtColor(target,dst,Imgproc.COLOR_RGBA2BGR);

此处引用自https://www.cnblogs.com/tony-yang-flutter/p/14156024.html

也就是将Mat对象Color先由RGB2BGR,传递到C、C++处理完毕后,再传递到JAVA后,再BGR2RGB

 Imgproc.cvtColor(mat_src, mat_src, Imgproc.COLOR_RGB2BGR);
 Imgproc.cvtColor(mat_dst, mat_dst, Imgproc.COLOR_BGR2RGB);

举例双边滤波

 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.man_ls);
 iv_normal.setImageBitmap(bitmap);

 Mat mat_src = new Mat();
 Mat mat_dst = new Mat();

 Utils.bitmapToMat(bitmap, mat_src);
 //千万别用RGB_565,极其劣质,磨皮后图片很多一层层的波浪
 Bitmap bitmap_deal = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
 Imgproc.cvtColor(mat_src, mat_src, Imgproc.COLOR_RGB2BGR);
 Imgproc.bilateralFilter(mat_src, mat_dst, 25, 50, 12.5);
//                JniUtils.bilateralFilter(mat_src.nativeObj, mat_dst.nativeObj);

 Imgproc.cvtColor(mat_dst, mat_dst, Imgproc.COLOR_BGR2RGB);
 Utils.matToBitmap(mat_dst, bitmap_deal);
 iv_deal.setImageBitmap(bitmap_deal);

在这里插入图片描述

欢迎联系、指正、批评

Github:https://github.com/AnJiaoDe

CSDN:https://blog.csdn.net/confusing_awakening

OpenCV入门教程:https://blog.csdn.net/confusing_awakening/article/details/113372425

ffmpeg入门教程:https://blog.csdn.net/confusing_awakening/article/details/102007792

微信公众号
这里写图片描述

QQ群

这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值