我有一个来自固定相机的视频。分辨率和FPS都很高。我得到的数据为拜耳格式,每个像素使用10位。由于我的平台上没有10位数据类型,因此原始数据使用16位字存储在内存中。我想在通过网络传输数据之前对数据进行某种无损压缩。
- 摄像头不会移动,因此连续帧的大部分几乎是相同的-但由于不可避免的噪声,仍不能完全消除(降噪不是一种选择,因为降噪是无损的,即使噪声也不应“丢失” )。
- 由于FPS高,即使变化的部分在任何两个连续的帧之间也变化不大。
- 但是,看起来相机也有些晃动。在图像空间中,即使很小,但即使静止的物体也并非完全如此。
- 压缩必须实时进行,因此我不能收集很多帧并将它们全部压缩在一起,但是我可以向后看一帧并将其用作参考。
基于以上所述,我的第一个想法是对数据进行位打包,以使这6个冗余位不会浪费在每个字上。但是,我认为如果使用某种熵编码(例如Huffman等),则会自动考虑冗余,因此不需要额外的包装。所以我做了以下工作:
- 取得两个连续帧之间的二进制差异。原始数据范围为0〜1023(例如,无符号10位)。差异数据变为有符号,范围增加到-1023〜1023,但数据变化(或正确的数学术语)变得比原始数据少得多,实际上,大多数值不足为零就不足为奇了。
- 将Rice编码应用于差异。据我了解,对于大多数数值较小的数据集,这似乎是一个不错的选择。
对于1280x720帧,这使我的尺寸减少了60%,并且我的测试系统(单核上的VirtualBox中的Linux)每秒可以进行约40次此类压缩(无需太多优化)。我猜不是那么好,但是很合理(或者是吗?)。
有更好的方法吗?我有任何常见的错误吗?我错过了任何常规步骤吗?以后可能会使用更高分辨率的帧-对于更大的帧大小,我应该期望更好的压缩率吗?
UPD:
- 我使用此库进行Rice编码。该库非常慢(作者本人将其描述为学习而不是实际使用),例如,它在循环中一对一地读写位,这会降低性能。最初它只给我约20 FPS,经过一些非常基本的优化后,它变成了40 FPS(如上所述),后来我对其进行了更多优化,变成了80 FPS。这是在没有向量化的单个i7内核上。
- 至于向量化,不幸的是,我无法想到一种对Rice代码进行向量化的方法(甚至根本不知道它是否可能-在Rice代码上找不到任何数据,我对霍夫曼代码的发现表明:它是顺序的,无法有效地向量化,这可能适用于Rice代码以及其他可变长度代码)。
- 我还尝试了一种完全不同的方法:将数据分成小块(例如,每个像素为64像素)并使用简单的零抑制。我们找到一个块中最大的数字,将表示它所需的位数写到该块的开头(在我的情况下,这需要再增加4位),然后将该块中的所有数字减少到相同的位数。位。我预计压缩率会很差,但是如果片段很小,那么它们中的许多都不会产生噪声尖峰,因此它们的二进制差异可以减小到每个值4〜6位,实际上只有比Rice代码差5%左右,但速度大约是Rice代码的两倍(例如我的情况下为160 FPS)。我曾尝试对其进行矢量化处理,但对矢量化处理还是有点不满,所以也许正因为如此,我只能实现约1.8倍的进一步加速。
由于负数没有前导零,因此我在二进制差之后和莱斯/零抑制之前应用了之字形编码。