游程编码(Run-Length Encoding, RLE)详解
游程编码(RLE,Run-Length Encoding)是一种简单而有效的数据压缩方法,特别适用于具有大量连续重复值的数据。它在图像处理、分割掩码表示和时间序列数据压缩等领域有着广泛的应用。
它通过记录每个值的“运行长度”(即连续出现的次数)来减少存储空间。RLE 在图像处理、文件压缩和机器学习中都有广泛应用,例如在 COCO 数据集中用于表示分割掩码。
1. RLE 的基本概念
定义:
- 游程 :一段连续的相同值。
- 编码 :将每个游程用一对值表示,通常是
(值, 长度)
或(长度, 值)
或(起点, 长度)
。- 对于二值mask编码有简化形式
- 交替存储连续的前景像素数和背景像素数。示例:
11100111110
编码为[3, 2, 5, 1]
- 存储前景像素的起点和长度。示例:
11100111110
编码为[0, 3, 5, 5]
- 交替存储连续的前景像素数和背景像素数。示例:
- 对于二值mask编码有简化形式
示例:
假设有一个二值数组 [0, 0, 0, 1, 1, 1, 1, 0, 0]
:
- 使用 RLE 编码后可以表示为
[(0, 3), (1, 4), (0, 2)]
,即:0
出现了 3 次,1
出现了 4 次,0
又出现了 2 次。
2. RLE 的两种常见形式
2.1 紧凑格式
- 将所有游程的长度按顺序排列成一个一维数组。
- 示例:
- 输入数组:
[0, 0, 0, 1, 1, 1, 1, 0, 0]
- 紧凑格式:
[3, 4, 2]
(分别表示0
的长度、1
的长度、0
的长度)。
- 输入数组:
这种格式常用于 COCO 数据集中的分割掩码。
2.2 展开格式
- 直接记录每个像素的值(通常为布尔值),不进行压缩。
- 示例:
- 输入数组:
[0, 0, 0, 1, 1, 1, 1, 0, 0]
- 展开格式:
[False, False, False, True, True, True, True, False, False]
- 输入数组:
这种格式占用更多存储空间,但在某些情况下更易于处理。
3. RLE 的应用场景
3.1 图像压缩
- RLE 是一种简单且高效的图像压缩方法,尤其适用于二值图像或具有大量连续颜色区域的图像。
- 示例:
- 黑白图像中的大面积背景可以用 RLE 表示,从而显著减少存储空间。
3.2 分割掩码表示
- 在目标检测和实例分割任务中,RLE 常用于表示分割掩码(mask)。相比于直接存储二值图像,RLE 能够大幅减少数据量。
- 示例:
- COCO 数据集中的
segmentation
字段使用 RLE 格式存储分割掩码。
- COCO 数据集中的
3.3 时间序列数据
- 对于具有重复模式的时间序列数据,RLE 可以有效压缩存储空间。
- 示例:
- 某个传感器输出的信号可能包含大量连续的相同值,RLE 可以用来压缩这些数据。
4. RLE 的优缺点
优点:
- 简单高效 RLE 的实现非常简单,适合处理具有大量连续重复值的数据。
- 无损压缩 RLE 是一种无损压缩算法,解码后可以完全恢复原始数据。
- 节省存储空间 对于具有长游程的数据,RLE 能够显著减少存储需求。
缺点:
- 对随机数据无效 如果数据中没有连续重复值(如随机噪声),RLE 不仅无法压缩,反而会增加存储开销。
- 不适合复杂形状 对于复杂的二值图像(如细碎的边缘或噪声),RLE 的压缩效果较差。
5. RLE 与mask互相转换
这里RLE编码是1base的, 编码格式是二值mask的(起点, 长度)
1 | import numpy as np |
6. YOLO标签 与mask互相转换
- Mask转YOLO标签
1 | import cv2 |
- YOLO标签转Mask
1 | import numpy as np |