压缩2D点集-想法

Compression of a 2D point set - ideas?

本文关键字:想法 点集 2D 压缩      更新时间:2023-10-16

我在一个数组中存储了一组2D点我需要尽可能多地压缩它最好速度快,但不要破坏交易,压缩率是目标。规则是:

  • a点=32位结构,存储为(x,y),每个坐标2个字节
  • 坐标=包含8位整数部分和8位小数部分的"浮点">

特殊属性:

  • 我可以根据自己的意愿更改点的顺序
  • 我得到的是x和y的整数部分的顺序,也许我可以利用它,但分数部分从我看到的情况来看是随机的
  • 我接收的数组是连续的(从内存的角度来看)

到目前为止我研究的内容:

  • 将它们视为纯整数(32位),对它们进行排序(顺序由我选择),然后像这个问题中那样压缩
  • 将我的数组视为一个纯字符串,然后应用带有游程编码的Burrows-Wheeler变换(BWT)或Huffman
  • 将我的数组视为纯二进制数据,然后应用LZW

我只实现了Huffman和BWT,但它们都没有给我一个好的压缩比(或者使用我的数据集的主要属性)。我今天要试试第一种选择。

我相信还有更好的主意。你有吗你有没有遇到类似的事情,并实现了一些非常好的东西?

数据集示例,十六进制:

00 0A 00 77 00 55 00 80 00 2B 00 B9 00 7A 00 5B 
00 F6 00 76 00 B4 00 25 00 47 00 D3 00 F6 00 7D
...
01 05 00 A9 01 B8 00 10 01 4F 00 6A 01 E6 00 DF
01 1F 00 F0 01 BE 00 C3 01 6C 00 87 01 CE 00 44
...
...
15 06 03 F4 15 1E 03 29 15 35 03 10 15 B9 03 22
15 67 03 73 15 EF 03 5C 15 29 03 B8 15 4C 03 2F
...

其中例如粒子15 67 03 73(最后一行)表示在x=15和67/256、y=3和73/256处的粒子。正如你所看到的,数据有点有序,但小数部分完全混乱。

OP的第一个选项更合适。但它可能会进一步改进。

  1. 将坐标重新解释为16位整数
  2. 将点位置转换为沿着希尔伯特曲线(或任何其他空间填充曲线)的距离
  3. 对距离进行排序,然后应用delta编码(计算相邻距离的差异)
  4. 根据压缩/速度偏好,(a)使用Elias或Golomb代码(最快),(b)使用霍夫曼编码,或(c)使用算术编码(最佳压缩率)

如果点的分布有某种模式,您可以尝试更先进的压缩器用于步骤#4:LZ*、BWT或PPM。


以下是步骤4中使用的方法的实验比较结果。假设最坏的情况是:点在00.00..FF.FF范围内随机均匀分布(因此唯一的压缩可能性是丢失有关其排序的信息)。所有结果均针对250000点进行计算:

method        compressed size
------        ---------------
Uncompressed: 1000000
Elias4:        522989
Elias3:        495371
Elias2:        505376
Golomb12:      479802
Golomb13:      472238
Golomb14:      479431
Golomb15:      501422
FSE1:          455367
FSE2:          454120
FSE3:          453862

我没有尝试霍夫曼编码。FSE是一种类似于算术编码的方法。方法名称后的数字显示配置参数:对于Elias编码-使用多少比特来编码每个数字的比特长度,对于Golomb编码-有多少最低有效比特未压缩,对于FSE-有多少最高有效比特被压缩(以及比特长度)。

所有结果均由以下来源产生:http://ideone.com/ulmPzO

交错表示每个点的X和Y坐标的位,进行排序和压缩。

例如,如果点(X,Y)由两个16位数字表示

(X15X14X13X12X119X8X7X6X-5X-4X-3X_2X.1>15Y14Y=12Y-11Y/sub>10Y9Y_8Y.7Y6Y=sub>5Y-4Y3Y1Y0)

将其转换为以下32位数字:

X15Y115X14Y14X13X12X11Y11X10Y10X9Y9Y7X6Y6X5X-4Y-3Y=3X-2Y/sub>X<2X/sub>X<1Y.1X0Y0

这将利用数据中可能出现的任何聚类,因为物理上接近的点将出现在排序列表上的接近位置,并且它们的表示共享它们的头位。

更新:点是让近点在近位置排序。如果你混合X和Y位,你就会得到它,产生32位整数的长序列,这些整数的头位值相同。如果你做delta,你会得到更小的值,如果你只在X上排序,然后在Y上排序(反之亦然)。

问题是,你可以把它看作一个k-d树,每一位都划分空间(左/右或上/下)。对于第一个层次,你可以压缩,然后只说一侧有多少元素,直到你得到只有几个元素的极点,这些元素可以通过显式地陈述剩下的几个位来表示。为了获得最佳压缩效果,您必须使用算术编码。