96 lines
3.2 KiB
Java
96 lines
3.2 KiB
Java
package com.aoleyun.sn.view;
|
||
|
||
import android.content.Context;
|
||
import android.graphics.Canvas;
|
||
import android.graphics.Color;
|
||
import android.graphics.Paint;
|
||
import android.graphics.PointF;
|
||
import android.util.AttributeSet;
|
||
import android.view.View;
|
||
|
||
import androidx.annotation.Nullable;
|
||
|
||
import java.util.Locale;
|
||
|
||
public class FaceOverlayView extends View {
|
||
private Paint pointPaint;
|
||
private Paint textPaint;
|
||
private PointF leftEye;
|
||
private PointF rightEye;
|
||
private double distance;
|
||
private int imageWidth;
|
||
private int imageHeight;
|
||
|
||
public FaceOverlayView(Context context) {
|
||
super(context);
|
||
init();
|
||
}
|
||
|
||
public FaceOverlayView(Context context, @Nullable AttributeSet attrs) {
|
||
super(context, attrs);
|
||
init();
|
||
}
|
||
|
||
private void init() {
|
||
pointPaint = new Paint();
|
||
pointPaint.setColor(Color.RED);
|
||
pointPaint.setStyle(Paint.Style.FILL);
|
||
pointPaint.setStrokeWidth(10f);
|
||
|
||
textPaint = new Paint();
|
||
textPaint.setColor(Color.YELLOW);
|
||
textPaint.setTextSize(60f);
|
||
textPaint.setFakeBoldText(true);
|
||
textPaint.setShadowLayer(5, 0, 0, Color.BLACK);
|
||
}
|
||
|
||
public void updateData(double distance, PointF leftEye, PointF rightEye, int imageWidth, int imageHeight) {
|
||
this.distance = distance;
|
||
this.leftEye = leftEye;
|
||
this.rightEye = rightEye;
|
||
this.imageWidth = imageWidth;
|
||
this.imageHeight = imageHeight;
|
||
postInvalidate();
|
||
}
|
||
|
||
@Override
|
||
protected void onDraw(Canvas canvas) {
|
||
super.onDraw(canvas);
|
||
if (leftEye == null || rightEye == null || imageWidth <= 0 || imageHeight <= 0) {
|
||
canvas.drawText("未检测到人脸", 50, 100, textPaint);
|
||
return;
|
||
}
|
||
|
||
// 1. 获取 View 的尺寸
|
||
float viewWidth = getWidth();
|
||
float viewHeight = getHeight();
|
||
|
||
// 2. 计算缩放比例 (适配 PreviewView 的 FILL_CENTER 逻辑)
|
||
// FILL_CENTER:取宽高缩放比例中较大的一个,使图像填满 View 且不拉伸,多出的部分被裁剪
|
||
float scale = Math.max(viewWidth / imageWidth, viewHeight / imageHeight);
|
||
|
||
// 3. 计算偏移量(由居中裁剪产生)
|
||
float postScaleWidth = imageWidth * scale;
|
||
float postScaleHeight = imageHeight * scale;
|
||
float offsetX = (viewWidth - postScaleWidth) / 2f;
|
||
float offsetY = (viewHeight - postScaleHeight) / 2f;
|
||
|
||
// 4. 坐标映射并处理镜像
|
||
// CameraX 的 PreviewView 显示前置摄像头时默认是镜像的
|
||
// 映射公式: viewX = viewWidth - (imageX * scale + offsetX)
|
||
float lx = viewWidth - (leftEye.x * scale + offsetX);
|
||
float ly = leftEye.y * scale + offsetY;
|
||
float rx = viewWidth - (rightEye.x * scale + offsetX);
|
||
float ry = rightEye.y * scale + offsetY;
|
||
|
||
// 绘制眼睛点位
|
||
canvas.drawCircle(lx, ly, 15, pointPaint);
|
||
canvas.drawCircle(rx, ry, 15, pointPaint);
|
||
|
||
// 绘制连线,更直观
|
||
canvas.drawLine(lx, ly, rx, ry, pointPaint);
|
||
|
||
canvas.drawText(String.format(Locale.getDefault(), "瞳距: %.2f", distance), 50, 100, textPaint);
|
||
}
|
||
}
|