深圳幻海软件技术有限公司 欢迎您!

【Android App】人脸识别中借助摄像头和OpenCV实时检测人脸讲解及实战(附源码和演示 超详细)

2023-03-01

需要全部代码请点赞关注收藏后评论区留言私信~~~一、借助摄像头实时检测人脸与Android自带的人脸检测器相比,OpenCV具备更强劲的人脸识别功能,它可以通过摄像头实时检测人脸,实时检测的预览空间是JavaCameraView常用方法说明如下setCvCameraViewListener:设置Op

需要全部代码请点赞关注收藏后评论区留言私信~~~

一、借助摄像头实时检测人脸

与Android自带的人脸检测器相比,OpenCV具备更强劲的人脸识别功能,它可以通过摄像头实时检测人脸,实时检测的预览空间是JavaCameraView 常用方法说明如下

setCvCameraViewListener:设置OpenCV的相机视图监听器。监听器需要写下列三个状态变更方法:

onCameraViewStarted:相机视图开始预览时回调。

onCameraViewStopped:相机视图停止预览时回调。

onCameraFrame:相机视图预览变更时回调。

enableView:启用OpenCV的相机视图。

 disableView:禁用OpenCV的相机视图。

接下来把JavaCameraView加入App工程,走一遍它的详细使用过程,首先修改AndroidManifest.xml补充一行相机权限配置

<uses-permission android:name="android.permission.CAMERA"/>

实时检测人脸有如下四个步骤

(1)从布局文件中获得相机视图对象后,调用它的setCvCameraViewListener方法,设置OpenCV的相机视图监听器。

(2)OpenCV初始化与资源加载完成后,调用enableView方法开启相机视图。

(3)活动类由继承AppCompatActivity改为继承CameraActivity类,并重写getCameraViewList方法,返回相机视图的单例列表。

(4)第一步重写监听器接口的onCameraFrame方法时,补充人脸识别等处理逻辑,也就是先检测人脸,再给人脸标上相框。

二、效果展示

运行测试App 会自动打开手机摄像机 然后检测摄像机内的人脸

由顶部状态栏可以看到打开了相机功能 此处用了博主小时候的照片~~~

三、代码 

部分代码如下 需要全部源码请点赞关注收藏后评论区留言~~~

  1. package com.example.face;
  2. import android.content.Context;
  3. import android.os.Bundle;
  4. import android.os.Environment;
  5. import android.util.Log;
  6. import android.widget.TextView;
  7. import com.example.face.util.DateUtil;
  8. import org.opencv.android.CameraActivity;
  9. import org.opencv.android.BaseLoaderCallback;
  10. import org.opencv.android.CameraBridgeViewBase;
  11. import org.opencv.android.LoaderCallbackInterface;
  12. import org.opencv.android.OpenCVLoader;
  13. import org.opencv.core.Core;
  14. import org.opencv.core.Mat;
  15. import org.opencv.core.MatOfRect;
  16. import org.opencv.core.Rect;
  17. import org.opencv.core.Scalar;
  18. import org.opencv.core.Size;
  19. import org.opencv.imgcodecs.Imgcodecs;
  20. import org.opencv.imgproc.Imgproc;
  21. import org.opencv.objdetect.CascadeClassifier;
  22. import java.io.File;
  23. import java.io.FileOutputStream;
  24. import java.io.InputStream;
  25. import java.util.Collections;
  26. import java.util.List;
  27. //OpenCV的实时扫描页面必须继承CameraActivity
  28. public class DetectRealtimeActivity extends CameraActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
  29. private static final String TAG = "DetectRealtimeActivity";
  30. private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
  31. private Mat mRgba, mGray; // 全彩矩阵,灰度矩阵
  32. private CascadeClassifier mJavaDetector; // OpenCV的人脸检测器
  33. private int mAbsoluteFaceSize = 0; // 绝对人脸大小
  34. // OpenCV默认横屏扫描,需要旋转90度改成竖屏预览,详细改动见CameraBridgeViewBase.java的deliverAndDrawFrame方法
  35. private CameraBridgeViewBase jcv_detect; // 声明一个OpenCV的相机视图对象
  36. @Override
  37. protected void onCreate(Bundle savedInstanceState) {
  38. super.onCreate(savedInstanceState);
  39. setContentView(R.layout.activity_detect_realtime);
  40. findViewById(R.id.iv_back).setOnClickListener(v -> finish());
  41. TextView tv_title = findViewById(R.id.tv_title);
  42. tv_title.setText("实时检测人脸");
  43. jcv_detect = findViewById(R.id.jcv_detect);
  44. jcv_detect.setVisibility(CameraBridgeViewBase.VISIBLE);
  45. jcv_detect.setCvCameraViewListener(this); // 设置OpenCV的相机视图监听器
  46. }
  47. @Override
  48. public void onPause() {
  49. super.onPause();
  50. if (jcv_detect != null) {
  51. jcv_detect.disableView(); // 禁用OpenCV的相机视图
  52. }
  53. }
  54. @Override
  55. public void onResume() {
  56. super.onResume();
  57. if (!OpenCVLoader.initDebug()) {
  58. Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
  59. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
  60. } else {
  61. Log.d(TAG, "OpenCV library found inside package. Using it!");
  62. mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
  63. }
  64. }
  65. @Override
  66. protected List<? extends CameraBridgeViewBase> getCameraViewList() {
  67. return Collections.singletonList(jcv_detect);
  68. }
  69. @Override
  70. public void onDestroy() {
  71. super.onDestroy();
  72. jcv_detect.disableView(); // 禁用OpenCV的相机视图
  73. }
  74. @Override
  75. public void onCameraViewStarted(int width, int height) {
  76. mGray = new Mat();
  77. mRgba = new Mat();
  78. }
  79. @Override
  80. public void onCameraViewStopped() {
  81. mGray.release();
  82. mRgba.release();
  83. }
  84. // 相机预览回调
  85. @Override
  86. public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
  87. mRgba = inputFrame.rgba();
  88. mGray = inputFrame.gray();
  89. Core.rotate(mRgba, mRgba, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90
  90. Core.rotate(mGray, mGray, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90
  91. if (mAbsoluteFaceSize == 0) {
  92. Log.d(TAG, "width="+mGray.width()+", height="+mGray.height()+", cols="+mGray.cols()+", rows="+mGray.rows());
  93. int height = mGray.rows();
  94. if (Math.round(height * 0.2f) > 0) {
  95. mAbsoluteFaceSize = Math.round(height * 0.2f);
  96. }
  97. // String filePath = String.format("%s/%s.jpg",
  98. // getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
  99. // DateUtil.getNowDateTime());
  100. // Imgcodecs.imwrite(filePath, mRgba);
  101. // Log.d(TAG, "filePath="+filePath);
  102. }
  103. MatOfRect faces = new MatOfRect();
  104. if (mJavaDetector != null) { // 检测器开始识别人脸
  105. mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2,
  106. new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
  107. }
  108. Rect[] faceArray = faces.toArray();
  109. for (Rect rect : faceArray) { // 给找到的人脸标上相框
  110. Imgproc.rectangle(mRgba, rect.tl(), rect.br(), FACE_RECT_COLOR, 3);
  111. Log.d(TAG, rect.toString());
  112. }
  113. Core.rotate(mRgba, mRgba, Core.ROTATE_90_COUNTERCLOCKWISE); // 恢复原状,逆时针旋转90
  114. return mRgba;
  115. }
  116. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
  117. @Override
  118. public void onManagerConnected(int status) {
  119. if (status == LoaderCallbackInterface.SUCCESS) {
  120. Log.d(TAG, "OpenCV loaded successfully");
  121. // 在OpenCV初始化完成后加载so库
  122. System.loadLibrary("detection_based_tracker");
  123. File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
  124. File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
  125. // 从应用程序资源加载级联文件
  126. try (InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
  127. FileOutputStream os = new FileOutputStream(cascadeFile)) {
  128. byte[] buffer = new byte[4096];
  129. int bytesRead;
  130. while ((bytesRead = is.read(buffer)) != -1) {
  131. os.write(buffer, 0, bytesRead);
  132. }
  133. } catch (Exception e) {
  134. e.printStackTrace();
  135. }
  136. // 根据级联文件创建OpenCV的人脸检测器
  137. mJavaDetector = new CascadeClassifier(cascadeFile.getAbsolutePath());
  138. if (mJavaDetector.empty()) {
  139. Log.d(TAG, "Failed to load cascade classifier");
  140. mJavaDetector = null;
  141. } else {
  142. Log.d(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath());
  143. }
  144. cascadeDir.delete();
  145. jcv_detect.enableView(); // 启用OpenCV的相机视图
  146. } else {
  147. super.onManagerConnected(status);
  148. }
  149. }
  150. };
  151. }

创作不易  觉得有帮助请点赞关注收藏~~~

文章知识点与官方知识档案匹配,可进一步学习相关知识
OpenCV技能树首页概览13322 人正在系统学习中