ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

浏览器端语义分割实战:tfjs-models DeepLab v3 模型的加载、推理与可视化完整指南

浏览器端语义分割实战:tfjs-models DeepLab v3 模型的加载、推理与可视化完整指南 人工智能深度学习计算机视觉NLP语音【免费下载链接】tfjs-modelsPretrained models for TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-models点击查看免费下载本文围绕 TensorFlow.js 官方模型仓库tfjs-models中的 tensorflow-models/deeplab 包展开系统讲解如何在浏览器中基于 DeepLab v3 完成语义分割Semantic Segmentation从预训练权重选择、量化配置、模型加载到segment/predict/toSegmentationImage三个核心 API 的输入输出与底层实现并给出本地权重转换与 Demo 运行方法。读完本文你将掌握一套可直接落地的浏览器端像素级图像分类方案。一、包与模型概览一个独立的 DeepLab 推理管线deeplab目录deeplab/提供了一个独立的 DeepLab 推理管线实现用于在浏览器中通过 TensorFlow.js 执行语义分割同时附带一个可交互的 Demo。语义分割的第一步是把图像送入一个基于MobileNet-v2骨干网络的预训练模型得到每个像素所属的类别。该实现基于 TensorFlow 官方 DeepLab v3。仓库提供了三组预训练权重分别对应三个经典语义分割数据集权重名称base取值训练数据集识别的类别数典型场景pascalPASCAL VOC 201221 类含背景通用物体分割人、车、动物、家具等cityscapesCityscapes19 类城市街景道路、建筑、车辆、行人等ade20kADE20K151 类室内外场景精细分割三个数据集的标签与配色方案分别定义在 deeplab/src/config.ts 中LABELS.PASCAL第 142 行起、LABELS.CITYSCAPES第 149 行起、LABELS.ADE20K第 155 行起共 151 个类别标签与对应的COLORMAPS调色板。每个数据集拥有各自独立的 colormap 与 labelling scheme因此选择不同的base意味着采用不同的类别集合与可视化配色。二、安装与快速开始包以 npm 包形式发布名称为tensorflow-models/deeplab。它不包含运行时依赖dependencies为空但以 peer dependency 方式依赖tensorflow/tfjs-converter与tensorflow/tfjs-core版本^3.0.0见 deeplab/package.json因此使用前需要一并安装 TensorFlow.js 核心库。npm install tensorflow/tfjs tensorflow/tfjs-converter tensorflow-models/deeplab加载模型并执行一次最简单的分割const tf require(tensorflow/tfjs); const deeplab require(tensorflow-models/deeplab); const loadModel async () { const modelName pascal; // 可选 pascal、cityscapes 或 ade20k const quantizationBytes 2; // 可选 1、2 或 4 return await deeplab.load({base: modelName, quantizationBytes}); }; const input tf.zeros([227, 500, 3]); // ... loadModel() .then((model) model.segment(input)) .then( ({legend}) console.log(The predicted classes are ${JSON.stringify(legend)}));默认行为不传任何参数调用deeplab.load()时会加载PASCAL 变体、量化到 2 字节的模型。该默认值定义在 deeplab/src/index.ts 的load函数默认参数中{base: pascal, quantizationBytes: 2}。三、模型配置详解base、quantizationBytes与modelUrlload函数接受一个ModelConfig配置对象其类型定义见 deeplab/src/types.ts配置项类型必填说明basepascal \| cityscapes \| ade20k与modelUrl二选一选择预训练模型变体同时决定默认 colormap 与标签体系quantizationBytes1 \| 2 \| 4否权重量化字节数。设为 1 或 2 时分别把 int32/float32 权重压缩到 1 或 2 字节设为 4 表示禁用量化modelUrlstring与base二选一自定义 TF.js GraphModel JSON 的加载 URL未提供时根据base与quantizationBytes自动推导load内部会做严格的参数校验deeplab/src/index.tsbase只能是pascal/cityscapes/ade20k三者之一quantizationBytes只能是 1、2 或 4若既未传base也未传modelUrl会直接抛出异常。随后通过tfconv.loadGraphModel加载 GraphModel并包装成SemanticSegmentation实例返回。3.1 量化字节数对模型的影响量化是减小模型体积、加速浏览器加载的关键手段。从 deeplab/src/utils.ts 的getURL实现可以看到权重 URL 的生成规则quantizationBytes 4未量化时路径为${base}/1/default/1/model.json量化时路径为${base}/1/quantized/${quantizationBytes}/1/model.json生成的完整 URL 形如https://tfhub.dev/tensorflow/tfjs-model/deeplab/pascal/1/default/1/model.json?tfjs-formatfileTF Hub 的tfjs-formatfile查询参数。量化到 1 字节能最大程度压缩体积但会引入一定的精度损失实际部署时需要在模型体积与分割精度之间权衡。3.2 加载自定义权重如果不想使用内置的三个预训练模型可以显式传入modelUrl加载自定义权重的 URLconst deeplab require(tensorflow-models/deeplab); const loadModel async () { const url https://tfhub.dev/tensorflow/tfjs-model/deeplab/pascal/1/default/1/model.json?tfjs-formatfile; return await deeplab.load({modelUrl: url}); }; loadModel().then(() console.log(Loaded the model successfully!));注意通过modelUrl加载时base未被设置此时segment方法无法自动推断 colormap 和标签你需要自行提供详见下文segment 方法的配置项一节。3.3 直接实例化SemanticSegmentation类对于需要精细控制初始化与推理行为的场景例如使用自定义标签与配色可以直接使用SemanticSegmentation类把预加载的GraphModel传入构造函数const tfconv require(tensorflow/tfjs-converter); const deeplab require(tensorflow-models/deeplab); const loadModel async () { const base pascal; // 可选 pascal、cityscapes、ade20k const quantizationBytes 2; // 可选 1、2 或 4 // 用 getURL 工具函数获取预训练权重 URL const modelUrl deeplab.getURL(base, quantizationBytes); const rawModel await tfconv.loadGraphModel(modelUrl); return new deeplab.SemanticSegmentation(rawModel); }; loadModel().then(() console.log(Loaded the model successfully!));SemanticSegmentation类定义于 deeplab/src/index.ts构造函数接收graphModel和可选的base对外暴露predict、segment、dispose三个方法。构造函数接受base参数作为第二个参数在segment未显式提供 colormap/labels 时使用。四、获取默认 colormap 与标签体系三个数据集各自有官方的配色与标签约定。包提供了两个工具函数直接获取deeplab/src/utils.tsimport {getLabels, getColormap} from tensorflow-models/deeplab; const model ade20k; const colormap getColormap(model); // [number, number, number][]RGB 三元组数组 const labels getLabels(model); // string[]类别名称数组getColormap(base)返回该数据集的 RGB 配色数组每个标签对应一个[r, g, b]三元组getLabels(base)返回类别名称数组索引与 colormap 一一对应。在 deeplab/src/config.ts 中PASCAL 的 256 项调色板COLORMAPS.PASCAL与官方 VOC 的索引配色一致——需要说明的是PASCAL 的调色板长度大于实际 21 个标签数DATASET_MAX_ENTRIES.PASCAL 256这是为兼容原版 Python 实现见 utils_test.ts 中对createPascalColormap与原始 256 色调色板完全一致的断言而 ADE20K 的 151 个标签与 151 色调色板严格一一对应DATASET_MAX_ENTRIES.ADE20K 151。每个模型能识别的类别集合不同具体见 config.ts 中的三组LABELS定义PASCAL 识别 person、car、cat、dog 等 21 类Cityscapes 识别 road、sidewalk、building、car 等 19 类街景要素ADE20K 识别 151 个室内外场景物体类别。五、segment方法端到端语义分割segment方法覆盖了绝大多数使用场景——输入一张图像直接得到类别名 → RGB 颜色的 legend 和可直接绘制到 canvas 的彩色分割图。5.1 输入参数model.segment(image, config?)image::ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | tf.Tensor3D—— 待分割的图像既可以是 DOM 图像对象也可以是tf.Tensor3D张量config.canvas可选::HTMLCanvasElement—— 传入 canvas 元素时输出会直接绘制到该 canvas 上config.colormap可选::[number, number, number][]—— 与标签对应的 RGB 颜色数组config.labels可选::string[]—— 与标签对应的类别名称数组。默认情况下colormap与labels会根据初始化时传入的base自动设置见 deeplab/src/index.ts 的segment实现当二者未提供时自动调用getColormap(this.base)与getLabels(this.base)补齐。5.2 输出结构segment返回一个PromiseDeepLabOutput包含四个字段类型见 deeplab/src/types.ts字段类型含义legend{ [name: string]: [number, number, number] }图像中识别出的类别名到 RGB 颜色的字典heightnumber返回的分割图高度widthnumber返回的分割图宽度segmentationMapUint8ClampedArray彩色分割图像素数据可直接喂给ImageData并映射到 canvas5.3 使用示例const classify async (image) { return await model.segment(image); }拿到segmentationMap后可以结合 canvas 的像素操作 APIputImageData把结果渲染到页面const {segmentationMap, width, height, legend} await model.segment(image); const ctx canvas.getContext(2d); const imageData new ImageData(segmentationMap, width, height); ctx.putImageData(imageData, 0, 0);5.4 使用前提segment内部要求要么初始化时提供了base要么显式传入colormap与labels二者缺一不可deeplab/src/index.ts。因此通过modelUrl加载自定义权重且未传base时必须手动提供colormap和labels否则会抛异常。提示如需更细粒度的控制例如先拿到原始分割图再自定义上色建议使用下文介绍的predict与toSegmentationImage方法组合。六、predict方法生成原始语义分割图predict直接返回模型输出的原始分割图——一个二维张量每个网格单元上标注了该位置的类别编号。网格最大边长固定为513CROP_SIZE: 513见 deeplab/src/config.ts。6.1 输入输出输入image::ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | tf.Tensor3D输出rawSegmentationMap::tf.Tensor2D—— 图像的分割图张量形状为[height, width]每个元素是类别索引。6.2 使用示例const getSemanticSegmentationMap (image) { return model.predict(image) }6.3 底层实现predict的完整实现见 deeplab/src/index.tspublic predict(input: DeepLabInput): tf.Tensor2D { return tf.tidy(() { const data tf.cast(toInputTensor(input), int32); return tf.squeeze(this.model.execute(data) as tf.Tensor); }); }整个推理包裹在tf.tidy中自动回收中间张量输入先经过toInputTensor预处理并转为int32对应转换脚本中--output_node_namesSemanticPredictions的输出节点再执行 GraphModel 前向计算最后squeeze去掉 batch 维得到二维分割图。其中toInputTensordeeplab/src/utils.ts完成了关键的输入预处理若输入不是张量则通过tf.browser.fromPixels把图像/视频帧转为张量取长边按resizeRatio CROP_SIZE / Math.max(width, height)计算缩放比例用双线性插值tf.image.resizeBilinear把图像等比缩放到长边不超过 513expandDims增加 batch 维后送入模型。从源码结构看这套预处理保证任意分辨率的输入都会被统一缩放到模型期望的输入尺寸范围内。七、toSegmentationImage把分割图翻译为彩色标注图predict得到的只是类别索引矩阵要变成人眼可读的彩色图需要借助toSegmentationImage函数。它是segment内部使用的核心函数也作为独立 API 导出见 deeplab/src/index.ts 的导出列表与 deeplab/src/utils.ts 的实现。7.1 输入参数toSegmentationImage(colormap, labels, segmentationMap, canvas?)colormap::[number, number, number][]—— 与标签对应的 RGB 颜色数组labels::string[]—— 与标签对应的类别名称数组segmentationMap::tf.Tensor2D——predict输出的原始分割图canvas可选::HTMLCanvasElement—— 传入时输出直接绘制到该 canvas。7.2 输出结构返回PromiseSegmentationData包含两个字段deeplab/src/types.tslegend::{ [name: string]: [number, number, number] }—— 识别出的类别名到颜色的字典segmentationMap::Uint8ClampedArray—— 彩色分割图可直接喂给ImageData并绘制到 canvas。7.3 使用示例const base pascal; const translateSegmentationMap async (segmentationMap) { return await toSegmentationImage( getColormap(base), getLabels(base), segmentationMap) }7.4 实现细节从 deeplab/src/utils.ts 的实现看该函数会校验colormap长度必须不小于labels长度否则抛出colormap 必须能覆盖每个标签的异常遍历分割图的每个像素用tf.buffer按类别索引把colormap[label]的 RGB 值写入缓冲区生成彩色张量通过tf.browser.toPixels输出为Uint8ClampedArray可选绘制到传入的 canvas统计实际出现的类别集合构建legend字典。这也解释了segment与toSegmentationImage的关系segment内部就是predict之后调用toSegmentationImage再补上height与width字段见 deeplab/src/index.ts。八、内存管理disposeSemanticSegmentation实例持有 GraphModel 及其权重使用完毕后应调用dispose释放资源deeplab/src/index.tsawait model.dispose();仓库测试 deeplab/src/deeplab_test.ts 中专门有一个用例验证SemanticSegmentation should not leak——用tf.memory().numTensors断言segment前后张量数量不变确保推理过程不产生内存泄漏。同文件还验证了 513 边长输入下predict输出维度与输入一致、segment输出的legend包含background 键等行为。九、本地权重转换从冻结图到 TF.js 格式本模型基于 TensorFlow 官方的 DeepLab v3 实现权重托管在 TF Hub。如果你需要从原始预训练权重自行转换可以查看 deeplab/scripts/convert_deeplab.sh 转换脚本并把dist替换为目标目录后运行./scripts/convert_deeplab.sh --target_dir ./scripts/dist查看脚本支持的选项./scripts/convert_deeplab.sh -h从脚本实现可以看到其工作原理与约束环境要求要求 Python 3.6 或更早版本脚本开头会检查并拒绝 3.7依赖wget与realpathcoreutils主要选项--target_dir指定输出目录默认$SCRIPT_DIR/dist--use_venvtrue使用预装依赖的虚拟环境会安装tensorflowjs0.8.6--tmp_working_dirtrue使用临时工作目录模型来源从http://download.tensorflow.org/models下载三个 MobileNet-v2 骨干的冻结图pascal 的deeplabv3_mnv2_dm05_pascal_trainaug、cityscapes 的deeplabv3_mnv2_cityscapes_train、ade20k 的deeplabv3_mnv2_ade20k_train转换流程对每个模型调用tensorflowjs_converter以tf_frozen_model为输入格式--output_node_namesSemanticPredictions指定输出节点分别生成未量化、量化 1 字节、量化 2 字节三份产物输出目录结构与getURL中的路径规则{base}/1/default/1与{base}/1/quantized/{1,2}/1完全对应。十、运行官方 Demodeeplab附带一个可交互的 Demo可对预设图片分别用三个 base 模型体验语义分割效果。10.1 快速启动按 deeplab/demo/README.md 的说明# 在仓库根目录与 deeplab 目录安装依赖 yarn # 根目录 cd deeplab yarn yarn build-npm # 构建 deeplab 包 # 进入 demo 目录并启动开发服务器 cd demo yarn yarn watch警告Cityscapes 模型在 Demo 中运行资源开销很大可能会拖垮浏览器建议优先体验 pascal 与 ade20k。10.2 本地开发模式如果你在本地修改了 deeplab 源码并希望 Demo 即时生效可使用yalc本地发布-链接流程cd deeplab yarn # 安装依赖 yarn publish-local # 构建并通过 yalc 发布本地副本 cd demo yarn yarn link-local # 把 demo 链接到本地发布的 deeplab 包 yarn watch # 启动开发服务器之后每当源码更新只需在deeplab目录重新执行yarn publish-local即可同步到 Demo。十一、API 速查与最佳实践小结API输入输出适用场景deeplab.load(config)ModelConfigPromiseSemanticSegmentation加载预训练/自定义模型model.segment(image, config?)图像 可选 colormap/labels/canvasDeepLabOutputlegend 彩色分割图 尺寸端到端分割开箱即用model.predict(image)图像tf.Tensor2D原始分割图需要自定义后处理/上色toSegmentationImage(...)colormap labels 分割图SegmentationDatalegend 彩色像素把原始分割图转彩色图model.dispose()—Promisevoid释放模型资源实践要点体积与精度的权衡生产环境建议先用quantizationBytes: 1压缩体积若精度不达标再升级到 2 或 4正确匹配 base 与标签segment的 legend 依赖与base匹配的 colormap/labels通过modelUrl加载时务必自行提供二者输入统一缩放所有输入都会等比缩放到长边 513原始分辨率不会影响推理形状只影响细节保留程度资源管理推理内部已通过tf.tidy自动回收临时张量有测试保证不泄漏但不再使用模型时应显式调用dispose按需选择数据集街景类应用优先 cityscapes通用物体优先 pascal室内外复杂场景优先 ade20k151 类。本文所有 API 说明与参数细节均以仓库源码为准可进一步查阅 deeplab/src/index.ts、deeplab/src/types.ts、deeplab/src/utils.ts 与 deeplab/src/config.ts 深入理解实现并通过 deeplab/src/deeplab_test.ts 与 deeplab/src/utils_test.ts 验证上述行为。赞分享人工智能深度学习计算机视觉NLP语音【免费下载链接】tfjs-modelsPretrained models for TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-models点击查看免费下载相关推荐GluonCV语义分割终极指南FCN、PSPNet、DeepLab-v3模型实战详解GluonCV语义分割终极指南FCN、PSPNet、DeepLab v3模型实战详解 GluonCV是由DMLC开发的计算机视觉库提供了丰富的预训练模型和计算机视觉深度学习预训练TensorFlow 实现语义分割DeepLab V3 指南TensorFlow 实现语义分割DeepLab V3 指南 项目介绍 DeepLab V3 是一个基于 TensorFlow 的语义分割模型实现专注于提高BodyPix 2.0 浏览器端人体与身体部位分割实战指南TensorFlow.js 模型加载、多人体推理与可视化渲染BodyPix 2.0 浏览器端人体与身体部位分割实战指南TensorFlow.js 模型加载、多人体推理与可视化渲染 BodyPix 是 TensorFlo人工智能深度学习计算机视觉NLP语音上一篇WeChatMsg一站式高效微信聊天记录永久保存与智能分析工具下一篇OneUptime 工作流配置与安全指南启用控制、机密管理、导入导出与运行时限制全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表