基于Camera实现人脸检测
2020-03-18 本文已影响0人
编程的猫
先看效果:

在原来Camera1的代码的基础上添加以下代码:
Camera1Helper中添加,追踪人脸信息:
/**
* 开启人脸检测
*/
public void startFaceDetech() {
if (mCamera != null) {
mCamera.startFaceDetection();
mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
@Override
public void onFaceDetection(Camera.Face[] faces, Camera camera) {
if (facesListener != null) {
if (faces != null && faces.length > 0)
facesListener.faces(transform(faces));
else
facesListener.clearFace();
}
}
});
}
}
/**
* 绘制矩形检测框
*/
private ArrayList<RectF> transform(Camera.Face[] faces) {
Matrix matrix = new Matrix();
if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
matrix.setScale(-1, 1);
} else {
matrix.setScale(1, 1);
}
int width = surfaceView.getWidth();
int height = surfaceView.getHeight();
matrix.postRotate(mDisplayOrientation);
matrix.postScale(width / 2000F, height / 2000F);
matrix.postTranslate(width / 2F, height / 2F);
ArrayList<RectF> rectFS = new ArrayList<>();
for (Camera.Face face : faces) {
RectF srcRectF = new RectF(face.rect);
RectF descRectF = new RectF(0, 0, 0, 0);
matrix.mapRect(descRectF, srcRectF);
rectFS.add(descRectF);
}
return rectFS;
}
在开启相机预览之后调用,开启人脸追踪:
/**
* 第四步:开启预览
*/
private void startPreview() {
try {
mCamera.setPreviewDisplay(surfaceHolder);
//设置预览时相机的旋转角度
setCameraDisplayOrientation();
mCamera.startPreview();
//开启人脸检测
startFaceDetech();
isActivedPreview = true;
} catch (IOException e) {
e.printStackTrace();
}
}
自定义一个FaceView:
public class FaceView extends View {
private static final String TAG = "FaceView";
private ArrayList<RectF> faces;
private Paint paint;
public FaceView(Context context) {
super(context);
init(context);
}
public FaceView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public FaceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
/**
* 初始化paint
*
* @param context context
*/
private void init(Context context) {
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f,
context.getResources().getDisplayMetrics()));
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
Log.i(TAG, " draw");
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, " onDraw");
if (faces != null && faces.size() > 0) {
//因为会同时存在多张人脸,所以用循环
for (RectF face : faces) {
//绘制人脸所在位置的矩形
Log.i(TAG, "绘制:" + face.top + " " + face.bottom);
canvas.drawRect(face, paint);
}
}
}
/**
* 设置人脸信息,然后刷新FaceView
*
* @param mFace mFace
*/
public void setFaces(ArrayList<RectF> mFace) {
this.faces = mFace;
postInvalidate();
}
public void clearRect() {
if (faces != null && faces.size() > 0)
faces.clear();
postInvalidate();
}
}
人脸信息回调:
public interface FacesListener {
void faces(ArrayList<RectF> rectFS);
void clearFace();
}
activity中调用
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
surfaceView = view.findViewById(R.id.surfaceView);
switchCamera = view.findViewById(R.id.switchCamera);
takePhoto = view.findViewById(R.id.takePhoto);
faceView = view.findViewById(R.id.faceView);
if (camera1Helper == null)
camera1Helper = new Camera1Helper(Objects.requireNonNull(getActivity()), surfaceView);
switchCamera.setOnClickListener(this);
takePhoto.setOnClickListener(this);
camera1Helper.setFacesListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.switchCamera) {
faceView.clearRect();
camera1Helper.switchCamera();
} else if (v.getId() == R.id.takePhoto) {
camera1Helper.takePhoto();
}
}
@Override
public void faces(ArrayList<RectF> rectFS) {
faceView.setFaces(rectFS);
}
@Override
public void clearFace() {
faceView.clearRect();
}
可参考这篇博文的注解:
Android: Camera相机开发详解(下) —— 实现人脸检测功能