更好的矢量数据压缩算法?

时间:2010-06-25 14:01:08

标签: c++ compression

我需要压缩一些空间相关的数据记录。目前我使用zlib获得1.2x-1.5x压缩,但我认为它应该可以更像2x。数据记录有各种字段,但是例如,zlib似乎无法压缩点列表。

这些点代表道路网络。它们是XXXXYYYY形式的定点4字节整数对。通常,如果单个数据块具有100个点,则将仅存在X和Y的前两个字节的几个组合(空间相关性)。但是底部字节总是在变化,并且必须看起来像随机数据到zlib。

类似地,记录具有4字节的ID,这些ID往往具有恒定的高字节和可变的低字节。

是否有其他算法可以更好地压缩此类数据?我正在使用C ++。

修改:请不要再提供更改数据本身的建议。我的问题是关于自动压缩算法。如果有人链接到所有流行压缩算法的概述,我会接受这个作为答案。

6 个答案:

答案 0 :(得分:6)

如果您尝试根据自己的结构知识自行压缩数据,则可能会获得更好的结果。

通用压缩算法只是将您的数据视为比特流。它们寻找常用的位序列,并用较短的字典索引替换它们。

但重复数据不会消失。重复的序列变得更短,但它仍然像以前一样经常重复。

据我了解,您有大量数据点

XXxxYYyy,大写字母非常均匀。因此将它们排除在外。

将列表重写为与此类似的内容:

XXYY // a header describing the common first and third byte for all the subsequent entries
xxyy // the remaining bytes, which vary
xxyy
xxyy
xxyy
...
XXYY // next unique combination of 1st and 3rd byte)
xxyy
xxyy
...

现在,很少变化的字节的每个组合仅列出一次,而不是为它们出现的每个条目重复。这相当于节省了大量空间。

基本上,在通过zlib运行之前,尝试自己删除重复数据。您可以更好地完成它,因为您有关于数据的其他知识。

另一种方法可能是,不是将这些坐标存储为绝对数字,而是将它们写为增量,选择的某些位置的相对偏差尽可能接近所有条目。您的增量将是较小的数字,可以使用较少的位来存储。

答案 1 :(得分:2)

不是特定于您的数据,但如果可以,我建议您检查7zip而不是zlib。我用这个看到了非常好的压缩比。

http://www.7-zip.org/

答案 2 :(得分:0)

通过某种接近度量对点进行排序,使得相邻点之间的平均距离很小。然后存储相邻点之间的差异。

如果你设法对点进行排序以便在x和y轴上的大多数差异都是正的,你可能会做得更好,但我不能肯定地说。

作为zlib的替代方案,当概率分布偏向小数时,一系列压缩技术效果很好universal codes。他们必须针对签名号码进行调整(编码abs(x)<<1 + (x < 0 ? 1 : 0))。

答案 3 :(得分:0)

在没有看到数据及其确切分布的情况下,我无法确定最佳方法是什么,但我建议您使用一个字节开始每组1-4条记录,其中8位表示以下内容: / p>

0-1应从先前记录借用的ID的字节数 2-4位置记录格式 6-7使用相同“模式”字节的后续记录数

每个位置记录可以以八种方式之一存储;除000之外的所有类型都使用签名位移。位代码后面的数字是位置记录的大小。

000 - 8 - 两个完整的四字节位置 001 - 3 - X和Y的12位 010 - 2 - 十位X和六位Y. 011 - 2 - 六位X和十位Y. 100 - 4 - 两个16位符号位移 101 - 3 - 16位X和8位Y符号位移 110 - 3 - X的八位有符号位移; Y为16位 111 - 2 - 两个八位有符号位移

模式字节为零将存储适用于某个点的所有信息,而不引用任何先前的点,使用总共13个字节来存储12个字节的有用信息。其他模式字节将允许基于与先前记录的相似性来压缩记录。如果四个连续记录仅在ID的最后一位有所不同,并且X和Y都在前一记录的+/- 127之内,或者X在+/- 31之内,Y在+/- 511之内,或者X在+/- 511和Y在+/- 31之内,则所有四个记录可以以13个字节存储(平均每个3.25个字节(空间减少73%)。

可以使用“贪婪”算法进行压缩:检查记录以查看它必须在输出中使用的大小ID和XY,然后再抓取另外三个记录,直到发现其中一个记录不能使用所选尺寸“匹配”以前的记录,或者可以写得更小(请注意,如果第一个记录的X和Y位移都等于12,则XY将写入两个字节,但直到一个读取后续记录我不知道要使用三种双字节格式中的哪一种。

在设置格式之前,我建议您通过它运行数据。可能是小的调整(例如使用7 + 9或5 + 11位格式而不是6 + 10)将允许许多数据更好地打包。但是,唯一真正了解的方法是查看真实数据会发生什么。

答案 4 :(得分:0)

看起来Burrows–Wheeler transform可能对此问题有用。它有一种特殊的倾向,即将重复字节的运行放在一起,这可能使zlib压缩得更好。 This article建议我应该将除zlib之外的其他算法与BWT结合起来。

直观地说这听起来很昂贵,但是看一些源代码表明,反向BWT是O(N),数据传输次数为3次,空间开销适中,可能使我的目标平台(WinCE)足够快。假设采用普通的排序算法,正向变换大致为O(N log N)或稍微超过。

答案 5 :(得分:0)

您可能希望将两个列表写入压缩文件:NodeListLinkList。每个节点都有一个ID,x,y。每个链接都有一个FromNode和一个ToNode,以及一个中间xy值列表。您可能有一个带有false origin的头记录,并且具有相对于该值的节点xy值。

如果您的街道遵循城市网格,通过消除交叉点的重复坐标,这将提供最大的好处。

如果压缩不需要是无损的,则可以使用截断的增量来表示中间坐标。虽然有人提到了上述增量,但请记住,连接丢失可能会造成比形状损失更多的问题,如果使用截断的增量来表示道路的最后一个坐标会发生什么情况(通常是一个交叉点)。

同样,如果你的道路不在城市网格上,这可能不会给你带来太大的收获。

相关问题