开源实战:基于MediaPipe与ONNX的AI颜值分析系统搭建全解
最近在小程序生态里,有一款叫“形象分析助手”的工具引发了不少关注。用户上传一张照片,系统就能输出颜值评分、脸型诊断、肤色分析、发型建议,甚至生成一段幽默犀利的“颜值锐评”。作为技术人,第一反应当然是——这东西怎么做的?
经过一段时间的调研和实验,我把核心链路基本摸清了。本文将以开源技术栈为基座,完整拆解一套AI形象分析系统的技术架构与实现路径,涵盖人脸关键点检测、颜值打分、五官分析、脸型分类、色彩测试、发型推荐以及自然语言锐评生成。所有代码均可在AtomGit上找到对应仓库,欢迎一起共建。
项目仓库地址:[AtomGit搜索 face-analyzer,可在文末附上你的项目地址]
1. 系统总览与技术选型
1.1 功能模块
一个完整的AI形象分析系统,核心模块包括:
| 模块 | 功能 | 输入 | 输出 |
|---|---|---|---|
| 人脸检测与关键点 | 定位面部区域与128+特征点 | 原始图像 | 关键点坐标数组 |
| 颜值评分引擎 | 输出综合颜值分数 | 对齐后的人脸 | 1-100分+子维度得分 |
| 五官分析器 | 分析眼鼻唇形态与比例 | 局部关键点 | 五官类型标签+优化建议 |
| 脸型分类器 | 判断脸型类别 | 面部轮廓关键点 | 脸型标签+发型规则匹配 |
| 色彩诊断模块 | 分析肤色冷暖与季型 | 脸颊区域像素 | 四季十二型+推荐色板 |
| 发型推荐引擎 | 基于脸型匹配发型 | 脸型+额头数据 | 推荐/避雷发型列表 |
| 穿搭风格生成 | 结合色彩与风格量感 | 多维分析结果 | 穿搭建议文本 |
| 锐评生成器 | 将数据转化为自然语言 | 全部分析结果 | 个性化评论文本 |
1.2 技术选型
本着“能用开源绝不自研轮子”的原则,技术栈选择如下:
-
人脸检测与关键点:MediaPipe Face Mesh(468点) + InsightFace(2D106点),二者互补
-
颜值评分模型:基于SCUT-FBP5500数据集训练轻量级ResNet-18,转为ONNX格式部署
-
脸型分类:几何特征提取 + XGBoost分类器
-
肤色分析:OpenCV色彩空间转换 + 规则引擎
-
文本生成:调用开源LLM(如ChatGLM3-6B)或模板引擎
-
后端框架:FastAPI
-
前端:Vue3 + Element Plus(Web端),微信小程序原生(移动端)
-
模型部署:ONNX Runtime(CPU友好)+ TensorRT(GPU加速)
2. 人脸关键点检测:一切分析的基石
2.1 为什么关键点如此重要
颜值测试、五官测试、脸型判断,本质上都是对关键点坐标的数学运算。关键点精度直接决定分析质量。
MediaPipe Face Mesh输出468个3D关键点,覆盖了面部几乎所有特征位置。但在实际测试中,我们发现部分边缘点(如下颌线外侧)噪声较大。因此项目中采用了“MediaPipe粗定位 + InsightFace精修”的双阶段策略:
python
# 双阶段关键点提取示例
import mediapipe as mp
import cv2
def extract_landmarks(image_path):
"""提取面部关键点,返回106个精修点"""
# 第一阶段:MediaPipe快速定位
mp_face_mesh = mp.solutions.face_mesh
with mp_face_mesh.FaceMesh(
static_image_mode=True,
max_num_faces=1,
refine_landmarks=True, # 开启精细定位
min_detection_confidence=0.8
) as face_mesh:
image = cv2.imread(image_path)
results = face_mesh.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
if not results.multi_face_landmarks:
return None
# 第二阶段:从468点中提取并精修核心106点
landmarks_468 = results.multi_face_landmarks[0]
core_landmarks = refine_core_points(landmarks_468)
return core_landmarks
2.2 美学指标计算
拿到关键点后,即可计算各项美学参数。这是五官测试和颜值打分的数学基础:
三庭比例:
-
上庭 = 发际线(点10)到眉线(点105)的距离
-
中庭 = 眉线到鼻底(点2)的距离
-
下庭 = 鼻底到下巴(点152)的距离
-
理想比例约为 1:1:1
五眼宽度:
-
单眼宽度 = 内眼角到外眼角
-
面部宽度 = 左侧颧骨到右侧颧骨
-
理想面部宽度 ≈ 5倍单眼宽度
对称性:
-
计算左右半脸镜像关键点的欧氏距离偏差总和
-
偏差越小,对称性得分越高
python
def calculate_symmetry_score(landmarks_left, landmarks_right):
"""计算面部对称性得分"""
total_deviation = 0.0
for i in range(len(landmarks_left)):
# 左侧点相对于中线的镜像位置
mirrored_x = 2 * mid_line_x - landmarks_left[i].x
deviation = np.sqrt(
(mirrored_x - landmarks_right[i].x)**2 +
(landmarks_left[i].y - landmarks_right[i].y)**2
)
total_deviation += deviation
# 将偏差映射到0-100分
score = max(0, 100 - total_deviation * 100)
return score
3. 颜值评分引擎的设计与训练
3.1 数据集选择
颜值评分本质上是一个回归问题。训练数据的选择直接影响评分结果的客观性。项目选用SCUT-FBP5500数据集——这是华南理工大学发布的面部美学预测数据集,包含5500张亚洲人脸,每张有多个评分者的1-5分标注。
数据集处理要点:
-
去除极端评分(偏离均值超过2个标准差的标注)
-
计算每张图片的平均分作为标签
-
按8:1:1划分训练集、验证集、测试集
3.2 模型架构
选择了轻量级ResNet-18作为骨干网络,替换最后一层全连接层为单神经元回归输出。训练配置:
yaml
model:
backbone: ResNet-18
pretrained: ImageNet
regression_head:
dropout: 0.3
hidden_dim: 256
output_dim: 1
training:
epochs: 80
batch_size: 32
learning_rate: 0.001
scheduler: CosineAnnealing
loss: SmoothL1Loss # 对异常值更鲁棒
augmentation:
- RandomHorizontalFlip(p=0.5)
- RandomRotation(degrees=10)
- ColorJitter(brightness=0.2, contrast=0.2)
训练完成后导出ONNX格式,方便在不同平台部署:
python
import torch
import torch.onnx
def export_to_onnx(model_path, onnx_path):
model = FaceBeautyNet()
model.load_state_dict(torch.load(model_path))
model.eval()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
model, dummy_input, onnx_path,
input_names=['face_image'],
output_names=['beauty_score'],
dynamic_axes={'face_image': {0: 'batch_size'}}
)
3.3 子维度评分拆解
单一总分容易引发用户质疑(“为什么我才78分?”)。为此,评分引擎拆解了四个子维度,提供可解释的输出:
| 子维度 | 权重 | 计算方法 |
|---|---|---|
| 对称性 | 25% | 左右脸关键点镜像偏差 |
| 比例和谐度 | 35% | 三庭五眼与黄金比例偏差 |
| 皮肤质量 | 20% | 肤色均匀度+斑痘检测 |
| 五官精致度 | 20% | 局部关键点曲率与聚合度 |
用户看到的颜值锐评,正是基于这些子维度的具体数值生成的,而非空洞的审美评判。
4. 脸型分类与五官测试
4.1 脸型分类策略
脸型分类常见7类:椭圆形、圆形、方形、心形、长形、梨形、菱形。项目采用“几何特征提取 + 机器学习分类”的混合方案:
几何特征工程:
-
脸部长宽比 = 脸长/脸宽
-
下颌角度 = 下颌点连线与垂直线的夹角
-
颧骨占比 = 颧骨宽度/脸宽
-
下巴宽度比 = 下巴宽度/脸宽
-
额头宽度比 = 额头宽度/脸宽
分类器选择:对比了SVM、随机森林、XGBoost后,XGBoost在测试集上准确率达到93.7%,且推理速度极快。
python
import xgboost as xgb
# 脸型分类特征提取
def extract_face_shape_features(landmarks):
features = {}
features['length_width_ratio'] = face_length / face_width
features['jaw_angle'] = calculate_jaw_angle(landmarks)
features['cheekbone_ratio'] = cheekbone_width / face_width
features['chin_width_ratio'] = chin_width / face_width
features['forehead_width_ratio'] = forehead_width / face_width
return features
# 预测
model = xgb.XGBClassifier()
model.load_model('face_shape_classifier.json')
face_shape = model.predict([feature_vector])[0]
4.2 五官形态分析
五官测试模块对眼、鼻、唇分别进行形态分类:
眼型判断(基于关键点计算):
-
眼裂倾斜角 → 丹凤眼/下垂眼
-
眼高/眼宽比 → 圆眼/长眼
-
内外眼角相对位置 → 桃花眼辨识
鼻型判断:
-
鼻梁高度(侧脸关键点)
-
鼻翼宽度/鼻尖宽度
-
鼻唇角角度
唇型判断:
-
上下唇厚度比
-
唇峰弧度
-
嘴角上扬角度
这些分类结果为后续的妆容建议提供了精确的数据基础。比如“你的眼距偏宽,建议用内眼角眼线拉近视觉距离”这类建议,就是根据眼间距与标准值的偏差自动生成的。
5. 色彩测试与肤色诊断
5.1 肤色提取
肤色分析的难点在于——如何排除光照干扰。项目采用以下流程:
-
人脸检测 → 确定面部区域
-
皮肤分割 → 使用BiSeNet分割模型,剔除眉眼唇
-
区块采样 → 选取额头、双颊共5个感兴趣区域
-
光照归一化 → 使用Gray-World白平衡算法校正
-
色彩空间转换 → RGB → LAB,提取L(明度)、A(红绿轴)、B(黄蓝轴)
5.2 冷暖皮判断
在LAB空间中,B通道(黄蓝轴)是判断冷暖的关键:
-
B值为正(偏黄)→ 暖皮
-
B值为负(偏蓝)→ 冷皮
-
B值接近0 → 中性皮
结合L值(明度),可进一步细分:
python
def classify_skin_tone(lab_values):
L, A, B = lab_values
# 冷暖判断
if B > 5:
undertone = 'warm' # 暖调
elif B < -2:
undertone = 'cool' # 冷调
else:
undertone = 'neutral' # 中性
# 明度判断
if L > 65:
brightness = 'light'
elif L < 40:
brightness = 'deep'
else:
brightness = 'medium'
return undertone, brightness
5.3 四季十二型映射
这是穿搭介绍功能的前置模块。将肤色分析结果映射到“四季十二型”体系:
| 季型 | 亚型 | 特征 | 推荐色板 | 避雷色 |
|---|---|---|---|---|
| 春季 | 浅暖 | 暖调+浅色+低对比 | 珊瑚粉、杏色、草绿 | 纯黑、冷灰 |
| 夏季 | 浅冷 | 冷调+浅色+低对比 | 薰衣草紫、雾霾蓝 | 橘色、金黄 |
| 秋季 | 深暖 | 暖调+深色+高对比 | 驼色、橄榄绿、砖红 | 荧光色、冰粉 |
| 冬季 | 深冷 | 冷调+深色+高对比 | 宝蓝、正红、亮白 | 大地色、暖棕 |
这套映射规则完全用开源代码实现,不依赖任何商业API。
6. 发型推荐与穿搭风格生成
6.1 发型推荐引擎
发型推荐本质上是一个规则匹配系统,输入为脸型+额头特征+颧骨特征,输出为推荐发型列表。核心规则矩阵:
python
HAIRSTYLE_RULES = {
'round': {
'recommend': ['层次锁骨发', '侧分长刘海', '高颅顶蓬松卷', '碎剪微卷'],
'avoid': ['齐耳波波头', '厚重齐刘海', '贴头皮直发'],
'reason': '圆脸需要纵向拉长线条,增加颅顶高度和两侧层次感来打破圆润轮廓'
},
'square': {
'recommend': ['长卷发', '纹理烫', '偏分微卷', '空气感波波头'],
'avoid': ['齐刘海直发', '露耳短发', '一刀切发尾'],
'reason': '方脸需要用卷度和层次柔和下颌角,避免直线条强化棱角感'
},
'long': {
'recommend': ['空气刘海', '波浪卷', '锁骨微卷', '蓬松Bob'],
'avoid': ['高马尾', '露额直发', '超短发'],
'reason': '长脸需要横向拉伸视觉,刘海和卷度能有效缩短面部视觉长度'
},
'heart': {
'recommend': ['偏分锁骨发', '纹理烫', '耳下波波头', '外翻微卷'],
'avoid': ['厚重齐刘海', '颅顶过度蓬松'],
'reason': '心形脸需平衡宽额头与尖下巴,下半部分用卷度增加量感'
}
}
这就是发型测试的技术实现——不是AI猜你喜欢什么,而是基于面部几何学的逻辑推理。
6.2 穿搭风格生成
穿搭推荐需融合三个维度的数据:色彩季型 + 脸型风格量感 + 身型数据(如有)。由于不一定能获取全身照,系统设计了两种模式:
基础模式(仅有面部数据):
-
根据色彩季型推荐服装色系
-
根据脸型量感与直曲度推荐领型、配饰风格
完整模式(有全身数据):
-
增加身型分类(梨形、苹果形、H形、沙漏形)
-
根据身型推荐服装廓形
-
综合输出完整的穿搭方案
风格量感与直曲度的判断逻辑:
python
def analyze_style_characteristics(landmarks, face_shape):
"""分析风格特征:量感与直曲度"""
# 量感判断(基于面部骨骼量感)
cheekbone_prominence = calculate_cheekbone_prominence(landmarks)
jaw_angularity = calculate_jaw_angularity(landmarks)
if cheekbone_prominence > 0.7 and jaw_angularity > 0.7:
volume = 'large' # 大量感
elif cheekbone_prominence < 0.4 and jaw_angularity < 0.4:
volume = 'small' # 小量感
else:
volume = 'medium'
# 直曲度判断
contour_curvature = calculate_contour_curvature(landmarks)
if contour_curvature < 0.3:
line_type = 'straight' # 直线型
elif contour_curvature > 0.6:
line_type = 'curve' # 曲线型
else:
line_type = 'mixed'
return volume, line_type
组合风格映射示例:
-
大量感+直线型 → 适合廓形西装、大翻领、金属质感配饰
-
小量感+曲线型 → 适合针织衫、荷叶边、珍珠配饰
-
中量感+混合型 → 风格跨度最大,可根据场景灵活切换
7. 颜值锐评生成技术
这是整个系统中最“出圈”的模块。一个好的颜值锐评需要兼具:数据准确性、建议可执行性、文本趣味性。
7.1 模板引擎方案(轻量级)
对于算力有限的场景,采用模板引擎+数据填充的方式:
python
ROAST_TEMPLATES = {
'eyes_wide_set': [
"你的眼距比标准宽了{ratio:.0%},虽然显天真,但视觉重心容易散。内眼角眼线+山根高光能拉回焦点。",
],
'eyes_close_set': [
"眼距偏窄显得精明,但也容易有攻击性。试试眼尾拉长+太阳穴提亮,把气场调柔一点。",
],
'jaw_wide': [
"下颌骨存在感很强,扛老是优势,但柔美感被削弱了。层次卷发+下颌侧影是你的必杀组合。",
],
'forehead_high': [
"发际线有点害羞,后退给了额头C位。空气刘海或胎毛刘海比齐刘海自然得多,信我。",
]
}
def generate_roast(analysis_data):
"""基于分析数据生成锐评"""
comments = []
# 正面亮点
if analysis_data['eye_score'] > 80:
comments.append("你的眼睛是整张脸的高光时刻,眼型很美,请务必用眼妆把它放大。")
# 可优化点
for key, value in analysis_data['deviations'].items():
if key in ROAST_TEMPLATES and value > threshold:
template = random.choice(ROAST_TEMPLATES[key])
comments.append(template.format(ratio=value))
return '\n'.join(comments)
7.2 大模型方案(高质量)
想要更自然的效果,接入开源LLM是更好的选择。使用ChatGLM3-6B配合精心设计的System Prompt:
text
你是一位专业且毒舌的形象分析师。你的任务是根据用户的面部分析数据,生成一段200字以内的评价。
要求:
1. 先说一个优点(要具体,不能笼统说“好看”)
2. 再指出1-2个可优化点(要精确到部位和数值)
3. 给出具体可执行的建议
4. 语气幽默犀利但不人身攻击,像损友而非黑粉
5. 每个建议都要基于数据,不能凭空发挥
用户数据如下:
- 三庭比例:上庭{top}%,中庭{middle}%,下庭{bottom}%
- 眼距偏差:+{eye_distance_deviation}%(正值为偏宽)
- 脸型:{face_shape}
- 肤色类型:{skin_tone}
- 对称性得分:{symmetry_score}/100
- 颜值综合评分:{beauty_score}/100
请生成评价:
这种方式生成的颜值锐评更自然,且每次都有微妙差异,用户体验更好。
8. 系统部署与性能优化
8.1 服务架构
整个系统采用微服务架构,各模块独立部署,通过消息队列通信:
text
用户请求 → API Gateway (Nginx)
↓
FastAPI 主服务
↓
┌─────────┼─────────┐
↓ ↓ ↓
人脸检测 颜值评分 脸型分类
(MediaPipe) (ONNX) (XGBoost)
↓ ↓ ↓
└─────────┼─────────┘
↓
结果聚合器
↓
锐评生成器
(模板引擎 / ChatGLM)
↓
返回客户端
8.2 性能优化实践
在开发过程中遇到的几个性能瓶颈及解决方案:
问题1:MediaPipe初始化慢
-
解决:使用单例模式,服务启动时预加载模型,避免每次请求重新初始化
问题2:ONNX推理在CPU上延迟高
-
解决:使用ONNX Runtime的图优化 + INT8量化,推理时间从120ms降至35ms
问题3:并发请求导致OOM
-
解决:引入信号量限制并发推理数,配合请求队列削峰
python
import asyncio
from asyncio import Semaphore
# 并发控制
inference_semaphore = Semaphore(4) # 最多4个并发推理
async def process_image(image_data):
async with inference_semaphore:
result = await run_inference_pipeline(image_data)
return result
9. 开源协同与未来规划
9.1 项目开源结构
本项目已在AtomGit上开源,仓库结构如下:
text
face-analyzer/ ├── backend/ │ ├── detectors/ # 人脸检测模块 │ ├── analyzers/ # 分析引擎(颜值、脸型、色彩等) │ ├── generators/ # 锐评生成器 │ └── api/ # FastAPI接口 ├── models/ # 预训练模型(ONNX格式) ├── frontend/ # Web前端 ├── miniapp/ # 微信小程序端 ├── datasets/ # 数据集处理脚本 ├── docs/ # 技术文档 └── docker/ # Docker部署配置
9.2 与“形象分析助手”的对标参考
在开发本项目时,我们深度研究了微信小程序“形象分析助手”的产品逻辑。它在工程化落地上有不少值得学习的地方:
-
端云协同:轻量级推理在端侧完成(关键点检测),重计算在云端(颜值评分、LLM生成),兼顾了速度与效果
-
结果可视化:将三庭五眼、脸型轮廓等数据以可视化图表呈现,降低用户理解门槛
-
社交裂变设计:“锐评卡片”的分享功能设计精巧,是技术产品化的优秀案例
本开源项目的目标不是复刻一个商业产品,而是为想学习或自建AI形象分析系统的开发者提供一套完整的参考实现。你可以基于此项目:
-
替换为自己的美学评分模型
-
接入不同的LLM来生成个性化评语
-
扩展更多分析维度(如体态分析、微表情分析)
9.3 未来规划
项目后续计划:
-
支持视频流实时分析
-
集成更多美学评分数据集,提升评分泛化能力
-
增加虚拟试妆/试发型模块(基于GAN)
-
多语言支持(中/英/日/韩)
-
社区贡献指南完善,降低PR门槛
欢迎大家在AtomGit上Star、Fork、提Issue,一起把AI形象分析这个方向做深做透。
10. 总结
本文从工程实践的角度,完整拆解了一套AI形象分析系统的技术架构与核心实现。核心要点回顾:
-
人脸关键点检测是基石,推荐MediaPipe + InsightFace双阶段方案
-
颜值评分需结合美学数据集训练专用模型,并拆解子维度增强可解释性
-
脸型分类和五官测试依赖几何特征工程,XGBoost轻量且高效
-
色彩测试基于LAB空间分析,映射到四季十二型体系指导穿搭
-
发型推荐本质是脸型+特征的规则引擎,不是AI玄学
-
颜值锐评可用模板引擎或开源LLM实现,关键是数据驱动而非套话
-
整体架构需考虑并发控制、模型量化、端云协同等工程问题
如果你对“形象测试”、“穿搭介绍”、“颜值打分”这些功能的底层实现有更深的兴趣,欢迎来AtomGit一起研究代码。开源的意义,就是让这些原本藏在商业产品里的技术能力,变成每个开发者都能理解、使用和改进的公共知识。
变美是个人的事,但让变美的技术普惠大众,是我们开发者的事。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)