Android利用SurfaceView显示Camera图像爬坑记(六) -- 用OpenCV进行Canny边缘检测

前言

上一篇《Android利用SurfaceView显示Camera图像爬坑记(五) -- 在现有项目中加入NDK配置》中我们已经把NDK加入到SurfaceView实时图像显示了,这一篇我们就针对这个实时进行图像处理,并显示到预览实时帧中。

本篇写完基本这个摄像头获取实时Camera进行图像处理的基本可以告一段落,所以最后我会把我的这套DEMO程序放到网盘上。

视频演示效果

今天这篇先上视频效果

代码实现

新建一个JNI的调用类VaccaeOpenCVJNI,在里面加入一个native的方法getCameraframebitbmp,用于实时处理传递进去的Bitmap的图像。

平时我们惯例直接ALT+ENTER,在native-lib中生成对应的方法了,不过这次因为我们原来的native-lib.cpp里面是空的,系统默认在JNI的目录下生成了一个native-lib.c的文件,没办法,这个只能手写了,不过写完这一个如果要再增加方法按ALT+ENTER就会指定对了。

native-lib.cpp里的方法

其中上面有个mat2bitmap就是我在《OpenCV4Android中NDK开发(二)---图片转为灰度图》处理灰度图的方法

extern "C"
JNIEXPORT jobject JNICALL
Java_dem_vac_surfaceviewdemo_VaccaeOpenCVJNI_getCameraframebitbmp(JNIEnv *env, jclass type,
                                                                  jobject bmp) {


    AndroidBitmapInfo bitmapInfo;
    void *pixelscolor;
    int ret;


    //获取图像信息,如果返回值小于0就是执行失败
    if ((ret = AndroidBitmap_getInfo(env, bmp, &bitmapInfo)) < 0) {
        LOGI("AndroidBitmap_getInfo failed! error-%d", ret);
        return NULL;
    }


    //判断图像类型是不是RGBA_8888类型
    if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGI("BitmapInfoFormat error");
        return NULL;
    }


    //获取图像像素值
    if ((ret = AndroidBitmap_lockPixels(env, bmp, &pixelscolor)) < 0) {
        LOGI("AndroidBitmap_lockPixels() failed ! error=%d", ret);
        return NULL;
    }


    //生成源图像
    cv::Mat src(bitmapInfo.height, bitmapInfo.width, CV_8UC4, pixelscolor);


    //生成Canny图像
    dealcanny(src);


    //获取原图片的参数
    jclass java_bitmap_class = (jclass) env->FindClass("android/graphics/Bitmap");
    jmethodID mid = env->GetMethodID(java_bitmap_class, "getConfig",
                                     "()Landroid/graphics/Bitmap$Config;");
    jobject bitmap_config = env->CallObjectMethod(bmp, mid);
    //将SRC转换为图片
    jobject _bitmap = mat2bitmap(env, src, false, bitmap_config);


    AndroidBitmap_unlockPixels(env, bmp);




    return _bitmap;
}

上图中看到这里有个dealcanny(src)的方法,这里正好学习一下新知识,新建别的C++的文件调用,这样我们的native-lib.cpp里的方法只有入口方法,具体的图像处理可以新建别的CPP来实现。

新建cvcanny的C++ class

鼠标右键CPP那选择新建,如下图,名称改为cvcanny

cvcanny.h头文件

在头文件中加入一个dealcanny的方法

cvcanny.cpp文件

cvcanny.cpp中写dealcanny的实现方法

然后在native-lib.cpp中引入cvcanny.h的头文件

CMakeLists.txt修改

CMakeLists.txt要做修改的原因有两点,一是我们在相同目录下加入了别的cpp的文件,所以要一起打包进去,另一个原因是我把Opencv4.1的版本改为OpenCV3.4.6了(改版本的原因是我有个老的测试机是android4.1的,用OpenCV4.1不支持这个机型,所以改为OpenCV3.4.6)

最后在VaccaeSurfaceView中的nv21Tobitmap的方法旋转图像下面加入调用JNI的方法,如下图红框

这样整个项目就完成了,总结一下几个注意的点:

  1. 增加新的CPP方法时一开始我直接加了cpp文件,结果运行时报错,后面才加入的cvcanny的class写法,但是一开始用重新编译时一直不通过,提示我原来增加的cpp文找不到,反复试了几次后发现需要重新修改一下CMakeLists.txt的任何地方,编译一次再改回来就好了。

  2. 返回图像时一开始我用的是传像素的方法,传递进来int[],返回的数据也是int[],再转为图片显示,参考《学习《实时Opencv处理后的Camera图像Android NDK方法》笔记》里的那个DEMO方式,结果试了一天多,还是预览的画面不变,到现在没解决,所以改为直接调用的图片方法返回也是图片。

DEMO下载地址

链接:https://pan.baidu.com/s/1EeK8MhqfXjvg8OjSGTnJBw
提取码:h2g7

-END-

Vaccae的往期经典


OpenCV

《C++ OpenCV案例实战---卡号获取

《C++ OpenCV案例实战---卡片截取(附代码)

《C++ OpenCV透视变换---切换手机正面图片》

《C++ OpenCV实战---获取数量

《C++ OpenCV实战---利用颜色分割获取数量》


Android

《Android利用SurfaceView结合科大讯飞修改语音实别UI

《Android关于语音识别的功能实现分析(一)---结构化思维》

《Android关于语音识别的功能实现分析(二)---语义解析》

《Android根据类生成签名字符串

《Android碎片化布局fragment的实战应用

《Android中RecyclerView嵌套RecyclerView

《Android里用AsyncTask后的接口回调


.Net C#

《C#自定义特性(Attribute)讲解与实际应用

《C#根据类生成签名字符串(附DEMO下载地址)

《C++创建动态库C#调用》

《C#与三菱PLC(型号FX2N)串口通讯类


数据库及其它

《Oracel存储过程写报表实战》

《Delphi轮播视频和图片程序(用于双屏显示程序)

《SQL随机增加销售数据的脚本编写(附脚本下载地址)

SQL Server中With As的介绍与应用(三)--递归的实战应用

《Oracle通过ODBC连接SQL Server数据库


长按下方二维码关注微卡智享

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值