优化人脸识别显示形状

This commit is contained in:
2026-02-11 17:00:08 +08:00
parent 462755824d
commit 59b3ad72fe
5 changed files with 144 additions and 174 deletions
@@ -905,62 +905,11 @@ class MainScreenPresentation(
displayOrientation: Int,
scale: Float
): ViewGroup.LayoutParams {
// val layoutParams = previewView.layoutParams
// val measuredWidth = previewView.measuredWidth
// val measuredHeight = previewView.measuredHeight
// var ratio = (previewSize.height.toFloat()) / previewSize.width.toFloat()
// if (ratio > 1) {
// ratio = 1 / ratio
// }
// if (displayOrientation % 180 == 0) {
// layoutParams.width = measuredWidth
// layoutParams.height = (measuredWidth * ratio).toInt()
// } else {
// layoutParams.height = measuredHeight
// layoutParams.width = (measuredHeight * ratio).toInt()
// }
// if (scale < 1f) {
// val rgbParam = rgbPreview.layoutParams
// layoutParams.width = (rgbParam.width * scale).toInt()
// layoutParams.height = (rgbParam.height * scale).toInt()
// } else {
// layoutParams.width = (layoutParams.width * scale).toInt()
// layoutParams.height = (layoutParams.height * scale).toInt()
// }
//
// val metrics = DisplayMetrics()
// activity.windowManager.defaultDisplay.getMetrics(metrics)
//
// if (layoutParams.width >= metrics.widthPixels) {
// val viewRatio = layoutParams.width / (metrics.widthPixels.toFloat())
// layoutParams.width = (layoutParams.width / viewRatio).toInt()
// layoutParams.height = (layoutParams.height / viewRatio).toInt()
// }
// if (layoutParams.height >= metrics.heightPixels) {
// val viewRatio = layoutParams.height / (metrics.heightPixels.toFloat())
// layoutParams.width = (layoutParams.width / viewRatio).toInt()
// layoutParams.height = (layoutParams.height / viewRatio).toInt()
// }
// Timber.tag(TAG).d("initRgbCamera:metrics(${metrics.widthPixels},${metrics.heightPixels})")
//val layoutParams = previewView.layoutParams
//layoutParams.width = 1024
//layoutParams.height = 768
// val w = 600.dp //(912.dp * scale).toInt()
// val h = 900.dp //684.dp
// val w = 500.dp
// val h = 850.dp
val w = 600.dp
val h = 1068.dp
//(1024*scale).toInt()
val layoutParams = FrameLayout.LayoutParams(w, h);
// val layoutParams = FrameLayout.LayoutParams(480, 320);
// val layoutParams = FrameLayout.LayoutParams(912.dp, 684.dp);
previewView.setLayoutParams(layoutParams)
faceRectView.setLayoutParams(layoutParams)
return layoutParams
}
@@ -280,58 +280,9 @@ class FacePayPresentation(
displayOrientation: Int,
scale: Float
): ViewGroup.LayoutParams {
// val layoutParams = previewView.layoutParams
// val measuredWidth = previewView.measuredWidth
// val measuredHeight = previewView.measuredHeight
// var ratio = (previewSize.height.toFloat()) / previewSize.width.toFloat()
// if (ratio > 1) {
// ratio = 1 / ratio
// }
// if (displayOrientation % 180 == 0) {
// layoutParams.width = measuredWidth
// layoutParams.height = (measuredWidth * ratio).toInt()
// } else {
// layoutParams.height = measuredHeight
// layoutParams.width = (measuredHeight * ratio).toInt()
// }
// if (scale < 1f) {
// val rgbParam = rgbPreview.getLayoutParams()
// layoutParams.width = (rgbParam.width * scale).toInt()
// layoutParams.height = (rgbParam.height * scale).toInt()
// } else {
// layoutParams.width = (layoutParams.width * scale).toInt()
// layoutParams.height = (layoutParams.height * scale).toInt()
// }
//
// val metrics = DisplayMetrics()
// activity.windowManager.defaultDisplay.getMetrics(metrics)
//
// if (layoutParams.width >= metrics.widthPixels) {
// val viewRatio = layoutParams.width / (metrics.widthPixels.toFloat())
// layoutParams.width = (layoutParams.width / viewRatio).toInt()
// layoutParams.height = (layoutParams.height / viewRatio).toInt()
// }
// if (layoutParams.height >= metrics.heightPixels) {
// val viewRatio = layoutParams.height / (metrics.heightPixels.toFloat())
// layoutParams.width = (layoutParams.width / viewRatio).toInt()
// layoutParams.height = (layoutParams.height / viewRatio).toInt()
// }
// val layoutParams = previewView.layoutParams
// layoutParams.width = (608.dp * 1.5).roundToInt()
// layoutParams.height = (456.dp * 1.5).roundToInt()
// layoutParams.width = (608.dp * 1.5).roundToInt()
// layoutParams.height = (456.dp * 1.5).roundToInt()
// layoutParams.width = 1024
// layoutParams.height = 768
// val w = 500.dp
// val h = 850.dp
val w = 600.dp
val w = (600.dp * 1.5).toInt()
val h = 1068.dp
// val w = 720.dp
// val h = 1280.dp
val layoutParams = FrameLayout.LayoutParams(w, h);
val layoutParams = FrameLayout.LayoutParams(w, h)
previewView.setLayoutParams(layoutParams)
faceRectView.setLayoutParams(layoutParams)
@@ -472,9 +423,10 @@ class FacePayPresentation(
)
irFaceRectTransformer = FaceRectTransformer(
// previewSizeIr.width, previewSizeIr.height,
previewSizeIr.width, previewSizeIr.height,
// layoutParams.width, layoutParams.height,
layoutParams.width, layoutParams.height,
layoutParams.width, layoutParams.height, displayOrientation, cameraId, isMirror,
displayOrientation, cameraId, isMirror,
ConfigUtil.isDrawIrRectHorizontalMirror(context),
ConfigUtil.isDrawIrRectVerticalMirror(context)
)
@@ -0,0 +1,122 @@
package com.sw.dualscreen.view
import androidx.core.graphics.toColorInt
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
/**
* 带镂空椭圆的矩形自定义View
* 矩形尺寸:400dp × 510dp,背景色 #FFF4FAFF
* 镂空椭圆尺寸:400dp × 436dp,居中显示
*/
class HollowOvalInRectView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// 基础尺寸配置(dp
private val rectWidthDp = 400f // 矩形宽度
private val rectHeightDp = 510f // 矩形高度
private val ovalWidthDp = 400f // 椭圆宽度
private val ovalHeightDp = 436f // 椭圆高度
// 转换后的像素尺寸
private val rectWidth: Float
private val rectHeight: Float
private var ovalWidth: Float
private var ovalHeight: Float
// 矩形背景画笔(颜色 #FFF4FAFF)
private val rectPaint = Paint().apply {
isAntiAlias = true
color = "#FFF4FAFF".toColorInt() // 矩形背景色
// color = "#FFFFFF".toColorInt() // 矩形背景色
style = Paint.Style.FILL
}
// 镂空椭圆画笔(核心:DST_OUT模式实现镂空)
private val hollowOvalPaint = Paint().apply {
isAntiAlias = true
color = Color.BLACK // 颜色不影响镂空效果,仅需非透明即可
style = Paint.Style.FILL
xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
}
// 椭圆路径(复用避免重复创建)
private val ovalPath = Path()
init {
// dp转px,保证多设备尺寸一致
val density = resources.displayMetrics.density
rectWidth = rectWidthDp * density
rectHeight = rectHeightDp * density
ovalWidth = ovalWidthDp * density
ovalHeight = ovalHeightDp * density
// 关键配置:关闭硬件加速保证Xfermode生效
setLayerType(LAYER_TYPE_HARDWARE, null)
// 视图背景透明,避免干扰
setBackgroundColor(Color.TRANSPARENT)
}
/**
* 强制设置View尺寸为指定的矩形尺寸
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val targetWidth = MeasureSpec.makeMeasureSpec(rectWidth.toInt(), MeasureSpec.EXACTLY)
val targetHeight = MeasureSpec.makeMeasureSpec(rectHeight.toInt(), MeasureSpec.EXACTLY)
super.onMeasure(targetWidth, targetHeight)
}
/**
* 核心绘制逻辑:先画矩形,再画镂空椭圆
*/
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 保存画布图层,确保Xfermode生效
val layerId = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)
// 1. 绘制底层矩形(背景色 #FFF4FAFF)
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), rectPaint)
// 2. 计算椭圆居中坐标(椭圆宽度和矩形宽度一致,仅垂直居中)
val ovalTop = (rectHeight - ovalHeight) / 2 // 椭圆顶部偏移
val ovalBottom = ovalTop + ovalHeight // 椭圆底部坐标
// 3. 绘制镂空椭圆(居中)
ovalPath.reset()
ovalPath.addOval(
0f, // 左:和矩形左对齐(宽度一致)
ovalTop, // 上:垂直居中
rectWidth, // 右:和矩形右对齐
ovalBottom, // 下
Path.Direction.CW
)
canvas.drawPath(ovalPath, hollowOvalPaint)
// 恢复画布状态
canvas.restoreToCount(layerId)
}
// 扩展方法:支持动态修改矩形背景色
fun updateRectBackgroundColor(colorHex: String) {
try {
rectPaint.color = Color.parseColor(colorHex)
invalidate() // 重绘视图
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
// 扩展方法:支持动态修改椭圆尺寸(可选)
fun updateOvalSize(widthDp: Float, heightDp: Float) {
val density = resources.displayMetrics.density
ovalWidth = widthDp * density
ovalHeight = heightDp * density
invalidate()
}
}
@@ -69,7 +69,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="510dp">
<FrameLayout
android:id="@+id/flFace"
@@ -89,33 +89,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- <ImageView-->
<!-- android:id="@+id/ivPreviewImage"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent" />-->
<!-- <ImageView-->
<!-- android:id="@+id/ivFaceRecMask"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="bottom"-->
<!-- android:adjustViewBounds="true"-->
<!-- android:src="@drawable/face_mask"-->
<!-- android:visibility="visible" />-->
<!-- <TextView-->
<!-- android:id="@+id/tvFaceTip"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="bottom|center"-->
<!-- android:layout_marginBottom="56dp"-->
<!-- android:text="请正视屏幕进行面部识别..."-->
<!-- android:textColor="@color/white"-->
<!-- android:textSize="24sp"-->
<!-- android:visibility="v" />-->
<FrameLayout
android:id="@+id/fl_recognize_ir"
android:layout_width="1.3333dp"
android:id="@+id/flRecognizeIr"
android:layout_width="1.33dp"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:visibility="visible">
@@ -149,7 +125,7 @@
android:layout_weight="1"
android:background="#FFF4FAFF" />
<com.sw.dualscreen.view.HollowCircleRectView
<com.sw.dualscreen.view.HollowOvalInRectView
android:layout_width="400dp"
android:layout_height="510dp"
android:layout_gravity="center_horizontal" />
@@ -165,7 +141,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="55dp"
android:text="请正视屏幕进行面部识别..."
android:textColor="#ff5e7585"
android:textSize="22sp"
@@ -173,21 +148,12 @@
android:layout_gravity="bottom|center_horizontal"
tools:ignore="HardcodedText" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="85dp"
android:layout_gravity="bottom"
android:background="#FFF4FAFF"/>
<!-- <View-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="85dp"-->
<!-- android:layout_gravity="bottom"-->
<!-- android:background="#FFF4FAFF"/>-->
</FrameLayout>
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="55dp"-->
<!-- android:text="请正视屏幕进行面部识别..."-->
<!-- android:textColor="#ff5e7585"-->
<!-- android:textSize="22sp"-->
<!-- android:textStyle="bold"-->
<!-- tools:ignore="HardcodedText" />-->
</LinearLayout>
</LinearLayout>
@@ -72,23 +72,6 @@
android:src="@drawable/face_mask"
android:visibility="gone" />
<!-- <TextView-->
<!-- android:id="@+id/tvFaceTip"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="bottom|center"-->
<!-- android:layout_marginBottom="56dp"-->
<!-- android:text="请正视屏幕进行面部识别..."-->
<!-- android:textColor="@color/white"-->
<!-- android:textSize="22sp"-->
<!-- android:visibility="gone" />-->
<!-- <ImageView-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_margin="28dp"-->
<!-- android:background="@drawable/ic_camera_rect" />-->
</FrameLayout>
<FrameLayout
@@ -108,7 +91,7 @@
android:layout_weight="1"
android:background="#FFF4FAFF" />
<com.sw.dualscreen.view.HollowCircleRectView
<com.sw.dualscreen.view.HollowOvalInRectView
android:layout_width="400dp"
android:layout_height="510dp"
android:layout_gravity="center_horizontal" />
@@ -121,22 +104,15 @@
</LinearLayout>
<!-- <ImageView-->
<!-- android:layout_width="400dp"-->
<!-- android:layout_height="400dp"-->
<!-- android:layout_marginTop="55dp"-->
<!-- android:layout_gravity="center_horizontal"-->
<!-- android:src="@drawable/facewrap"/>-->
<TextView
android:id="@+id/tvFaceTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_gravity="bottom|center_horizontal"
android:text="请正视屏幕进行面部识别..."
android:textColor="#FF0A1428"
android:textSize="22sp" />
android:textSize="22sp"
tools:ignore="HardcodedText" />
</FrameLayout>
<com.google.android.material.imageview.ShapeableImageView
@@ -316,4 +292,9 @@
</FrameLayout>
<!-- <ImageView-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:src="@drawable/bg_face"/>-->
</FrameLayout>