MogFace人脸检测Streamlit应用进阶:添加人脸关键点检测扩展功能教程

张开发
2026/4/4 8:43:28 15 分钟阅读
MogFace人脸检测Streamlit应用进阶:添加人脸关键点检测扩展功能教程
MogFace人脸检测Streamlit应用进阶添加人脸关键点检测扩展功能教程1. 引言从检测到分析让人脸应用更智能人脸检测技术已经相当成熟了但很多时候我们需要的不仅仅是知道这里有人脸而是想知道这张脸的具体特征。想象一下你正在开发一个美颜应用需要精确定位眼睛、鼻子、嘴巴的位置或者在做表情分析需要知道眉毛、嘴角的变化又或者在做虚拟试妆需要准确找到五官的位置。这就是人脸关键点检测的价值所在。它能在人脸检测的基础上进一步定位出人脸上的几十个甚至上百个关键点让计算机真正看懂人脸的结构。今天我要分享的就是如何在现有的MogFace人脸检测Streamlit应用基础上添加人脸关键点检测功能。这个扩展不仅能让你的应用功能更强大还能为后续的人脸分析、表情识别、虚拟化妆等应用打下基础。学完这篇教程你将能够理解人脸关键点检测的基本原理和应用场景在现有MogFace应用基础上集成关键点检测模型构建一个既能检测人脸又能定位关键点的完整应用掌握关键点数据的可视化方法和实际应用前置条件已经部署了基础的MogFace人脸检测应用熟悉Python基础语法和Streamlit框架了解基本的深度学习概念不需要深入2. 人脸关键点检测不只是找到脸还要看懂脸2.1 什么是人脸关键点检测简单来说人脸关键点检测就是在人脸图像上找到一系列有意义的点比如眼角、鼻尖、嘴角、下巴轮廓等。这些点就像人脸的骨架定义了人脸的基本形状和特征。常见的点位数有5点两个眼睛中心、鼻尖、两个嘴角68点更详细的五官轮廓包括眉毛、眼睛、鼻子、嘴巴、下巴98点/106点更密集的点位适合精细的人脸分析2.2 为什么需要关键点检测你可能会有疑问我已经能检测到人脸了为什么还要关键点让我用几个实际例子来说明美颜应用场景# 没有关键点检测 检测到人脸 → 对整个脸区域进行磨皮、美白 # 有关键点检测 检测到人脸 → 定位眼睛、嘴巴位置 → - 只对皮肤区域磨皮避开眼睛、嘴巴 - 精准放大眼睛 - 调整嘴唇颜色 - 瘦脸调整下巴轮廓点虚拟试妆场景眼影需要知道眼睑位置口红需要知道嘴唇轮廓美瞳需要知道瞳孔位置腮红需要知道脸颊区域安防监控场景表情分析通过嘴角、眉毛位置变化判断情绪疲劳检测通过眼睛开合程度判断是否疲劳身份验证通过关键点特征进行更精准的人脸比对2.3 关键技术原理简单版不用担心我不会用复杂的数学公式吓到你。关键点检测的核心思想其实很直观特征提取就像人脸检测一样先用神经网络提取图像特征坐标回归网络学习预测每个关键点的(x, y)坐标形状约束确保预测的点符合人脸的基本结构比如两个眼睛应该在同一水平线上现在主流的模型都能在普通电脑上实时运行准确率也很高。3. 环境准备与模型选择3.1 新增依赖安装在原有MogFace应用的基础上我们需要安装一些额外的包# 如果还没有安装基础环境 pip install modelscope opencv-python torch streamlit pillow numpy # 新增的关键点检测相关依赖 pip install mediapipe # 谷歌的轻量级关键点检测库 # 或者使用其他关键点模型 pip install dlib # 传统的68点检测需要下载预训练模型我推荐使用MediaPipe原因有几个安装简单不需要额外下载模型文件速度快能在CPU上实时运行准确率高支持468个3D关键点开源免费商业友好3.2 模型文件准备如果你选择使用其他模型比如Dlib的68点模型需要下载预训练文件# dlib的68点模型下载如果需要 import dlib # 模型会自动下载到用户目录或者你可以手动指定路径 predictor_path shape_predictor_68_face_landmarks.dat对于MediaPipe不需要额外下载首次运行时会自动下载模型。3.3 检查现有代码结构在开始修改之前先看看我们现有的MogFace应用代码结构# app.py 现有结构概览 import streamlit as st import cv2 import numpy as np from PIL import Image from modelscope.pipelines import pipeline # 1. 页面配置 st.set_page_config(layoutwide) # 2. 模型加载缓存 st.cache_resource def load_model(): return pipeline(face-detection, model/root/ai-models/iic/cv_resnet101_face-detection_cvpr22papermogface) # 3. 侧边栏 with st.sidebar: # 模型信息显示 # 重置按钮 # 4. 主界面布局 col1, col2 st.columns(2) with col1: # 图片上传 uploaded_file st.file_uploader(...) with col2: if uploaded_file: # 显示检测结果 if st.button( 开始检测): # 调用模型检测 results model(image) # 绘制检测框 # 显示结果我们需要在这个基础上添加关键点检测功能。4. 集成关键点检测功能4.1 添加关键点检测模型首先在模型加载部分添加关键点检测模型import streamlit as st import cv2 import numpy as np from PIL import Image from modelscope.pipelines import pipeline import mediapipe as mp # 新增导入 # 初始化MediaPipe人脸关键点检测 mp_face_mesh mp.solutions.face_mesh face_mesh mp_face_mesh.FaceMesh( static_image_modeTrue, # 静态图片模式 max_num_faces10, # 最多检测10张脸 refine_landmarksTrue, # 使用更精细的关键点包括瞳孔 min_detection_confidence0.5 # 检测置信度阈值 ) # 原有的MogFace模型加载 st.cache_resource def load_face_detection_model(): return pipeline(face-detection, model/root/ai-models/iic/cv_resnet101_face-detection_cvpr22papermogface) # 加载模型 detection_model load_face_detection_model()4.2 修改检测处理函数我们需要修改检测按钮的处理逻辑让它同时进行人脸检测和关键点检测def detect_faces_and_landmarks(image_np): 同时进行人脸检测和关键点检测 results {} # 1. 使用MogFace进行人脸检测 detection_results detection_model(image_np) results[detections] detection_results # 2. 使用MediaPipe进行关键点检测 # 转换颜色空间MediaPipe需要RGB image_rgb cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB) # 进行关键点检测 landmarks_results face_mesh.process(image_rgb) results[landmarks] landmarks_results return results4.3 添加关键点绘制函数检测到关键点后我们需要把它们可视化出来def draw_landmarks_on_image(image_np, landmarks_result, face_detections): 在图像上绘制关键点 image_copy image_np.copy() h, w, _ image_copy.shape if landmarks_result.multi_face_landmarks: for face_landmarks in landmarks_result.multi_face_landmarks: # 绘制所有关键点 for landmark in face_landmarks.landmark: # 将归一化坐标转换为像素坐标 x int(landmark.x * w) y int(landmark.y * h) # 绘制点红色小圆点 cv2.circle(image_copy, (x, y), 1, (0, 0, 255), -1) # 绘制关键轮廓线可选 # 这里可以添加代码绘制眼睛、嘴唇等轮廓 return image_copy4.4 修改主界面显示逻辑现在修改主界面的显示部分同时展示人脸检测框和关键点with col2: if uploaded_file: if st.button( 开始检测含关键点): # 转换图片格式 image Image.open(uploaded_file) image_np np.array(image.convert(RGB)) # 进行检测 with st.spinner(正在检测人脸和关键点...): results detect_faces_and_landmarks(image_np) # 绘制人脸检测框原有功能 detected_image image_np.copy() for det in results[detections]: bbox det[box] score det[score] # 绘制绿色检测框 cv2.rectangle(detected_image, (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3])), (0, 255, 0), 2) # 添加置信度标签 cv2.putText(detected_image, f{score:.2f}, (int(bbox[0]), int(bbox[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 绘制关键点新增功能 if results[landmarks].multi_face_landmarks: detected_image draw_landmarks_on_image( detected_image, results[landmarks], results[detections] ) # 显示结果 st.image(detected_image, caption检测结果绿色框红色关键点, use_column_widthTrue) # 显示统计信息 face_count len(results[detections]) landmark_count 0 if results[landmarks].multi_face_landmarks: for face_landmarks in results[landmarks].multi_face_landmarks: landmark_count len(face_landmarks.landmark) st.success(f✅ 检测到 {face_count} 张人脸共 {landmark_count} 个关键点)5. 功能增强与界面优化5.1 添加关键点显示控制不是所有时候都需要显示468个点我们可以添加控制选项# 在侧边栏添加控制选项 with st.sidebar: st.subheader( 关键点检测设置) # 是否启用关键点检测 enable_landmarks st.checkbox(启用关键点检测, valueTrue) # 关键点显示模式 landmark_mode st.radio( 关键点显示模式, [全部点, 只显示轮廓, 自定义选择], index0 ) # 如果选择自定义让用户选择要显示的点 if landmark_mode 自定义选择: col_a, col_b st.columns(2) with col_a: show_eyes st.checkbox(眼睛, valueTrue) show_nose st.checkbox(鼻子, valueTrue) with col_b: show_mouth st.checkbox(嘴巴, valueTrue) show_face st.checkbox(脸部轮廓, valueTrue)5.2 改进关键点绘制函数根据用户选择显示不同的关键点def draw_selected_landmarks(image_np, landmarks_result, options): 根据选项绘制选中的关键点 image_copy image_np.copy() h, w, _ image_copy.shape # MediaPipe的关键点索引部分 # 眼睛左眼[33, 133], 右眼[362, 263] # 嘴唇外轮廓[61, 146, 91, 181] # 鼻子鼻尖[1] # 脸部轮廓[10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288] if landmarks_result.multi_face_landmarks: for face_landmarks in landmarks_result.multi_face_landmarks: landmarks face_landmarks.landmark # 根据选项绘制不同的点 if options[mode] 全部点: # 绘制所有点 for i, landmark in enumerate(landmarks): x int(landmark.x * w) y int(landmark.y * h) cv2.circle(image_copy, (x, y), 2, (0, 0, 255), -1) elif options[mode] 只显示轮廓: # 只绘制脸部轮廓点 contour_indices [10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288, 397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136, 172, 58, 132, 93, 234, 127, 162, 21, 54, 103, 67, 109] for idx in contour_indices: if idx len(landmarks): landmark landmarks[idx] x int(landmark.x * w) y int(landmark.y * h) cv2.circle(image_copy, (x, y), 2, (0, 255, 255), -1) elif options[mode] 自定义选择: # 根据用户选择绘制 color_map { eyes: (255, 0, 0), # 蓝色 nose: (0, 255, 0), # 绿色 mouth: (0, 0, 255), # 红色 face: (255, 255, 0) # 青色 } # 这里可以添加更精细的点选择逻辑 # 简化版绘制大致区域 return image_copy5.3 添加关键点数据导出除了可视化我们还可以让用户导出关键点数据# 在结果显示部分添加数据导出 if results[landmarks].multi_face_landmarks: # 创建关键点数据 landmarks_data [] for i, face_landmarks in enumerate(results[landmarks].multi_face_landmarks): face_points [] for j, landmark in enumerate(face_landmarks.landmark): face_points.append({ index: j, x: landmark.x, y: landmark.y, z: landmark.z if hasattr(landmark, z) else 0 }) landmarks_data.append({ face_index: i, landmarks: face_points }) # 显示数据 with st.expander( 查看关键点数据): st.json(landmarks_data) # 提供下载 import json landmarks_json json.dumps(landmarks_data, indent2) st.download_button( label 下载关键点数据 (JSON), datalandmarks_json, file_nameface_landmarks.json, mimeapplication/json )6. 完整代码整合把上面的所有功能整合起来这里是一个完整的代码示例import streamlit as st import cv2 import numpy as np from PIL import Image from modelscope.pipelines import pipeline import mediapipe as mp import json # 页面配置 st.set_page_config( page_titleMogFace人脸检测关键点, page_icon️, layoutwide ) # 初始化MediaPipe mp_face_mesh mp.solutions.face_mesh face_mesh mp_face_mesh.FaceMesh( static_image_modeTrue, max_num_faces10, refine_landmarksTrue, min_detection_confidence0.5 ) # 加载MogFace模型 st.cache_resource def load_face_detection_model(): return pipeline(face-detection, model/root/ai-models/iic/cv_resnet101_face-detection_cvpr22papermogface) detection_model load_face_detection_model() # 检测函数 def detect_faces_and_landmarks(image_np): 同时进行人脸检测和关键点检测 results {} # 人脸检测 detection_results detection_model(image_np) results[detections] detection_results # 关键点检测 image_rgb cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB) landmarks_results face_mesh.process(image_rgb) results[landmarks] landmarks_results return results # 绘制函数 def draw_detections_and_landmarks(image_np, detections, landmarks_result, draw_landmarksTrue): 绘制检测框和关键点 image_copy image_np.copy() h, w, _ image_copy.shape # 绘制人脸检测框 for det in detections: bbox det[box] score det[score] cv2.rectangle(image_copy, (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3])), (0, 255, 0), 2) cv2.putText(image_copy, f{score:.2f}, (int(bbox[0]), int(bbox[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 绘制关键点 if draw_landmarks and landmarks_result.multi_face_landmarks: for face_landmarks in landmarks_result.multi_face_landmarks: for landmark in face_landmarks.landmark: x int(landmark.x * w) y int(landmark.y * h) cv2.circle(image_copy, (x, y), 1, (0, 0, 255), -1) return image_copy # 侧边栏 with st.sidebar: st.header(⚙️ 设置) st.subheader(模型信息) st.info( **MogFace ResNet101** - 人脸检测模型 - CVPR 2022 顶会算法 - 支持复杂场景检测 ) st.subheader( 关键点设置) enable_landmarks st.checkbox(启用关键点检测, valueTrue) if enable_landmarks: landmark_display st.selectbox( 显示模式, [全部关键点, 只显示轮廓, 简化显示], index0 ) if st.button( 重置应用): st.rerun() # 主界面 st.title(️ MogFace 人脸检测 关键点定位) st.markdown(上传图片检测人脸并定位关键点) col1, col2 st.columns(2) with col1: st.subheader( 上传图片) uploaded_file st.file_uploader( 选择图片文件, type[jpg, jpeg, png], help支持JPG、PNG格式建议图片尺寸不要过大 ) if uploaded_file: image Image.open(uploaded_file) st.image(image, caption原始图片, use_column_widthTrue) with col2: st.subheader( 检测结果) if uploaded_file: if st.button( 开始检测, typeprimary): # 转换图片 image_np np.array(image.convert(RGB)) with st.spinner(正在检测中...): # 执行检测 results detect_faces_and_landmarks(image_np) # 绘制结果 result_image draw_detections_and_landmarks( image_np, results[detections], results[landmarks], draw_landmarksenable_landmarks ) # 显示结果 st.image(result_image, caption检测结果, use_column_widthTrue) # 显示统计 face_count len(results[detections]) landmark_count 0 if enable_landmarks and results[landmarks].multi_face_landmarks: for face_landmarks in results[landmarks].multi_face_landmarks: landmark_count len(face_landmarks.landmark) st.success(f✅ 检测到 {face_count} 张人脸) if enable_landmarks: st.info(f 定位到 {landmark_count} 个关键点) # 显示详细数据 with st.expander( 查看检测数据): tab1, tab2 st.tabs([人脸检测数据, 关键点数据]) with tab1: detection_data [] for i, det in enumerate(results[detections]): detection_data.append({ face_id: i, bbox: det[box], confidence: float(det[score]) }) st.json(detection_data) with tab2: if enable_landmarks and results[landmarks].multi_face_landmarks: landmarks_data [] for i, face_landmarks in enumerate(results[landmarks].multi_face_landmarks): face_points [] for j, landmark in enumerate(face_landmarks.landmark[:20]): # 只显示前20个点 face_points.append({ point_id: j, x: float(landmark.x), y: float(landmark.y) }) landmarks_data.append({ face_id: i, landmarks: face_points }) st.json(landmarks_data) # 下载按钮 landmarks_json json.dumps(landmarks_data, indent2) st.download_button( label 下载关键点数据, datalandmarks_json, file_nameface_landmarks.json, mimeapplication/json ) else: st.info(请先在左侧上传图片) # 使用说明 st.markdown(---) st.subheader( 使用说明) col_a, col_b, col_c st.columns(3) with col_a: st.markdown( **1. 上传图片** - 点击左侧上传区域 - 选择包含人脸的图片 - 支持JPG、PNG格式 ) with col_b: st.markdown( **2. 开始检测** - 点击蓝色检测按钮 - 等待处理完成 - 查看右侧结果 ) with col_c: st.markdown( **3. 查看结果** - 绿色框人脸位置 - 红色点关键点 - 底部查看详细数据 )7. 实际应用案例7.1 案例一人脸对齐与标准化关键点检测的一个重要应用是人脸对齐。在很多人脸识别系统中需要将人脸对齐到标准位置def align_face(image_np, landmarks): 使用关键点进行人脸对齐 # 获取眼睛位置简化版 left_eye landmarks[33] # 左眼中心 right_eye landmarks[263] # 右眼中心 # 计算眼睛连线角度 dy right_eye.y - left_eye.y dx right_eye.x - left_eye.x angle np.degrees(np.arctan2(dy, dx)) # 旋转图像使人眼水平 h, w image_np.shape[:2] center (w // 2, h // 2) rotation_matrix cv2.getRotationMatrix2D(center, angle, 1.0) aligned_image cv2.warpAffine(image_np, rotation_matrix, (w, h)) return aligned_image7.2 案例二简单表情分析通过关键点的位置变化可以分析基本表情def analyze_expression(landmarks): 简单表情分析基于关键点距离 # 嘴巴开合程度 mouth_top landmarks[13] # 上嘴唇中点 mouth_bottom landmarks[14] # 下嘴唇中点 mouth_open mouth_bottom.y - mouth_top.y # 眉毛位置 left_eyebrow landmarks[159] # 左眉 right_eyebrow landmarks[386] # 右眉 # 简单判断 if mouth_open 0.05: # 阈值需要调整 return 惊讶 elif left_eyebrow.y landmarks[33].y - 0.02: # 眉毛上扬 return 高兴 else: return 中性7.3 案例三虚拟眼镜试戴这是一个有趣的应用可以在人脸上添加虚拟眼镜def add_virtual_glasses(image_np, landmarks, glasses_image): 在检测到的人脸上添加虚拟眼镜 # 获取眼睛位置 left_eye landmarks[33] right_eye landmarks[263] # 计算眼镜位置和大小 eye_distance np.sqrt((right_eye.x - left_eye.x)**2 (right_eye.y - left_eye.y)**2) glasses_width int(eye_distance * 2.5 * image_np.shape[1]) glasses_height int(glasses_width * 0.3) # 调整眼镜图片大小 glasses_resized cv2.resize(glasses_image, (glasses_width, glasses_height)) # 计算放置位置眼睛上方 x int((left_eye.x right_eye.x) / 2 * image_np.shape[1] - glasses_width // 2) y int(min(left_eye.y, right_eye.y) * image_np.shape[0] - glasses_height * 0.5) # 将眼镜叠加到原图简化版实际需要处理透明度 result image_np.copy() if x 0 and y 0 and x glasses_width result.shape[1] and y glasses_height result.shape[0]: result[y:yglasses_height, x:xglasses_width] glasses_resized return result8. 常见问题与解决方案8.1 问题一关键点检测不准确可能原因人脸角度过大侧脸超过45度光照条件太差人脸被严重遮挡解决方案# 添加预处理 def preprocess_image(image_np): 图像预处理提高检测准确率 # 1. 调整亮度对比度 lab cv2.cvtColor(image_np, cv2.COLOR_BGR2LAB) l, a, b cv2.split(lab) clahe cv2.createCLAHE(clipLimit3.0, tileGridSize(8,8)) l clahe.apply(l) lab cv2.merge((l, a, b)) enhanced cv2.cvtColor(lab, cv2.COLOR_LAB2BGR) # 2. 人脸对齐如果可能 # 可以先用人脸检测框裁剪再检测关键点 return enhanced8.2 问题二检测速度慢优化建议降低图片分辨率检测前先缩小图片限制人脸数量设置最大检测人脸数使用GPU加速确保MediaPipe使用GPU如果可用# 优化后的检测函数 def optimized_detect(image_np, max_faces5, target_size640): 优化版检测函数 # 调整图片大小 h, w image_np.shape[:2] scale target_size / max(h, w) if scale 1: new_h, new_w int(h * scale), int(w * scale) small_image cv2.resize(image_np, (new_w, new_h)) else: small_image image_np # 检测使用缩小后的图片 results detect_faces_and_landmarks(small_image) # 将坐标转换回原图尺寸 if scale 1: for det in results[detections]: det[box] [int(x / scale) for x in det[box]] if results[landmarks].multi_face_landmarks: for face_landmarks in results[landmarks].multi_face_landmarks: for landmark in face_landmarks.landmark: landmark.x / scale landmark.y / scale return results8.3 问题三多张脸的关键点混淆解决方案将人脸检测框和关键点进行匹配def match_faces_with_landmarks(detections, landmarks_result, image_shape): 将检测到的人脸框和关键点进行匹配 h, w image_shape[:2] matched_results [] if landmarks_result.multi_face_landmarks: for i, face_landmarks in enumerate(landmarks_result.multi_face_landmarks): # 计算关键点的中心点 xs [lm.x * w for lm in face_landmarks.landmark] ys [lm.y * h for lm in face_landmarks.landmark] center_x sum(xs) / len(xs) center_y sum(ys) / len(ys) # 找到包含这个中心点的人脸框 for det in detections: bbox det[box] if (bbox[0] center_x bbox[2] and bbox[1] center_y bbox[3]): matched_results.append({ detection: det, landmarks: face_landmarks, face_id: i }) break return matched_results9. 总结与进阶建议9.1 功能总结通过本教程我们成功在原有的MogFace人脸检测应用基础上添加了人脸关键点检测功能。现在这个应用可以同时进行人脸检测和关键点定位使用MogFace检测人脸MediaPipe定位关键点灵活的可视化选项可以选择显示全部关键点或只显示轮廓数据导出功能可以将关键点坐标导出为JSON格式实时处理能力能够在普通电脑上快速处理图片9.2 性能优化建议如果你需要处理视频或大量图片可以考虑以下优化批量处理一次性处理多张图片减少模型加载次数异步处理使用多线程或异步IO提高响应速度模型量化将模型转换为更轻量级的格式缓存结果对相同图片的检测结果进行缓存9.3 功能扩展方向这个基础版本还可以进一步扩展3D关键点检测使用支持3D的关键点模型表情识别基于关键点位置分析表情年龄性别估计结合关键点特征进行估计人脸属性分析分析是否戴眼镜、是否微笑等实时视频处理扩展为视频流处理应用9.4 实际应用建议在实际项目中应用时建议根据需求选择模型不同的关键点模型有不同的特点考虑计算资源在准确率和速度之间找到平衡添加错误处理处理检测失败的情况优化用户体验添加加载动画、进度提示等9.5 最后的建议人脸关键点检测是一个非常有用的技术但记住不是越多的点越好根据应用需求选择合适的点数准确率比速度更重要在大多数应用中准确的关键点比快速但不准的点更有价值考虑实际场景不同的光照、角度、遮挡条件需要不同的处理策略现在你已经有了一个完整的人脸检测关键点定位应用可以根据自己的需求进一步定制和扩展。无论是做学术研究、产品开发还是个人项目这个工具都能为你提供强大的支持。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章