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)
  • 将我的数组视为纯二进制数据,然后应用
我只实现了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中的第一个选项更合适。但它可能会得到进一步改进

  • 将坐标重新解释为16位整数
  • 沿希尔伯特曲线(或任何其他空间填充曲线)将点位置转换为距离
  • 对距离排序,然后应用增量编码(计算相邻距离的差异)
  • 根据压缩/速度偏好,(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
    
    我没有尝试哈夫曼编码。是一种类似于算术编码的方法。方法名称后的数字显示配置参数:对于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中找到它们