Android OpenCV implements face detection (hand in hand, step by step)

1. Download OpenCV

OpenCV URL: OpenCV 

Select a version to download, here take version 4.5.3 as an example, download the Android version

 After downloading and decompressing, you get 4 files, as follows:

 2. Create an Android project

Open Android studio, create a new project, and click Import Module under the New menu under File in the upper left corner of Android studio after creation, as shown below:

 Find the newly downloaded and decompressed OpenCV directory, select sdk as module import, as shown below:

You can modify the name of the module

 After importing, you need to modify the build.gradle under the openCV module. The modified information is consistent with the version information of the build.gradle under your app.

 It should be noted that openCV4.5.3 uses kotlin, so if you develop in Java, you also need to add kotlin support in the build.gradle file under your project, as shown below:

 After that, add the module dependency to your project, and add the dependency of OpenCV module to app's build.gradle, as shown below:

 At this point, the OpenCV environment is set up, and then, face detection is realized

3. Realize face detection

1. Add layout:

        Create a new layout as the display of the interface, the code is as follows:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/di"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FAFFFFFF"
    android:orientation="vertical">

    <org.opencv.android.JavaCameraView
        android:id="@+id/cjv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00090808" />

</LinearLayout>

Opencv comes with a camera preview control, which we use directly here.

The activity code is as follows:


import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.*;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.tbruyelle.rxpermissions2.RxPermissions;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;


public class OpenCVActivity extends AppCompatActivity implements CvCameraViewListener2 {
    private static final String TAG = "OCVSample::Activity";
    private CameraBridgeViewBase mOpenCvCameraView;
    private Mat mIntermediateMat;
    private CascadeClassifier classifier;
    private Mat mGray;
    private Mat mRgba;
    private int mAbsoluteFaceSize = 0;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: {
                    Log.i(TAG, "OpenCV loaded successfully");
                    getPermission();
                    mOpenCvCameraView.enableView();
                }
                break;
                default: {
                    super.onManagerConnected(status);
                }
                break;
            }
        }
    };

    public OpenCVActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_manipulations_surface_view);
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.cjv);
        //这里的cjv也是我的项目中JavaCameraView的id,自己改一下
        mOpenCvCameraView.setCvCameraViewListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @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, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height) {
        mGray = new Mat();
        mRgba = new Mat();
    }

    public void onCameraViewStopped() {
        // Explicitly deallocate Mats
        if (mIntermediateMat != null)
            mIntermediateMat.release();
        mIntermediateMat = null;
        mGray.release();
        mRgba.release();
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
//        Mat rgba = inputFrame.rgba();
//        return rgba;
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();
        float mRelativeFaceSize = 0.2f;
        if (mAbsoluteFaceSize == 0) {
            int height = mGray.rows();
            if (Math.round(height * mRelativeFaceSize) > 0) {
                mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
            }
        }
        MatOfRect faces = new MatOfRect();
        if (classifier != null)
            classifier.detectMultiScale(mGray, faces, 1.1, 2, 2,
                    new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
        Rect[] facesArray = faces.toArray();
        Scalar faceRectColor = new Scalar(0, 255, 0, 255);
        for (Rect faceRect : facesArray)
            Imgproc.rectangle(mRgba, faceRect.tl(), faceRect.br(), faceRectColor, 1);
        return mRgba;
    }


    // 初始化人脸级联分类器,必须先初始化
    private void initClassifier() {
        try {
            InputStream is = getResources()
                    .openRawResource(R.raw.lbpcascade_frontalface);
            File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
            File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
            FileOutputStream os = new FileOutputStream(cascadeFile);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            is.close();
            os.close();
            classifier = new CascadeClassifier(cascadeFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    @SuppressLint("CheckResult")
    private void getPermission(){
        RxPermissions rxPermissions = new RxPermissions(OpenCVActivity.this);
        rxPermissions.request(Manifest.permission.CAMERA).subscribe(aBoolean -> {
            if (aBoolean) {
                initClassifier();
                mOpenCvCameraView.setCameraPermissionGranted();
            } else {
                Toast.makeText(OpenCVActivity.this, "您还没有开启相机权限,请前往设置->应用管理->开启", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

The lbpcascade_frontalface file in the code can be obtained from etc/lbpcascades/lbpcascade_frontalface.xml under the openCV module,

Copy it to the raw directory under the app, if there is no raw, create it yourself.

In addition, it should be noted that we use the camera here. The camera needs to add permissions in AndroidManifest.xml and dynamically apply for the camera above android6.0, otherwise the camera cannot be opened. AndroidManifest.xml permissions are as follows:

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

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

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.camera.front"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.camera.front.autofocus"
        android:required="true" />

4. Running effect

Guess you like

Origin blog.csdn.net/h5630/article/details/121790319