前言
上一篇《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的方法,如下图红框
这样整个项目就完成了,总结一下几个注意的点:
增加新的CPP方法时一开始我直接加了cpp文件,结果运行时报错,后面才加入的cvcanny的class写法,但是一开始用重新编译时一直不通过,提示我原来增加的cpp文找不到,反复试了几次后发现需要重新修改一下CMakeLists.txt的任何地方,编译一次再改回来就好了。
返回图像时一开始我用的是传像素的方法,传递进来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数据库》
长按下方二维码关注微卡智享