WeChat_20230718173530
6、使用手机前置摄像头进行人脸识别
package com.example.opencv;
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.content.pm.ActivityInfo;
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 MainActivity 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 MainActivity() {
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.activity_main);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.by);
mOpenCvCameraView.enableView();
mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);//前置摄像头 CameraBridgeViewBase.CAMERA_ID_BACK为后置摄像头
//这里的by也是我的项目中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();
//判断横竖屏用于进行图像的旋转
if(getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
Mat rotatedRgbMat = null;
Mat rotatedGrayMat = null;
//厂商把后置摄像头映射成前置摄像头了
Core.flip(mRgba,mRgba,1);//使用了前置摄像头,又设置了drawSource=false需要翻转左不然旋转90度之后会有问题右,
rotatedRgbMat=new Mat(mRgba.cols(), mRgba.rows(), mRgba.type());
Core.rotate(mRgba,rotatedRgbMat, Core.ROTATE_90_CLOCKWISE);//旋转之后得到正确的预览图像
mRgba = rotatedRgbMat;
Core.flip(mGray,mGray,1);//使用了前置摄像头,又设置了drawSource=false,需要翻转左右不然旋转90度之后会有问题
rotatedGrayMat=new Mat(mGray.cols(), mGray.rows(), mGray.type());
Core.rotate(mGray,rotatedGrayMat, Core.ROTATE_90_CLOCKWISE);//旋转之后得到正确的预览图像
mGray=rotatedGrayMat;
}
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, 3);
// Core.flip(mRgba, mRgba, 1);
// Core.flip(mGray, mGray, 1);
Log.e(TAG, "共检测到 " + faces.toArray().length + " 张脸");
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(MainActivity.this);
rxPermissions.request(Manifest.permission.CAMERA).subscribe(aBoolean -> {
if (aBoolean) {
initClassifier();
mOpenCvCameraView.setCameraPermissionGranted();
} else {
Toast.makeText(MainActivity.this, "您还没有开启相机权限,请前往设置->应用管理->开启", Toast.LENGTH_SHORT).show();
}
});
}
}