Android OpenCV实现人脸检测完成预览画面显示
Posted 胡刚2021
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android OpenCV实现人脸检测完成预览画面显示相关的知识,希望对你有一定的参考价值。
android OpenCV 人脸识别系列文章:
Android Studio 集成OpenCV
Android OpenCV实现人脸检测(一)完成人脸检测功能
代码链接:
注意:如果你之前下载过本代码,安装运行的时候预览画面停下来了,并且之前也安装过这个应用,请先把应用卸载掉,然后点击 Android Studio的 Build -> Clean Project -> 运行,安装后即可运行。
又或者是:你下载了本代码,然后修改了 JNI 层的代码 然后运行卡到预览画面,那么也请你按上述步骤做。
在上面两篇文章的基础上,我们实现了人脸检测,并将检测出的人脸变为 24 * 24 大小的灰度图存放在 /data/data/com.example.myopencv/cache/face_img_24x24/ 这个目录下。
接下来,我们需要将画面渲染到预览Surface。
1.引入 libjnigraphics.so 和 libandroid.so 这两个系统的库
其中 libjnigraphics.so 是 Java 层传 Bitmap 到 JNI 层需要用到的库。由于这两个是系统自带的库,所以我们只需要在 target_link_libraries 引入即可。
target_link_libraries(
myopencv
opencv_java4
$log-lib
android
jnigraphics
# 千万不要写成下面这种形式,下面这种写法不能引用系统库
# $android
# $jnigraphics # Java 层传 Bitmap 到 JNI 层需要用到的库
)
2.实现 Java 层传递 Surface 到 JNI 层
native void setSurface(Surface surface);
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
//设置surface 用于显示
setSurface(holder.getSurface());
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myopencv_MainActivity_setSurface(JNIEnv *env, jobject thiz, jobject surface)
// 如果window已经存在,就释放掉
if (window)
ANativeWindow_release(window);
window = NULL;
window = ANativeWindow_fromSurface(env, surface);
3.JNI层将人脸渲染到预览画面
修改 JNI 的 postData 方法:
for (Rect face : faces)
//要将下面几行注释掉,否则预览画面只会停在显示一帧
// sprintf(picture_name, "/data/data/com.example.myopencv/cache/face_img_24x24/%d.png", index++);
// Mat face_rect;
// face_rect = gray_img(face).clone();
// resize(face_rect, face_rect, Size(24, 24));
// imwrite(picture_name, face_rect);
// 在原始的预览画面中画人脸区域的框框
rectangle(src, face,Scalar(0, 0, 255));
// 将人脸渲染到预览画面
if (window)
do
ANativeWindow_setBuffersGeometry(window, src.cols, src.rows, WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer buffer;
if (ANativeWindow_lock(window, &buffer, 0))
ANativeWindow_release(window);
window = NULL;
int srcLineSize = src.cols * 4;
int dstLineSize = buffer.stride * 4;
uint8_t *dstData = static_cast<uint8_t *> (buffer.bits);
uint8_t *srcData = src.data;
for (int i = 0; i < buffer.height; ++i)
memcpy(dstData + dstLineSize * i, srcData + srcLineSize * i, srcLineSize);
// 如果没有下面这行,则画面只会显示一帧
ANativeWindow_unlockAndPost(window);
while (0);
src.release();
gray_img.release();
编译运行后,预览画面显示出来
以上是关于Android OpenCV实现人脸检测完成预览画面显示的主要内容,如果未能解决你的问题,请参考以下文章
Android OpenCV实现人脸检测JNI层添加打印时间
如何使用opencv从相机的所有位置检测带有android的人脸?
opencv for android 如何实现后台启动摄像头,不显示预览界面