为什么要改?
先来看看sdk demo中提供的人脸框样式,这个框看上去并不是非常美观(个人觉得)
再看看下面这个框是不是就要顺眼一点
怎么换?
先来看看原始的画法:
@Override
public void onAfterRender(CameraFrameData data) {
mGLSurfaceView.getGLES2Render().draw_rect((Rect[]) data.getParams(), Color.GREEN, 2);
}
其实更换人脸识别框是非常简单的,因为虹软的人脸识别sdk已经将人脸的位置回调出来了,实时回调的是一个Rect(将回调出来的CameraFrameData强转一下即可),既然都知道人脸框的位置,那就是一个自定义View就解决的事了。
只需要在onDraw方法中画八条线即可
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (rect != null) {
/**
* 左上角的竖线
*/
canvas.drawLine(rect.left, rect.top, rect.left, rect.top + 20, mPaint);
/**
* 左上角的横线
*/
canvas.drawLine(rect.left, rect.top, rect.left + 20, rect.top, mPaint);
/**
* 右上角的竖线
*/
canvas.drawLine(rect.right, rect.top, rect.right - 20, rect.top, mPaint);
/**
* 右上角的横线
*/
canvas.drawLine(rect.right, rect.top, rect.right, rect.top + 20, mPaint);
/**
* 左下角的竖线
*/
canvas.drawLine(rect.left, rect.bottom, rect.left, rect.bottom - 20, mPaint);
/**
* 左下角的横线
*/
canvas.drawLine(rect.left, rect.bottom, rect.left + 20, rect.bottom, mPaint);
/**
* 右下角的竖线
*/
canvas.drawLine(rect.right, rect.bottom, rect.right, rect.bottom-20, mPaint);
/**
* 右下角的横线
*/
canvas.drawLine(rect.right, rect.bottom, rect.right-20, rect.bottom , mPaint);
}
}
这里其实还有一个坑,就是这个Rect是相对于相机分辨率的,但是如果摄像头的预览分辨率不等于画布的大小就会出现错位的情况,比如下面的情况:(绿框是虹软demo中的人脸框,蓝色框是自定义的框)
怎么解决呢?你应该想到了,将宽高等比例缩放一下即可,所以提供画人脸框的一个方法:
/**
* 开始画矩形框
*
* @param rect1
*/
public void drawFaceRect(Rect rect1) {
this.rect = rect1;
//将屏幕人脸框转换为视频区域的人脸框
rect.left = rect.left * getWidth() / screenHeight+20;
rect.right = rect.right * getWidth() / screenHeight+40;
rect.top = rect.top * getHeight() / screenHeight+30;
rect.bottom = rect.bottom * getHeight() / screenHeight+75;
//在主线程发起绘制请求
postInvalidate();
}
注意:此处的+20,+40,+30,+75都是经验值,都是相对于左上右下的位置,可根据自己的设备做微调。
此外我们还需要提供一个清除人脸框的方法(没有识别到人脸的时候框要消失):
public void clearRect() {
rect = null;
postInvalidate();
}
下面是本View完整的代码(只是demo,还有优化的地方,只是提供一种思路,思路理解了,还可以画很多炫酷的框):
/**
* 自定义虹软人脸识别框/人脸抓拍框/人脸追踪框
* Created by HDL on 2018/7/31.
*/
public class FaceRectView extends View {
private Rect rect;
private int screenWidth;
private int screenHeight;
public FaceRectView(Context context) {
this(context, null);
}
public FaceRectView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FaceRectView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
screenHeight = wm.getDefaultDisplay().getHeight();
initPaint(context);
}
private void initPaint(Context context) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(3);
mPaint.setColor(context.getResources().getColor(R.color.color_face_rect));
}
private Paint mPaint;
/**
* 开始画矩形框
*
* @param rect1
*/
public void drawFaceRect(Rect rect1) {
this.rect = rect1;
//将屏幕人脸框转换为视频区域的人脸框
rect.left = rect.left * getWidth() / screenHeight+20;
rect.right = rect.right * getWidth() / screenHeight+40;
rect.top = rect.top * getHeight() / screenHeight+30;
rect.bottom = rect.bottom * getHeight() / screenHeight+75;
//在主线程发起绘制请求
postInvalidate();
}
public void clearRect() {
rect = null;
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (rect != null) {
/**
* 左上角的竖线
*/
canvas.drawLine(rect.left, rect.top, rect.left, rect.top + 20, mPaint);
/**
* 左上角的横线
*/
canvas.drawLine(rect.left, rect.top, rect.left + 20, rect.top, mPaint);
/**
* 右上角的竖线
*/
canvas.drawLine(rect.right, rect.top, rect.right - 20, rect.top, mPaint);
/**
* 右上角的横线
*/
canvas.drawLine(rect.right, rect.top, rect.right, rect.top + 20, mPaint);
/**
* 左下角的竖线
*/
canvas.drawLine(rect.left, rect.bottom, rect.left, rect.bottom - 20, mPaint);
/**
* 左下角的横线
*/
canvas.drawLine(rect.left, rect.bottom, rect.left + 20, rect.bottom, mPaint);
/**
* 右下角的竖线
*/
canvas.drawLine(rect.right, rect.bottom, rect.right, rect.bottom-20, mPaint);
/**
* 右下角的横线
*/
canvas.drawLine(rect.right, rect.bottom, rect.right-20, rect.bottom , mPaint);
}
}
}
2018.9.27更新
有小伙伴不知道怎么使用,只需要在onAfterRender回调中使用即可
@Override
public void onAfterRender(CameraFrameData data) {
params = (Rect[]) data.getParams();
if (params.length > 0) {
param = params[0];
faceRectView.drawFaceRect(param);
} else {
faceRectView.clearRect();
}
}