如何在JavaScript中解码COCO RLE二进制掩码并转为图像?
在JavaScript中解码COCO RLE掩码并渲染到Canvas的方案
有几个现成的JavaScript工具库可以处理COCO RLE掩码的解码,也可以手动实现解码逻辑,以下是具体方案:
一、可用的第三方库
- @cocodataset/coco-utils:COCO数据集官方提供的工具库,原生支持RLE格式的解码,功能稳定可靠。
- maskjs:轻量级图像掩码处理库,专门针对COCO RLE等常见掩码格式做了优化。
使用@cocodataset/coco-utils的示例
- 先安装库:
npm install @cocodataset/coco-utils
- 解码并渲染到Canvas的代码:
import { maskUtils } from '@cocodataset/coco-utils'; // YOLOv8生成的预测数据 const examplePrediction = { "image_id": "102_jpg", "category_id": 0, "bbox": [153.106, 281.433, 302.518, 130.737], "score": 0.8483, "segmentation": { "size": [640, 640], "counts": "<你的RLE编码字符串>" // 替换为实际的RLE内容 } }; // 解码RLE为二进制掩码数组 const mask = maskUtils.decode(examplePrediction.segmentation); // 将掩码渲染到指定Canvas function renderMaskToCanvas(mask, canvasId) { const canvas = document.getElementById(canvasId); const ctx = canvas.getContext('2d'); const [height, width] = examplePrediction.segmentation.size; canvas.width = width; canvas.height = height; const imageData = ctx.createImageData(width, height); const data = imageData.data; // 遍历掩码,设置像素:白色前景,透明背景 for (let i = 0; i < height; i++) { for (let j = 0; j < width; j++) { const idx = i * width + j; const pixelOffset = idx * 4; if (mask[idx]) { data[pixelOffset] = 255; // 红色通道 data[pixelOffset + 1] = 255; // 绿色通道 data[pixelOffset + 2] = 255; // 蓝色通道 data[pixelOffset + 3] = 255; // 透明度 } else { data[pixelOffset + 3] = 0; } } } ctx.putImageData(imageData, 0, 0); } // 执行渲染(假设页面上有id为maskCanvas的Canvas元素) renderMaskToCanvas(mask, 'maskCanvas');
二、手动实现RLE解码(不依赖第三方库)
如果不想引入额外依赖,可以手动实现COCO RLE的解码逻辑。COCO RLE的规则是:交替记录连续的背景像素数和前景像素数,从背景开始,counts字符串是经过Base64编码的可变长度整数序列。
// 解码COCO RLE掩码 function decodeCocoRLE(rle) { const { size, counts } = rle; const [height, width] = size; const totalPixels = height * width; const mask = new Uint8Array(totalPixels); // 解码counts字符串为整数数组 const countsArr = decodeRLECounts(counts); let currentPixel = 0; let isBackground = true; for (const count of countsArr) { const endPixel = currentPixel + count; if (!isBackground) { // 填充前景区域(值为1) mask.fill(1, currentPixel, endPixel); } currentPixel = endPixel; isBackground = !isBackground; } return mask; } // 解码RLE的counts字段(处理Base64和可变长度编码) function decodeRLECounts(countsStr) { const buffer = Uint8Array.from(atob(countsStr), c => c.charCodeAt(0)); const counts = []; let i = 0; while (i < buffer.length) { let value = 0; let shift = 0; let byte; do { byte = buffer[i++]; value |= (byte & 0x7F) << shift; shift += 7; } while (byte & 0x80); counts.push(value); } return counts; } // 使用示例 const mask = decodeCocoRLE(examplePrediction.segmentation); // 调用之前的renderMaskToCanvas函数渲染到Canvas renderMaskToCanvas(mask, 'maskCanvas');
内容的提问来源于stack exchange,提问作者Nikolay Dyankov
相关产品推荐
相关产品推荐

