需要全部代码请点赞关注收藏后评论区留言私信~~~
一、借助摄像头实时检测人脸
与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 会自动打开手机摄像机 然后检测摄像机内的人脸
由顶部状态栏可以看到打开了相机功能 此处用了博主小时候的照片~~~
三、代码
部分代码如下 需要全部源码请点赞关注收藏后评论区留言~~~
- package com.example.face;
-
- import android.content.Context;
- import android.os.Bundle;
- import android.os.Environment;
- import android.util.Log;
- import android.widget.TextView;
-
- import com.example.face.util.DateUtil;
-
- import org.opencv.android.CameraActivity;
-
- import org.opencv.android.BaseLoaderCallback;
- import org.opencv.android.CameraBridgeViewBase;
- import org.opencv.android.LoaderCallbackInterface;
- import org.opencv.android.OpenCVLoader;
- import org.opencv.core.Core;
- import org.opencv.core.Mat;
- import org.opencv.core.MatOfRect;
- import org.opencv.core.Rect;
- import org.opencv.core.Scalar;
- import org.opencv.core.Size;
- import org.opencv.imgcodecs.Imgcodecs;
- import org.opencv.imgproc.Imgproc;
- import org.opencv.objdetect.CascadeClassifier;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.util.Collections;
- import java.util.List;
-
- //OpenCV的实时扫描页面必须继承CameraActivity
- public class DetectRealtimeActivity extends CameraActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
- private static final String TAG = "DetectRealtimeActivity";
- private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
- private Mat mRgba, mGray; // 全彩矩阵,灰度矩阵
- private CascadeClassifier mJavaDetector; // OpenCV的人脸检测器
- private int mAbsoluteFaceSize = 0; // 绝对人脸大小
- // OpenCV默认横屏扫描,需要旋转90度改成竖屏预览,详细改动见CameraBridgeViewBase.java的deliverAndDrawFrame方法
- private CameraBridgeViewBase jcv_detect; // 声明一个OpenCV的相机视图对象
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_detect_realtime);
- findViewById(R.id.iv_back).setOnClickListener(v -> finish());
- TextView tv_title = findViewById(R.id.tv_title);
- tv_title.setText("实时检测人脸");
- jcv_detect = findViewById(R.id.jcv_detect);
- jcv_detect.setVisibility(CameraBridgeViewBase.VISIBLE);
- jcv_detect.setCvCameraViewListener(this); // 设置OpenCV的相机视图监听器
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (jcv_detect != null) {
- jcv_detect.disableView(); // 禁用OpenCV的相机视图
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (!OpenCVLoader.initDebug()) {
- Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
- OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
- } else {
- Log.d(TAG, "OpenCV library found inside package. Using it!");
- mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
- }
- }
-
- @Override
- protected List<? extends CameraBridgeViewBase> getCameraViewList() {
- return Collections.singletonList(jcv_detect);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- jcv_detect.disableView(); // 禁用OpenCV的相机视图
- }
-
- @Override
- public void onCameraViewStarted(int width, int height) {
- mGray = new Mat();
- mRgba = new Mat();
- }
-
- @Override
- public void onCameraViewStopped() {
- mGray.release();
- mRgba.release();
- }
-
- // 相机预览回调
- @Override
- public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
- mRgba = inputFrame.rgba();
- mGray = inputFrame.gray();
- Core.rotate(mRgba, mRgba, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90度
- Core.rotate(mGray, mGray, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90度
- if (mAbsoluteFaceSize == 0) {
- Log.d(TAG, "width="+mGray.width()+", height="+mGray.height()+", cols="+mGray.cols()+", rows="+mGray.rows());
- int height = mGray.rows();
- if (Math.round(height * 0.2f) > 0) {
- mAbsoluteFaceSize = Math.round(height * 0.2f);
- }
- // String filePath = String.format("%s/%s.jpg",
- // getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
- // DateUtil.getNowDateTime());
- // Imgcodecs.imwrite(filePath, mRgba);
- // Log.d(TAG, "filePath="+filePath);
- }
- MatOfRect faces = new MatOfRect();
- if (mJavaDetector != null) { // 检测器开始识别人脸
- mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2,
- new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
- }
- Rect[] faceArray = faces.toArray();
- for (Rect rect : faceArray) { // 给找到的人脸标上相框
- Imgproc.rectangle(mRgba, rect.tl(), rect.br(), FACE_RECT_COLOR, 3);
- Log.d(TAG, rect.toString());
- }
- Core.rotate(mRgba, mRgba, Core.ROTATE_90_COUNTERCLOCKWISE); // 恢复原状,逆时针旋转90度
- return mRgba;
- }
-
- private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
- @Override
- public void onManagerConnected(int status) {
- if (status == LoaderCallbackInterface.SUCCESS) {
- Log.d(TAG, "OpenCV loaded successfully");
- // 在OpenCV初始化完成后加载so库
- System.loadLibrary("detection_based_tracker");
- File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
- File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
- // 从应用程序资源加载级联文件
- try (InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
- FileOutputStream os = new FileOutputStream(cascadeFile)) {
- byte[] buffer = new byte[4096];
- int bytesRead;
- while ((bytesRead = is.read(buffer)) != -1) {
- os.write(buffer, 0, bytesRead);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- // 根据级联文件创建OpenCV的人脸检测器
- mJavaDetector = new CascadeClassifier(cascadeFile.getAbsolutePath());
- if (mJavaDetector.empty()) {
- Log.d(TAG, "Failed to load cascade classifier");
- mJavaDetector = null;
- } else {
- Log.d(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath());
- }
- cascadeDir.delete();
- jcv_detect.enableView(); // 启用OpenCV的相机视图
- } else {
- super.onManagerConnected(status);
- }
- }
- };
-
- }
创作不易 觉得有帮助请点赞关注收藏~~~