[Application Android] Dans la reconnaissance faciale, détection en temps réel des visages à l'aide de la caméra et d'OpenCV Explication et combat réel (avec code source et démonstration super détaillée)

Si vous avez besoin de tous les codes, veuillez aimer et suivre la collection et laisser un message privé dans la zone de commentaire ~~~

1. Détection en temps réel des visages à l'aide de caméras

Par rapport au détecteur de visage fourni avec Android, OpenCV dispose d'une fonction de reconnaissance faciale plus puissante. Il peut détecter les visages en temps réel via la caméra. L'espace de prévisualisation pour la détection en temps réel est JavaCameraView. Les méthodes courantes sont décrites ci-dessous.

setCvCameraViewListener : définit l'écouteur de la vue de la caméra d'OpenCV. Les écouteurs doivent écrire les trois méthodes de changement d'état suivantes :

onCameraViewStarted : Rappel lorsque la vue de la caméra démarre la prévisualisation.

onCameraViewStopped : rappel lorsque la vue de la caméra arrête la prévisualisation.

onCameraFrame : appelé lorsque l'aperçu de la vue de la caméra change.

enableView : active la vue de la caméra d'OpenCV.

 disableView : désactive la vue de la caméra d'OpenCV.

Ensuite, ajoutez JavaCameraView au projet App, suivez son processus d'utilisation détaillé, modifiez d'abord AndroidManifest.xml pour ajouter une ligne de configuration d'autorisation de caméra

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

La détection de visage en temps réel comporte les quatre étapes suivantes

(1) Après avoir obtenu l'objet de vue de caméra à partir du fichier de mise en page, appelez sa méthode setCvCameraViewListener pour définir l'écouteur de vue de caméra OpenCV.

(2) Une fois l'initialisation d'OpenCV et le chargement des ressources terminés, appelez la méthode enableView pour ouvrir la vue de la caméra.

(3) La classe d'activité passe de l'héritage d'AppCompatActivity à l'héritage de la classe CameraActivity, et la réécriture de la méthode getCameraViewList pour renvoyer la liste singleton des vues de caméra.

(4) Lors de la réécriture de la méthode onCameraFrame de l'interface d'écoute dans la première étape, ajoutez une logique de traitement telle que la reconnaissance faciale, c'est-à-dire, détectez d'abord le visage, puis marquez le visage avec un cadre photo.

2. Affichage des effets

L'exécution de l'application de test allumera automatiquement l'appareil photo du téléphone et détectera les visages dans l'appareil photo

Dans la barre d'état supérieure, vous pouvez voir que la fonction appareil photo est activée. Voici les photos du blogueur lorsqu'il était enfant ~~~

3. Coder 

Une partie du code est la suivante, tout le code source est requis, veuillez aimer et suivre la collection et laisser un message dans la zone de commentaire ~~~

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);
            }
        }
    };

}

Ce n'est pas facile à créer, si vous le trouvez utile, veuillez aimer, suivre et collecter ~~~

Je suppose que tu aimes

Origine blog.csdn.net/jiebaoshayebuhui/article/details/128157645
conseillé
Classement