C++ 二维点集的压缩-想法?
我有一组二维点存储在一个数组中我需要尽可能多地压缩它。最好是快速压缩,但不能破坏交易,压缩率是目标。这些规则是:C++ 二维点集的压缩-想法?,c++,arrays,algorithm,compression,C++,Arrays,Algorithm,Compression,我有一组二维点存储在一个数组中我需要尽可能多地压缩它。最好是快速压缩,但不能破坏交易,压缩率是目标。这些规则是: a点=32位结构,存储为(x,y),每个坐标2字节 坐标=8位整数部分、8位小数部分的“浮点” 特殊属性: 我可以根据自己的意愿更改积分顺序 我给点的顺序是x和y的整数部分,也许我可以利用这一点,但从我所看到的来看,分数部分几乎是随机的 我接收的数组是连续的(从内存的角度看) 到目前为止我所研究的: 考虑它们是纯整数(32位),对它们进行排序(顺序由我选择),然后按中所示进
- a点=32位结构,存储为(x,y),每个坐标2字节
- 坐标=8位整数部分、8位小数部分的“浮点”
- 我可以根据自己的意愿更改积分顺序
- 我给点的顺序是x和y的整数部分,也许我可以利用这一点,但从我所看到的来看,分数部分几乎是随机的
- 我接收的数组是连续的(从内存的角度看)
- 考虑它们是纯整数(32位),对它们进行排序(顺序由我选择),然后按中所示进行压缩
- 将我的数组视为普通字符字符串,然后使用或应用(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中的第一个选项更合适。但它可能会得到进一步改进
下面是第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
我没有尝试哈夫曼编码。是一种类似于算术编码的方法。方法名称后的数字显示配置参数:对于Elias编码-有多少位用于编码每个数字的位长度,对于Golomb编码-有多少最低有效位未压缩,对于FSE-有多少最高有效位被压缩(连同位长度)
所有结果都是由该源生成的:交错表示每个点的X和Y坐标的位,排序并压缩 例如,如果点(X,Y)由两个16位数字表示 (X15x14x13x12x12x11x1x9x8x7x6x5x4x3x2x1x0,Y15Y14Y13Y12Y11Y10Y9Y8Y7Y6Y5Y4Y3Y2Y1Y0) 将其转换为以下32位数字: X15Y15X14Y14X13X12X11Y12X11X10X9Y9X8Y8X7Y7X6Y6X5Y5X4Y4X3Y3X2Y2x1Y0Y0 这将利用数据中可能出现的任何聚类,因为物理上接近的点将出现在排序列表中的近位置,并且它们的表示共享它们的头位 更新:要点是在近位置对近点进行排序。如果你混合X和Y位,你会得到它,结果是32位整数的长序列,它的头位中的值相同。如果你接着做delta,你将得到更小的值,如果你只是在X上排序,然后在Y上排序(反之亦然)
问题是,你可以把它看作是一棵K-D树,每一个空间都有分区(左/右或上/下)。对于第一个级别,您可以压缩,然后只说一侧有多少个元素,直到您用几个元素到达极点,这些元素可以通过明确说明剩余的几个位来表示。为了获得最佳的压缩效果,您必须使用算术编码。这个“浮点”实际上是一个“固定的”。不管怎样,你的数据集是什么样子的?是的,它是某种固定小数。分数部分在我看来是随机的,但整数部分是按顺序排列的(先是x,然后是y)。我在问题上加了一个例子,我会分别做整数和小数部分。1.您可以尝试RLE(运行长度编码),并可能是整数部分的哈夫曼编码。2.分数部分很棘手,我只想尝试Hufman的方法。除非你对分布有所了解,否则最好的算法是对多集进行排序和反排序。你可以尝试交错x和y位,排序,增量码。(我可能会尝试xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyx。)你能详细介绍一下希尔伯特曲线吗?希尔伯特曲线将你的点从二维空间映射到一维空间,同时保留局部性(这意味着第3步后的距离增量往往较小,因此可以更好地压缩)。IMHO-Hilbert曲线比其他空间填充曲线更好地保留局部性,尽管与其他曲线相比,它需要稍微复杂一些的实现(salva提出的想法与Z-curve相同,Z-curve具有最简单的实现)。在将坐标映射到希尔伯特曲线之前,您可以先将点所占据的面积(可能某些异常值除外)映射到希尔伯特曲线所占据的平方面积。这意味着可能会增大两个坐标的比例,以便将高度/宽度扩展到2的下一次幂。将坐标映射到距离和背面的算法是众所周知的,例如,您可以在.Hilbert曲线、Z曲线或其他空间填充曲线w中找到它们