手把手教你用M2FP:健身应用人体解析实战教程

📅 发布时间:2026/7/3 23:11:53 👁️ 浏览次数:
手把手教你用M2FP:健身应用人体解析实战教程
手把手教你用M2FP健身应用人体解析实战教程你是否正在开发一款健身应用希望它能像专业教练一样“看懂”用户的动作比如当用户在做深蹲时应用能自动判断膝盖是否超过脚尖、背部是否挺直或者在做瑜伽时能分析身体的伸展角度是否到位。要实现这些智能功能一个核心的技术基础就是“人体解析”——它能精确识别图像中人的每一个身体部位。听起来很酷但实现起来会不会很复杂模型怎么选环境怎么搭代码怎么写别担心这篇文章就是为你准备的“一站式”解决方案。我将带你从零开始使用一个开箱即用的M2FP人体解析服务镜像手把手教你如何快速部署、调用API并最终将其集成到一个模拟的健身应用场景中。整个过程不需要你从零训练模型也不需要处理繁琐的环境依赖跟着步骤走1小时内就能看到实际效果。1. 环境准备与快速部署5分钟启动服务我们的第一步是让服务跑起来。得益于CSDN星图平台提供的预置镜像这个过程变得异常简单。1.1 选择并启动M2FP镜像首先你需要登录CSDN星图平台。在平台的镜像广场中搜索“M2FP 多人人体解析服务”。你会看到一个名为“M2FP 多人人体解析服务 (WebUI API)”的镜像其描述明确指出它基于M2FP模型专为多人场景优化且环境稳定支持CPU运行。点击“部署”按钮后平台会让你选择资源配置。对于学习和功能验证阶段选择最低配置例如1核CPU、2GB内存即可这足以运行这个针对CPU优化的镜像。确认后平台会在后台自动创建并启动一个容器实例。1.2 访问WebUI进行功能验证实例启动成功后控制台会提供一个访问地址通常是一个URL链接。点击它浏览器会打开一个简洁的Web界面。这个界面就是内置的可视化工具。你会看到一个上传按钮用于选择本地图片。一个展示区域用于显示原图和解析结果。现在找一张包含人物的图片单人、多人、健身场景、日常照片都可以点击上传。等待几秒钟右侧就会显示出解析结果。不同颜色的色块代表了不同的身体部位例如头发、上衣、裤子、皮肤等黑色区域则代表背景。这个直观的演示能让你立刻理解M2FP在做什么。1.3 理解服务架构与API在动手写代码前我们先简单了解一下这个镜像提供的服务方式。它主要包含两部分WebUI就是我们刚才用的可视化界面适合手动测试和效果预览。RESTful API这是我们将要集成的核心。它是一个HTTP接口我们的应用程序可以通过发送网络请求携带图片来获取结构化的解析结果。服务启动后API的地址通常是http://你的实例IP:端口号/parse。接下来我们就学习如何调用它。2. 核心API调用从图片到结构化数据WebUI展示了效果而API才是赋能我们应用的关键。我们来学习如何用代码与这个服务对话。2.1 发起你的第一个解析请求调用API非常简单本质上就是向一个特定的网址发送一张图片。这里以Python的requests库为例import requests # 1. 设置API地址请替换为你的实际服务地址 api_url http://127.0.0.1:8080/parse # 如果是本地部署可能是这个地址 # 2. 准备要解析的图片 image_path ./test_workout.jpg # 你的图片路径 # 3. 构建请求 with open(image_path, rb) as f: files {image: f} # 可以添加一些可选参数比如置信度阈值 data {confidence_threshold: 0.5} # 4. 发送POST请求 response requests.post(api_url, filesfiles, datadata) # 5. 检查响应 if response.status_code 200: result response.json() print(解析成功) # 接下来处理 result else: print(f请求失败状态码{response.status_code}) print(response.text)将上面的api_url替换成你的实例地址并确保test_workout.jpg图片存在运行这段代码。如果一切正常你会收到一个JSON格式的响应。2.2 解读API返回结果API返回的数据结构清晰包含了丰富的解析信息。一个典型的成功响应如下{ success: true, message: Parsing completed, data: { persons: [ { id: 1, bbox: [120, 80, 250, 360], // 人体边界框 [x, y, width, height] parts: [ { label: head, score: 0.98, mask: iVBORw0KGgoAAAANSUhEUgAA... // Base64编码的掩码图像 }, { label: upper_clothes, score: 0.95, mask: ... }, // ... 更多身体部位 ] }, // ... 可能有多个人物 ], overlay_image: iVBORw0KGgoAAAANSUhEUgAA... // 合成后的可视化结果图Base64 } }我们来拆解一下关键字段persons: 一个列表包含了图片中检测到的每一个人。这对于健身房的多人场景非常有用。id: 每个人的唯一标识。bbox: 人体检测框格式为[左上角x坐标, 左上角y坐标, 宽度, 高度]。parts: 这个人所有被解析的身体部位列表。每个部位包含label: 部位名称如head头、upper_clothes上衣、lower_clothes下装、arms手臂、legs腿等。score: 模型对该部位预测的置信度越高越好。mask: 该部位的二值掩码Binary Mask经过Base64编码。白色像素255代表该部位黑色像素0代表其他区域。这是最核心的数据用于精确的像素级分析。overlay_image: 将各个部位的掩码用不同颜色叠加在原图上的可视化结果同样是Base64编码。可以直接解码显示用于用户界面反馈。2.3 处理掩码数据从Base64到可用矩阵mask字段是Base64编码的PNG图像字符串。要在程序中使用它比如计算某个部位的面积我们需要将其解码并转换为数值矩阵。以下是示例代码import base64 import numpy as np from PIL import Image from io import BytesIO def decode_mask(mask_b64): 将Base64编码的掩码字符串解码为numpy数组。 返回的数组中255代表该部位0代表背景。 # 1. 解码Base64字符串为字节 mask_data base64.b64decode(mask_b64) # 2. 用PIL打开图像 mask_image Image.open(BytesIO(mask_data)) # 3. 转换为灰度numpy数组 mask_array np.array(mask_image) # 通常掩码是二值的0和255我们将其归一化为0和1方便计算 binary_mask (mask_array 128).astype(np.uint8) return binary_mask # 假设我们从API结果中拿到了头部的掩码 head_mask_b64 result[data][persons][0][parts][0][mask] head_binary_mask decode_mask(head_mask_b64) # 现在可以计算头部区域的像素面积即像素点数 head_area np.sum(head_binary_mask) print(f检测到的头部区域面积像素: {head_area}) # 你也可以获取这个掩码的轮廓、中心点等 from skimage import measure contours measure.find_contours(head_binary_mask, 0.5) print(f找到 {len(contours)} 个轮廓)掌握了如何调用API和解析数据我们就拥有了“看懂”人体结构的能力。接下来我们把它用到一个具体的健身场景中。3. 实战应用构建一个深蹲姿势分析器现在我们利用M2FP解析出的数据来实现一个简单的深蹲姿势评估功能。我们将关注两个关键点膝盖是否超过脚尖和背部是否挺直。3.1 步骤一获取关键部位掩码首先我们需要从解析结果中提取出腿部、脚部和躯干的掩码。def extract_body_parts(parsed_result, person_index0): 从解析结果中提取特定人物的关键部位掩码。 person parsed_result[data][persons][person_index] parts_dict {p[label]: decode_mask(p[mask]) for p in person[parts]} # 我们可能需要以下部位标签名称可能因模型而异这里是示例 # ‘legs’可能代表整个腿部我们需要更精细的。这里假设有‘upper_leg’和‘lower_leg’ required_parts [head, torso, upper_leg, lower_leg, foot] extracted {} for part in required_parts: extracted[part] parts_dict.get(part) # 如果不存在则为None return extracted # 使用之前API调用得到的 result body_parts extract_body_parts(result)3.2 步骤二计算关键点与角度由于M2FP返回的是像素级掩码而非直接的关键点我们需要从掩码中估算出关节位置。一个简单的方法是计算某个部位掩码的“底部中心点”或“质心”。def calculate_centroid(mask): 计算二值掩码的质心中心点坐标。 if mask is None: return None # np.where 返回满足条件mask1的像素坐标 y_coords, x_coords np.where(mask 1) if len(x_coords) 0 or len(y_coords) 0: return None center_x np.mean(x_coords).astype(int) center_y np.mean(y_coords).astype(int) return (center_x, center_y) def calculate_bottom_center(mask): 计算二值掩码底部中心点的坐标。 if mask is None: return None # 找到所有为1的像素点 y_coords, x_coords np.where(mask 1) if len(y_coords) 0: return None # 取y坐标最大的那些点最底部然后求它们x坐标的平均值 bottom_y np.max(y_coords) bottom_x_indices np.where(y_coords bottom_y)[0] bottom_x np.mean(x_coords[bottom_x_indices]).astype(int) return (bottom_x, bottom_y) # 估算关键点 hip_center calculate_centroid(body_parts.get(torso)) # 用躯干质心近似髋部 knee_center calculate_centroid(body_parts.get(upper_leg)) # 用大腿质心近似膝盖 ankle_center calculate_bottom_center(body_parts.get(lower_leg)) # 用小腿底部近似脚踝 toe_center calculate_bottom_center(body_parts.get(foot)) # 用脚部底部近似脚尖 print(f估算点位 - 髋: {hip_center}, 膝: {knee_center}, 踝: {ankle_center}, 脚尖: {toe_center})3.3 步骤三实现姿势评估逻辑有了估算的关键点我们就可以进行简单的几何判断。def analyze_squat_pose(keypoints): 基于估算的关键点分析深蹲姿势。 keypoints: 字典包含 ‘hip‘, ‘knee‘, ‘ankle‘, ‘toe‘ 的坐标。 feedback [] score 100 # 起始满分 hip keypoints.get(hip) knee keypoints.get(knee) ankle keypoints.get(ankle) toe keypoints.get(toe) if not all([hip, knee, ankle, toe]): return {score: 0, feedback: [无法检测到所有关键部位请确保全身在画面中。]} # 1. 判断膝盖是否超过脚尖 (粗略的X轴位置比较) # 注意图像坐标系中Y轴向下X轴向右。 if knee and toe and knee[0] toe[0]: # 膝盖的X坐标 脚尖的X坐标 feedback.append(⚠️ 膝盖可能超过脚尖请尝试将重心后移臀部向后坐。) score - 30 # 2. 判断背部是否挺直 (通过髋-膝-踝的连线角度) # 计算向量 if hip and knee and ankle: # 向量 HK: 髋到膝 向量 KA: 膝到踝 vec_hk np.array([knee[0] - hip[0], knee[1] - hip[1]]) vec_ka np.array([ankle[0] - knee[0], ankle[1] - knee[1]]) # 计算夹角简化版实际应计算躯干与垂直线的夹角 # 这里我们计算膝-髋连线与垂直线的夹角来近似判断背部倾斜 # 垂直向量 (0, -1) 指向图像上方 vertical_vec np.array([0, -1]) dot_product vec_hk[0]*vertical_vec[0] vec_hk[1]*vertical_vec[1] norm_hk np.linalg.norm(vec_hk) norm_v np.linalg.norm(vertical_vec) if norm_hk 0: angle_rad np.arccos(dot_product / (norm_hk * norm_v)) angle_deg np.degrees(angle_rad) # 如果躯干以髋-膝向量近似过于前倾与垂直线夹角过大 if angle_deg 20: # 这是一个经验阈值 feedback.append(⚠️ 背部可能前倾过多请保持背部挺直收紧核心。) score - 25 # 3. 判断下蹲深度 (通过膝-踝的Y坐标差) if knee and ankle: squat_depth knee[1] - ankle[1] # Y坐标差值越大可能蹲得越深 if squat_depth 50: # 这是一个非常粗略的阈值需根据图像尺寸调整 feedback.append( 可以尝试蹲得更低一些直到大腿与地面平行。) score - 15 else: feedback.append(✅ 下蹲深度良好。) if not feedback: feedback.append( 姿势看起来不错继续保持。) return { score: max(score, 0), # 确保分数不为负 feedback: feedback, keypoints: keypoints } # 组装关键点字典 estimated_kps { hip: hip_center, knee: knee_center, ankle: ankle_center, toe: toe_center } analysis_result analyze_squat_pose(estimated_kps) print(f深蹲评分: {analysis_result[score]}/100) for tip in analysis_result[feedback]: print(f - {tip})3.4 步骤四可视化反馈最后我们可以将分析结果和M2FP生成的可视化图叠加给用户更直观的反馈。import cv2 from PIL import Image def visualize_analysis(original_image_path, parsed_result, analysis_result): 将原始图片、M2FP解析结果和姿势分析结果可视化。 # 1. 解码M2FP生成的可视化叠加图 overlay_b64 parsed_result[data].get(overlay_image) if overlay_b64: overlay_data base64.b64decode(overlay_b64) overlay_img Image.open(BytesIO(overlay_data)).convert(RGB) overlay_cv cv2.cvtColor(np.array(overlay_img), cv2.COLOR_RGB2BGR) else: # 如果没有叠加图就用原图 original_img cv2.imread(original_image_path) overlay_cv original_img.copy() # 2. 在图上标注估算的关键点 kps analysis_result.get(keypoints, {}) colors {hip: (255, 0, 0), # 蓝色 knee: (0, 255, 0), # 绿色 ankle: (0, 0, 255), # 红色 toe: (255, 255, 0)} # 青色 for label, point in kps.items(): if point: color colors.get(label, (255, 255, 255)) cv2.circle(overlay_cv, point, 8, color, -1) # 画实心圆 cv2.putText(overlay_cv, label, (point[0]10, point[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) # 3. 连接点画出简易骨架例如连接髋-膝-踝 if kps.get(hip) and kps.get(knee): cv2.line(overlay_cv, kps[hip], kps[knee], (0, 255, 255), 3) if kps.get(knee) and kps.get(ankle): cv2.line(overlay_cv, kps[knee], kps[ankle], (0, 255, 255), 3) # 4. 在图像上方添加评分和反馈 y_offset 30 cv2.putText(overlay_cv, fScore: {analysis_result[score]}/100, (10, y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 200, 0), 2) for i, tip in enumerate(analysis_result[feedback]): y_offset 30 cv2.putText(overlay_cv, tip, (10, y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2) # 显示或保存结果 cv2.imshow(Squat Analysis Result, overlay_cv) cv2.waitKey(0) # 等待按键 cv2.destroyAllWindows() # 或者保存 # cv2.imwrite(analysis_output.jpg, overlay_cv) # 使用函数 visualize_analysis(test_workout.jpg, result, analysis_result)至此一个具备基础深蹲姿势分析功能的原型就完成了。你可以在此基础上扩展分析更多动作如平板支撑、弓步蹲、手臂弯举等。4. 总结与进阶思考通过本教程我们完成了一个完整的闭环从一键部署M2FP人体解析服务到调用API获取精准的身体部位掩码再到利用这些数据实现一个具体的健身动作分析应用。回顾一下核心步骤快速部署利用预置镜像免去了环境配置的烦恼。理解数据掌握了API返回的结构化数据特别是mask掩码的妙用。实战编程学习了如何从掩码中提取关键点并基于简单的几何规则实现姿势评估。可视化反馈将分析结果直观地呈现给用户提升体验。下一步可以做什么更多动作借鉴深蹲分析的思路为其他健身动作如俯卧撑、引体向上设计评估逻辑。精度提升当前的关节点估算是粗略的。可以考虑集成一个专门的人体姿态估计模型如OpenPose、MediaPipe与M2FP的解析结果结合获得更精确的关节点坐标。时序分析处理视频流分析动作的连贯性、速度和节奏。个性化反馈根据用户的历史数据提供个性化的改进建议和训练计划。这个基于M2FP的方案为你快速验证健身类应用的AI功能提供了强大的起点。它解决了“看得清”人体结构的问题让你能更专注于上层业务逻辑的创新。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。