ml5.js BodyPix 人体与身体部位分割指南:在浏览器中实时分割人像与 24 个身体部位 人工智能机器学习深度学习计算机视觉NLP【免费下载链接】ml5-libraryFriendly machine learning for the web! 项目地址https://gitcode.com/gh_mirrors/ml/ml5-library点击查看免费下载BodyPix 是 ml5.js 提供的人像分割person segmentation模型封装它基于 TensorFlow.js 在浏览器端运行可把图像像素划分为“人”与“背景”两大类并进一步将人体像素细分为 24 个身体部位。本文以 docs/reference/bodypix.md 为核心脉络结合 src/BodyPix 源码与 examples/p5js/BodyPix 示例完整讲解初始化参数、segment()与segmentWithParts()的调用方式与返回结构、调色板定制技巧以及模型与训练数据的来源读完后你可以在自己的 p5.js 或原生 JavaScript 项目中直接落地人像抠图、背景替换、身体部位可视化等能力。BodyPix 是什么在浏览器中做像素级人像分割按 BodyPix 开发者的原话BodyPix 是一个开源机器学习模型允许在浏览器中通过 TensorFlow.js 进行人物与身体部位分割。在计算机视觉中图像分割image segmentation是指将图像中的像素按语义区域分组的技术通常用于定位物体与边界。BodyPix 模型经过训练可以对一个人以及二十四个身体部位如左手、右前小腿外侧、躯干背部完成这项任务。换句话说BodyPix 可以把图像的像素分为两类1代表人的像素2代表背景的像素它还可以把代表人的像素进一步归类到 24 个身体部位中的任意一个。从 ml5.js 的实现看这一点被封装在 src/BodyPix/index.js 中它直接导入tensorflow-models/body-pix包import * as bp from tensorflow-models/body-pix;模型加载后即可调用底层estimatePersonSegmentation人像分割与estimatePartSegmentation身体部位分割两个 API。也就是说你不需要直接接触 TensorFlow.js 的底层接口ml5.js 已经替你完成了模型加载、参数传递与结果格式转换。快速开始5 行代码完成第一次分割把下面的代码放入你的 p5.js sketch 或普通 HTML 页面中即可体验 BodyPix 的基础流程const bodypix ml5.bodyPix(modelReady); function modelReady() { // 对给定的图片执行分割 bodypix.segment(img, gotResults); } function gotResults(error, result) { if (error) { console.log(error); return; } // 输出结果 console.log(result.backgroundMask); }流程很直观先通过ml5.bodyPix(modelReady)创建实例并传入模型就绪回调模型就绪后在回调里调用bodypix.segment(img, gotResults)对图像执行分割最终结果在gotResults(error, result)中接收。注意这里img可以是HTMLImageElement、HTMLVideoElement、ImageData或HTMLCanvasElement。初始化与配置参数构造函数签名const bodyPix new ml5.bodyPix(?video, ?options, ?callback);三个参数中video与options是可选的callback是模型加载完成后执行的回调函数参数必填说明video可选一个HTMLVideoElement传入后可作为后续segment()/segmentWithParts()的默认输入callback必填模型加载完成后执行的回调函数options可选用于改变默认行为的配置对象可用项见下文构造函数内部的处理可参考 src/BodyPix/index.js它把video存入this.video用传入的options覆盖默认值生成this.config并调用this.loadModel()异步加载模型最后通过callCallbacksrc/utils/callcallback.js把回调接入加载流程。加载完成后this.modelReady被置为truesrc/BodyPix/index.js。options 完整配置项文档给出的默认配置如下{ multiplier: 0.75, // 1.0, 0.75, 或 0.50, 0.25 outputStride: 16, // 8, 16, 或 32默认是 16 segmentationThreshold: 0.5, // 0 - 1默认是 0.5 palette: { /* 24 个身体部位的颜色映射见下文 */ }, }对照 src/BodyPix/index.js 中的DEFAULTS还可以确认一个文档中未列出的隐藏配置项——returnTensors配置项取值默认值作用multiplier1.0、0.75、0.50、0.250.75MobileNet 的宽度乘子控制模型大小与精度之间的权衡数值越小模型越快但精度越低outputStride8、16、3216输出步长影响分割结果的像素精度与计算量8最精细segmentationThreshold0-10.5判定像素属于“人”的置信度阈值越低越容易把人更多地纳入分割结果palette对象BODYPIX_PALETTE24 个身体部位各自的id与 RGBcolor映射returnTensors布尔值false是否在结果中保留 TensorFlow 张量用于底层调试或进一步张量运算其中palette定义在独立的 src/BodyPix/BODYPIX_PALETTE.js 中对应 24 个身体部位的完整颜色表。文档原样给出了这份调色板整理成表格如下ml5.js 默认即为这些颜色部位idRGB 颜色leftFace0[110, 64, 170]rightFace1[106, 72, 183]rightUpperLegFront2[100, 81, 196]rightLowerLegBack3[92, 91, 206]rightUpperLegBack4[84, 101, 214]leftLowerLegFront5[75, 113, 221]leftUpperLegFront6[66, 125, 224]leftUpperLegBack7[56, 138, 226]leftLowerLegBack8[48, 150, 224]rightFeet9[40, 163, 220]rightLowerLegFront10[33, 176, 214]leftFeet11[29, 188, 205]torsoFront12[26, 199, 194]torsoBack13[26, 210, 182]rightUpperArmFront14[28, 219, 169]rightUpperArmBack15[33, 227, 155]rightLowerArmBack16[41, 234, 141]leftLowerArmFront17[51, 240, 128]leftUpperArmFront18[64, 243, 116]leftUpperArmBack19[79, 246, 105]leftLowerArmBack20[96, 247, 97]rightHand21[115, 246, 91]rightLowerArmFront22[134, 245, 88]leftHand23[155, 243, 88]值得注意当在 p5.js 环境中传入调色板时ml5.js 还支持直接用 p5 的颜色对象p5.Color。src/BodyPix/index.js 中的bodyPartsSpec()会先检查传入的调色板是否达到 24 个部位再通过p5Color2RGB()把p5.Color转回[r, g, b]数组保证内部始终以 RGB 数组工作。这一特性在 examples/p5js/BodyPix/BodyPix_Webcam_Parts/sketch.js 中被用于实现随机 HSB/RGB 调色板生成。运行时参数覆盖除了构造时设置optionssegment()与segmentWithParts()也接受一个options参数用于在单次调用中临时修改outputStride与segmentationThresholdsegmentWithParts()还额外支持palette。从源码看这些运行时选项会被写入this.config再传给底层 APIsrc/BodyPix/index.jsthis.config.palette segmentationOptions.palette || this.config.palette; this.config.outputStride segmentationOptions.outputStride || this.config.outputStride; this.config.segmentationThreshold segmentationOptions.segmentationThreshold || this.config.segmentationThreshold;属性Properties创建实例后你可以访问以下公开属性属性类型说明.videoObject构造时传入的HTMLVideoElement未传则为null.modelObject已加载的 BodyPix 底层模型.modelReadyBoolean模型是否加载完成的标志truthy 表示已就绪.modelPathString模型路径.configObject当前生效的 BodyPix 配置对象包含multiplier、outputStride、segmentationThreshold、palette、returnTensors其中.config尤其有用在 examples/p5js/BodyPix/BodyPix_Webcam_Parts/sketch.js 中可以看到自定义调色板正是通过读取bodypix.config.palette并改写各部位的color实现的。方法详解.segment()人像与背景分割允许你把人物从背景中分割出来。bodyPix.segment(?input, ?options, callback);输入inputHTMLImageElement、HTMLVideoElement、ImageData、HTMLCanvasElement之一。注意视频也可以在构造函数中传入作为默认输入。optionsObject可修改outputStride与segmentationThreshold。callbackFunction用于处理.segment()结果通常用来对分割后的图像做后续处理。输出返回一个对象如果环境中存在 p5.js掩码会是p5.Image否则是像素数组UInt8{ segmentation, raw: { personMask: null, backgroundMask: null, }, tensor: { personMask: null, backgroundMask: null, }, personMask: null, backgroundMask: null, }内部实现segment()的参数解析依赖 src/utils/handleArguments.js 中的handleArguments()——它支持任意顺序的可选参数组合会自动识别图像/视频元素、配置对象与回调src/BodyPix/index.js。若既没有传入图像也没有在构造时传入视频会抛出错误No input image provided...。真正的工作在segmentInternal()src/BodyPix/index.js中完成等待模型就绪await this.ready并等待媒体可读mediaReady调用底层this.model.estimatePersonSegmentation(imgToSegment, outputStride, segmentationThreshold)得到像素级分割结果segmentation用bp.toMaskImageData(segmentation, true)生成背景掩码、bp.toMaskImageData(segmentation, false)生成人物掩码存入raw在tf.tidy中把原图与分割掩码做张量乘法得到带 alpha 通道的人物/背景掩码张量通过 src/utils/generatedImageResult.js 把张量转成raw像素数组、blob与如果存在 p5p5.Image若config.returnTensors为true同时把张量放入result.tensor否则张量会被dispose()释放。这也解释了为什么结果里同时出现raw、tensor与顶层personMask/backgroundMask三套字段raw是ImageData级别的像素数据tensor是 TensorFlow 张量仅returnTensors: true时顶层字段是便于直接绘制的p5.Imagep5 环境下或像素数组。.segmentWithParts()身体部位分割允许你获取人物的身体部位分割结果。bodyPix.segmentWithParts(?input, ?options, callback);输入inputHTMLImageElement、HTMLVideoElement、ImageData、HTMLCanvasElement之一。视频同样可在构造函数中传入。optionsObject可修改outputStride、segmentationThreshold与palette。callbackFunction处理分割结果的回调。输出{ segmentation: *ImageData*, raw: { personMask: *ImageData*, backgroundMask: *ImageData*, partMask: *ImageData* }, tensor: { personMask: *Tensor*, backgroundMask: *Tensor*, partMask: *Tensor*, }, personMask: *P5Image*, backgroundMask: *P5Image*, partMask: *P5Image*, bodyParts: *JSONObject* }与segment()相比这里多了partMask身体部位着色掩码和bodyParts部位元数据。在segmentWithPartsInternal()src/BodyPix/index.js中底层调用的是estimatePartSegmentation并通过bp.toColoredPartImageData(segmentation, colorsArray)结合调色板数组生成彩色部位掩码bodyParts则来自bodyPartsSpec()包含每个部位的id与color。完整可运行示例示例一静态图片分割p5.js完整代码见 examples/p5js/BodyPix/BodyPix_Image核心逻辑如下节选自其 sketch.jslet bodypix; let segmentation; let img; function preload() { img loadImage(data/harriet.jpg); bodypix ml5.bodyPix(); } function setup() { createCanvas(480, 560); bodypix.segment(img, gotResults); } function gotResults(err, result) { if (err) { console.log(err); return; } segmentation result; background(0); image(segmentation.backgroundMask, 0, 0, width, height); }这里segmentation.backgroundMask是 p5.Image可以直接用image()绘制到画布上实现“只保留背景、人物变黑”的视觉效果。示例二网络摄像头实时分割p5.js见 examples/p5js/BodyPix/BodyPix_Webcam节选自其 sketch.jsconst options { outputStride: 8, // 8, 16, 或 32默认是 16 segmentationThreshold: 0.3, // 0 - 1默认是 0.5 }; function preload() { bodypix ml5.bodyPix(options); } function setup() { createCanvas(320, 240); video createCapture(VIDEO, videoReady); video.size(width, height); } function videoReady() { bodypix.segment(video, gotResults); } function draw() { background(0); if (segmentation) { image(segmentation.backgroundMask, 0, 0, width, height); } } function gotResults(error, result) { if (error) { console.log(error); return; } segmentation result; bodypix.segment(video, gotResults); // 在回调中再次调用形成连续分割循环 }注意两个实用技巧一是把outputStride调低到8、segmentationThreshold调低到0.3以获得更精细的实时分割二是在gotResults回调里递归调用bodypix.segment(video, gotResults)让每一帧分割完成后立即处理下一帧形成流畅的连续分割管线。此外视频可以只作为输入通过隐藏原始视频元素、只绘制掩码画布实现“虚拟背景”。示例三身体部位实时着色p5.js见 examples/p5js/BodyPix/BodyPix_Webcam_Parts节选自其 sketch.jsfunction videoReady() { bodypix.segmentWithParts(video, gotResults, options); } function gotResults(err, result) { if (err) { console.log(err); return; } segmentation result; background(255, 0, 0); image(segmentation.partMask, 0, 0, width, height); bodypix.segmentWithParts(video, gotResults, options); }segmentation.partMask就是 24 个身体部位按调色板着色后的彩色掩码直接绘制即可看到身体各部位被不同颜色标注。同一示例中还演示了自定义调色板createSimplePalette()随机为每个部位分配 RGB 颜色createHSBPalette()用 HSB 色彩模式生成随机色createRGBPalette()生成随机 RGB 色见 examples/p5js/BodyPix/BodyPix_Webcam_Parts/sketch.js都通过改写options.palette实现。示例四纯 JavaScript无 p5.js如果不想依赖 p5.js可以参考 examples/javascript/BodyPix/BodyPix_Image 的 sketch.js它使用await ml5.bodyPix()与await bodypix.segment(img)的 Promise 风格调用并把segmentation.raw.backgroundMask.data转成ImageData后绘制到canvas上。示例目录中还有同名的 Webcam 与 Webcam Parts 版本以及对应的 HTML 入口 examples/javascript/BodyPix/BodyPix_Image/index.html通过script srchttp://localhost:8080/ml5.js引入本地构建的 ml5.js。所有示例在仓库中均有对应 HTML 入口与素材图片版使用data/harriet.jpg、data/ada.jpg见 examples/p5js/BodyPix/BodyPix_Image 与 examples/javascript/BodyPix/BodyPix_Image。运行这些示例时你需要先构建 ml5.js 并在本地启动一个静态服务器参考 docs/tutorials/local-web-server.md因为浏览器环境加载本地文件与模型资源通常需要 HTTP 服务。模型与数据来源该项目由 Ellen Nickles 发起。MobileNetV1 模型传记描述MobileNet 描述了一类为算力受限平台如移动设备、嵌入式设备优化而设计的机器学习模型架构可用于图像分类、目标检测与图像分割等任务。ml5.js 使用的这个 MobileNet 模型属于卷积神经网络CNN经过训练可检测图像或视频中的人与 24 个身体大致区域。CNN 在图像像素中寻找模式如水平或垂直边缘并通过逐层计算组合出更复杂的模式如角或圆最终识别出它预测属于某个类别的精细模式如左脸或右大臂前侧——具体类别取决于模型训练数据集中图像的标注方式。ml5.js 默认模型使用基于 TensorFlow.js 创建的 MobileNet。TensorFlow 是由 Google 开发的开源机器学习平台。开发者与年份Google 的 TensorFlow.js 团队。TensorFlow.js BodyPix 模型由纽约大学的 Dan Oved 与 Google Research 的 Tyler Zhu 及更多贡献者于 2019 年开发。用途与目标用户TensorFlow 是一个开源机器学习平台拥有全面而灵活的工具、库与社区资源生态。该模型以 Apache License 2.0 许可提供给 ml5.js 使用。托管位置截至 2019 年 6 月ml5.js 从 TensorFlow 导入 MobileNetV1模型托管在 NPM 数据库上这意味着你的 ml5 sketch 会自动使用 NPM 上分发的最新版本。ml5.js 贡献者与年份由 Joey Lee 于 2019 年移植到 ml5.js。MobileNetV1 数据传记描述根据官方文章模型训练数据包含两部分1来自 COCO 数据集的图像2数字生成的“模拟数据”。来源COCO 数据集由多个学术与商业机构的合作者共同维护用于“大规模目标检测、分割与图像描述”根据论文其图像来自 FlickrGoogle Research 的 Per Karlsson 渲染了数据集中其余部分的模拟图像。采集者与年份COCO 数据库始于 2014 年。采集方法COCO 采集图像并将像素标注为分割区域的方法在论文中有详细描述。用途与目标用户COCO 数据集旨在推进计算机视觉研究。使用混合数据集的原因正如官方文章所述为像素级分割任务手动标注大量训练数据把图像像素分成 24 个身体部位区域非常耗时。作为替代我们在内部使用计算机图形渲染带有 ground truth 身体部位分割标注的图像。训练时我们把渲染图像与真实 COCO 图像带 2D 关键点与实例分割标注混合在一起。源码结构与测试验证BodyPix 模块的源码组织如下src/BodyPix/index.js核心实现包含BodyPix类、默认配置、参数解析、分割与部位分割两条完整管线src/BodyPix/BODYPIX_PALETTE.js24 个身体部位的默认调色板src/BodyPix/tests/BodyPix.test.js测试用例验证默认配置值multiplier: 0.75、outputStride: 16、segmentationThreshold: 0.5、segment()对ImageData的输入支持以及对 128x128 测试图片的分割尺寸正确性src/utils/handleArguments.js通用参数解析器识别图像/视频/ImageData/p5 元素/配置/回调src/utils/generatedImageResult.js张量到raw/blob/p5.Image的结果转换src/utils/p5Utils.jsp5 环境检测与 p5 图像转换工具。测试代码src/BodyPix/tests/BodyPix.test.js还提供了一种无须浏览器 UI 即可验证 BodyPix 行为的方式直接await bodyPix()创建实例再对随机ImageData或固定图片调用bp.segment(img)并断言返回的segmentation.width/segmentation.height。这印证了ml5.bodyPix()在没有显式回调时会返回一个 Promise见 src/BodyPix/index.js因此你完全可以用 async/await 风格替代回调风格编写代码。小结BodyPix 是 ml5.js 中最适合快速上手的人像分割模型ml5.bodyPix()一行完成初始化segment()与segmentWithParts()分别提供人/背景二分类分割与 24 个身体部位细分返回结果同时覆盖raw像素数据、p5.Image与可选张量天然适配 p5.js 绘图与纯 JavaScript 两种场景。无论是做虚拟背景、人像抠图、身体部位着色还是交互艺术装置配合 examples/p5js/BodyPix 与 examples/javascript/BodyPix 下的四个示例都能快速起步。如果你想在运行前进一步了解模型加载与回调机制可继续阅读 docs/tutorials/promises-and-callbacks.md。赞分享人工智能机器学习深度学习计算机视觉NLP【免费下载链接】ml5-libraryFriendly machine learning for the web! 项目地址https://gitcode.com/gh_mirrors/ml/ml5-library点击查看免费下载相关推荐BodyPix 人体分割详解在 TF.js 的 body-segmentation 中使用 BodyPix 实现人像与 24 部位语义分割BodyPix 人体分割详解在 TF.js 的 body segmentation 中使用 BodyPix 实现人像与 24 部位语义分割 BodyPix 是人工智能深度学习计算机视觉NLP语音BodyPix 2.0 浏览器端人体与身体部位分割实战指南TensorFlow.js 模型加载、多人体推理与可视化渲染BodyPix 2.0 浏览器端人体与身体部位分割实战指南TensorFlow.js 模型加载、多人体推理与可视化渲染 BodyPix 是 TensorFlo人工智能深度学习计算机视觉NLP语音BodyPix 浏览器端人体与身体部位分割实战指南基于 TensorFlow.js 的模型加载、推理与图像合成BodyPix 浏览器端人体与身体部位分割实战指南基于 TensorFlow.js 的模型加载、推理与图像合成 BodyPix 是 TensorFlow.js人工智能深度学习计算机视觉NLP语音上一篇Video2X终极指南免费AI视频增强工具轻松实现4K超分辨率与智能插帧下一篇codeforces-go中的几何问题空间关系创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考