最近在小程序生态里,有一款叫“形象分析助手”的工具引发了不少关注。用户上传一张照片,系统就能输出颜值评分、脸型诊断、肤色分析、发型建议,甚至生成一段幽默犀利的“颜值锐评”。作为技术人,第一反应当然是——这东西怎么做的?

经过一段时间的调研和实验,我把核心链路基本摸清了。本文将以开源技术栈为基座,完整拆解一套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 肤色提取

肤色分析的难点在于——如何排除光照干扰。项目采用以下流程:

  1. 人脸检测 → 确定面部区域

  2. 皮肤分割 → 使用BiSeNet分割模型,剔除眉眼唇

  3. 区块采样 → 选取额头、双颊共5个感兴趣区域

  4. 光照归一化 → 使用Gray-World白平衡算法校正

  5. 色彩空间转换 → 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形象分析系统的技术架构与核心实现。核心要点回顾:

  1. 人脸关键点检测是基石,推荐MediaPipe + InsightFace双阶段方案

  2. 颜值评分需结合美学数据集训练专用模型,并拆解子维度增强可解释性

  3. 脸型分类五官测试依赖几何特征工程,XGBoost轻量且高效

  4. 色彩测试基于LAB空间分析,映射到四季十二型体系指导穿搭

  5. 发型推荐本质是脸型+特征的规则引擎,不是AI玄学

  6. 颜值锐评可用模板引擎或开源LLM实现,关键是数据驱动而非套话

  7. 整体架构需考虑并发控制、模型量化、端云协同等工程问题

如果你对“形象测试”、“穿搭介绍”、“颜值打分”这些功能的底层实现有更深的兴趣,欢迎来AtomGit一起研究代码。开源的意义,就是让这些原本藏在商业产品里的技术能力,变成每个开发者都能理解、使用和改进的公共知识。

变美是个人的事,但让变美的技术普惠大众,是我们开发者的事。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐