M2FP API设计解析:RESTful接口返回结构说明
📖 项目背景与技术定位
在计算机视觉领域,人体解析(Human Parsing)是一项细粒度的语义分割任务,目标是将图像中的人体分解为多个语义明确的身体部位,如头发、面部、左臂、右腿、上衣、裤子等。相较于传统的人体检测或姿态估计,人体解析提供了更精细的空间语义信息,在虚拟试衣、动作分析、智能安防和AR/VR场景中具有广泛的应用价值。
M2FP(Mask2Former-Parsing)作为ModelScope平台上领先的多人人体解析模型,基于改进的Mask2Former架构,专为复杂场景下的多人体像素级解析而设计。其核心优势在于能够同时处理多人重叠、遮挡、远近尺度差异大等现实挑战,并输出高精度的分割掩码(Mask)。本服务在此基础上进一步封装为可部署的WebAPI与可视化WebUI系统,支持无GPU环境稳定运行,极大降低了技术落地门槛。
🔍 M2FP服务架构概览
整个M2FP服务采用前后端分离的轻量级架构,后端基于Flask搭建RESTful API,前端通过HTML+JavaScript实现交互式WebUI。整体流程如下:
- 用户上传原始图像(JPEG/PNG格式)
- 后端接收请求并调用M2FP模型进行推理
- 模型输出每个检测到的人体实例及其对应的身体部位Mask列表
- 内置“拼图算法”对多个Mask进行颜色映射与叠加,生成可视化语义图
- 返回结果包括:
- 原始JSON格式的结构化数据(含各类别Mask坐标)
- 可视化合成图(Base64编码或静态资源路径)
📌 核心设计理念:
“结构化输出 + 可视化增强”双轨并行,既满足开发者对接需求,也兼顾非技术人员的操作体验。
🧩 RESTful API 接口设计规范
✅ 接口地址与请求方式
POST /api/v1/parsing/m2fp Content-Type: multipart/form-data请求参数说明
| 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| |image| File | 是 | 待解析的图片文件(支持JPG/PNG) | |threshold| float | 否 | 置信度阈值(默认0.5,过滤低质量Mask) | |return_vis| bool | 否 | 是否返回可视化图像(默认true) |
📤 标准响应结构设计
无论成功与否,所有响应均遵循统一的RESTful返回格式,确保客户端可预测地解析结果。
{ "code": 200, "message": "success", "data": { "request_id": "req-abc123xyz", "timestamp": 1712345678901, "result_image": "data:image/png;base64,iVBORw0KGgoAAAANSUh...", "parsing_result": [ ... ] } }全局字段解释
| 字段 | 类型 | 说明 | |------|------|------| |code| int | 状态码(200=成功,400=参数错误,500=服务异常) | |message| string | 状态描述信息 | |data| object | 实际返回内容容器(失败时为null) |
🧱 核心返回结构深度解析:parsing_result
这是API最核心的部分——多人人体解析的结果集合。它是一个数组,每一项代表一个被识别出的“人体实例”,包含该人物的所有身体部位分割信息。
单个实例结构定义
{ "person_id": 0, "bbox": [120, 80, 450, 720], "segments": [ { "label": "hair", "category_id": 1, "confidence": 0.96, "mask": { "format": "rle", "size": [1080, 1920], "counts": "kagb0W_1O..." } }, { "label": "upper_clothes", "category_id": 5, "confidence": 0.93, "mask": { ... } } ] }字段详解
| 字段 | 类型 | 说明 | |------|------|------| |person_id| int | 当前人体实例ID(从0开始递增) | |bbox| array[int] | 外接矩形框[x_min, y_min, x_max, y_max],单位像素 | |segments| array[object] | 身体部位分割列表,每项为一个部位 |
segments中的子字段
| 子字段 | 类型 | 说明 | |--------|------|------| |label| string | 部位语义标签(见下文类别表) | |category_id| int | 对应的类别编号(便于程序处理) | |confidence| float | 模型对该Mask的置信度评分(0~1) | |mask| object | 分割掩码数据,采用RLE压缩编码 |
🎨 RLE掩码编码机制说明
为了减少网络传输开销,M2FP API默认使用Run-Length Encoding (RLE)编码方式表示二值Mask。这是一种高效的压缩格式,特别适合稀疏或连通区域的图像掩码。
RLE结构组成
"mask": { "format": "rle", "size": [height, width], "counts": "kagb0W_1O..." }size: 原图尺寸[H, W]counts: Base64编码后的字节串,记录连续前景像素的数量序列
💡 示例理解:
若原Mask中有连续5个像素为1,则RLE会记作5;接着3个为0,则记作3……以此类推。最终通过变长编码压缩存储。
如何还原为Mask?
Python示例代码如下:
import numpy as np from pycocotools import mask as coco_mask def rle_to_mask(rle_dict): """ 将RLE格式转换为HxW的二值Mask """ mask = coco_mask.decode(rle_dict) return mask # shape: (H, W), dtype: bool or uint8 # 使用示例 rle_data = { "size": [1080, 1920], "counts": "kagb0W_1O..." # 实际Base64字符串 } binary_mask = rle_to_mask(rle_data) print(binary_mask.shape) # 输出: (1080, 1920)⚠️ 注意:需安装
pycocotools支持RLE解码:bash pip install pycocotools
🗂️ 身体部位分类体系(Label Map)
M2FP模型共支持20类常见人体部位,覆盖头部、躯干、四肢及衣物。以下是完整标签映射表:
| ID | Label(英文) | 中文含义 | 是否常用于可视化 | |----|---------------|----------|------------------| | 0 | background | 背景 | 黑色填充 | | 1 | hair | 头发 | 红色 | | 2 | face | 面部 | 米白 | | 3 | right_arm | 右上臂 | 浅蓝 | | 4 | left_arm | 左上臂 | 深蓝 | | 5 | right_hand | 右手 | 天蓝 | | 6 | left_hand | 左手 | 湖蓝 | | 7 | torso_skin | 躯干裸露皮肤 | 肤色 | | 8 | upper_clothes | 上衣 | 绿色 | | 9 | skirt | 裙子 | 粉红 | | 10 | pants | 裤子 | 深灰 | | 11 | left_leg | 左大腿 | 棕褐 | | 12 | right_leg | 右大腿 | 橄榄 | | 13 | left_shoe | 左鞋 | 黑棕 | | 14 | right_shoe | 右鞋 | 黑棕 | | 15 | scarf | 围巾 | 橙黄 | | 16 | gloves | 手套 | 浅灰 | | 17 | hat | 帽子 | 紫罗兰 | | 18 | sunglasses | 太阳镜 | 银灰 | | 19 | umbrella | 雨伞 | 亮红 |
📌 提示:颜色方案可在WebUI中自定义配置,但API返回仅提供语义标签,不包含颜色信息。
🖼️ 可视化拼图算法实现原理
虽然API返回的是结构化的Mask数据,但用户往往需要一张直观的“彩色分割图”。为此,系统内置了实时拼图引擎(Puzzle Engine),其工作流程如下:
🔁 拼图处理步骤
- 初始化画布:创建与原图同尺寸的全黑背景(RGB三通道)
- 遍历每个人体实例
- 按Z序叠加:先绘制远处(小bbox)人物,再绘近处,避免遮挡错乱
- 逐部位上色:
- 解码RLE → 获取二值Mask
- 查找预设颜色表(Color Palette)
- 将Mask区域内像素赋值为对应RGB值
- 融合输出:合并所有实例后生成最终可视化图像
Python伪代码示意
import cv2 import numpy as np COLOR_PALETTE = [ (0, 0, 0), # background - black (255, 0, 0), # hair - red (255, 255, 255), # face - white (0, 255, 255), # right_arm - yellow # ... 其他颜色省略 ] def build_visualization(image_shape, parsing_result): H, W = image_shape[:2] vis_image = np.zeros((H, W, 3), dtype=np.uint8) for person in parsing_result: for seg in person["segments"]: label_id = seg["category_id"] if label_id == 0: # skip background continue color = COLOR_PALETTE[label_id % len(COLOR_PALETTE)] rle = seg["mask"] mask = coco_mask.decode(rle).astype(bool) vis_image[mask] = color # 填充颜色 return vis_image # 调用示例 vis_img = build_visualization(original_image.shape, json_response['data']['parsing_result']) cv2.imwrite("output_vis.png", vis_img)✅ 优势:无需额外模型参与,纯CPU运算即可完成,兼容性强。
🛠️ 异常处理与状态码设计
为提升API健壮性,系统对各类异常情况进行了精细化分类响应。
| HTTP状态码 | code值 | message示例 | 触发条件 | |-----------|--------|-------------|---------| | 200 | 200 | success | 成功解析 | | 400 | 40001 | missing required field 'image' | 缺少图片上传 | | 400 | 40002 | unsupported image format | 图像格式非JPG/PNG | | 413 | 40003 | image too large (>10MB) | 文件过大 | | 500 | 50001 | model inference failed | 推理过程崩溃 | | 500 | 50002 | visualization generation error | 拼图失败 |
客户端可根据code字段做针对性容错处理。
🧪 实际调用示例(Python)
以下是一个完整的Python脚本,演示如何调用M2FP API并解析返回结果:
import requests import json import base64 from PIL import Image import io url = "http://localhost:5000/api/v1/parsing/m2fp" # 准备图片文件 with open("test.jpg", "rb") as f: files = {"image": f} data = {"return_vis": True} # 发起请求 response = requests.post(url, files=files, data=data) if response.status_code == 200: result = response.json() print(f"请求成功!共检测到 {len(result['data']['parsing_result'])} 个人体实例") # 提取可视化图像并保存 img_data = result['data']['result_image'].split(",")[1] img_bytes = base64.b64decode(img_data) output_img = Image.open(io.BytesIO(img_bytes)) output_img.save("m2fp_result.png") print("可视化结果已保存至 m2fp_result.png") # 遍历每个人体实例 for person in result['data']['parsing_result']: print(f"\n👤 Person ID: {person['person_id']}, BBox: {person['bbox']}") for seg in person['segments']: print(f" 🧩 {seg['label']} (ID:{seg['category_id']}): " f"conf={seg['confidence']:.2f}") else: error = response.json() print(f"❌ 请求失败: [{error['code']}] {error['message']}")📊 性能表现与优化建议
⏱️ 推理耗时统计(CPU环境)
| 图像分辨率 | 平均延迟(单人) | 多人(3人以上) | |------------|------------------|-----------------| | 640×480 | ~1.8s | ~3.2s | | 1080×720 | ~3.5s | ~6.0s | | 1920×1080 | ~7.2s | ~12.5s |
💡 优化建议: - 对实时性要求高的场景,建议预缩放图像至1080p以内 - 开启
threshold=0.6可减少无效Mask数量,加快后处理速度 - 批量请求应使用队列机制避免阻塞
✅ 总结:M2FP API的设计哲学
M2FP API的设计体现了三大核心原则:
1. 结构清晰:采用标准RESTful风格,返回结构层次分明,易于自动化解析。
2. 开发友好:提供RLE压缩与可视化双输出模式,兼顾效率与易用性。
3. 工程稳健:锁定关键依赖版本,解决PyTorch与MMCV兼容问题,保障长期可用性。
无论是集成到智能服装推荐系统,还是用于行为分析平台,M2FP都提供了一套开箱即用、可扩展、易维护的人体解析解决方案。未来还将支持gRPC协议、ONNX导出与边缘设备部署,持续降低AI应用门槛。
🚀 下一步建议:
若你正在构建基于人体语义的视觉应用,建议优先测试M2FP在遮挡场景下的鲁棒性,并结合业务逻辑定制后处理规则(如只保留上半身Mask),以最大化利用其高精度分割能力。