压缩2D点集 - 想法?

时间:2015-04-20 10:41:26

标签: c++ arrays algorithm compression

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

  • a point = 32位结构,存储为(x,y),每个坐标为2个字节
  • 坐标= a" float" 8位整数部分,8位小数部分

特殊属性:

  • 我可以按照我认为合适的方式更改积分的顺序
  • 我按照x和y的整数部分的顺序给出了点数,也许我可以利用它,但是从我看到的部分是非常随机的
  • 我收到的数组是连续的(从内存的角度来看)

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

  • 将它们视为普通整数(32位),对它们进行排序(我可以选择该顺序),然​​后按this question中的方式对其进行压缩。
  • 将我的数组视为普通字符串字符串,然后将a Burrows-Wheeler transform(BWT)应用于run-length encodingHuffman
  • 将我的数组视为纯二进制数据,然后应用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的粒子。如您所见,数据有些有序,但小数部分完全混乱。

2 个答案:

答案 0 :(得分:3)

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

  1. 将坐标重新解释为16位整数。
  2. 将点位置沿希尔伯特曲线(或任何其他空间填充曲线)转换为距离。
  3. 对距离进行排序,然后应用delta编码(计算相邻距离的差异)。
  4. 根据压缩/速度偏好,(a)使用Elias或Golomb代码(最快),(b)使用霍夫曼编码,或(c)使用算术编码(最佳压缩率)。
  5. 如果点分布中存在某种模式,您可以尝试使用更高级的压缩器来执行步骤#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

答案 1 :(得分:1)

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

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

(X <子> 15 X <子> 14 X <子> 13 X <子> 12 X <子> 11 X <子> 10 X <子> 9 X <子> 8 X <子> 7 X <子> 6 X <子> 5 < / sub> X 4 X 3 X 2 X 1 X 0 ,Y <子> 15 ý<子> 14 ý<子> 13 ý<子> 12 ý<子> 11 ý<子> 10 < /子>ý<子> 9 ý<子> 8 ý<子> 7 ý<子> 6 ý<子> 5 ÿ<子> 4 ý<子> 3 ý<子> 2 ý<子> 1 ý<子> 0

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

X <子> 15 ý<子> 15 X <子> 14 ý<子> 14 X <子> 13 ÿ<子> 13 X <子> 12 ý<子> 12 X <子> 11 ý<子> 11 X <子> 10 ÿ<子> 10 X <子> 9 ý<子> 9 X <子> 8 ý<子> 8 X <子> 7 ý<子> 7 X <子> 6 ý<子> 6 X <子> 5 ý<子> 5 X <子> 4 ý<子> 4 X <子> 3 ý<子> 3 X <子> 2 ý<子> 2 X <子> 1 ý<子> 1 X <子> 0 ý<子> 0

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

更新:关键点是近点位置在近位置排序。如果混合X和Y位,就可以得到它,导致32位整数的长序列,其头位中的值相同。如果你然后做增量,你将有更小的值,如果你只是在X上然后在Y上排序(反之亦然)。

然后,你可以将它视为k-d树,每一位都划分空间(左/右或上/下)。对于第一级,你可以压缩然后只是说一边有多少元素,直到你到达极点只有几个元素,可以通过明确说明剩余的几个位来表示。为了获得最佳压缩效果,您必须使用算术编码。