6

在我一直在处理的应用程序中,我必须通过套接字发送一个 256 x 256 矩阵。我正在为在集群上运行的海上系统模拟器开发可视化客户端,该矩阵是表示海洋表面当前状态的高度图。

这是一个实时应用程序,所以速度是必须的。而且,使用 256 x 256 的浮点矩阵,我必须每秒发送 256 KB 的数据,以满足 256 KB/秒的带宽要求。

这很多,至少对于我的应用程序而言。

所以,我的问题是,在通过套接字发送之前压缩这个矩阵有什么好的方法吗?而且,如果有这样的方法,我可以期望减少多少操作系统?

由于我的矩阵代表一个连续的表面,有损压缩方法对我来说不是问题。我最关心的是压缩率、压缩所花费的时间,以及最后是否已经为 C++ 实现了这种方法。

4

8 回答 8

5

如果您离岸足够远和/或处于平静的海面,那么破浪不太可能成为大问题。如果是这种情况,那么表面将非常连续,并且看起来很像 X 和 Y 中多个正弦/余弦波的叠加。

表面的二维 FFT 可能会给您一些见解。您也许可以将表面表示为带宽受限的 2-D FFT,并丢弃更高空间频率的数据。

于 2010-08-20T17:00:46.850 回答
2

首先:数字表示

如果我正确理解您的描述,我假设海高的物理范围是有限的(比如 -50.0 到 50 米的波浪),典型的IEEE 754-2008 32 位浮点(即floatC/C++)使用 8-它的指数位(范围为 -126 到 127),小数位为 23 位,符号位为 1 位。请注意,这是底数 2。

如果您的最小测量(或计算)方差是 1 毫米,0.001 米,那么您可以将浮点大小减少到至少 16 位。IEEE 754 确实定义了一个 16 位浮点值,用作交换格式。指数为 5 位,小数为 10 位,符号为 1 位。我相信这是合适的,并立即将您的要求降低到 128KB/s (1024Kbps)。

在我最初写这篇文章之后,我意识到如果你想要一个统一的表示,表示中的错误非常小(<= 2mm),然后转换为一个 16 位有符号整数,aunit代表 2mm 的物理高度。这样您就可以获得分辨率为 2 毫米的统一表示,其值范围从 -32768(== -65536 毫米或大约 -65 米,-200 英尺)到 32767(== 65534 毫米或大约 65.5 米)。

这是一个非常简单的替代表示,基于以下简单假设:a) 值的有效范围为 +/- 65.5 米,并且 2mm 分辨率对于传输是可以接受的。

二:修改(过滤)数据

我不知道类似于 JPEG 压缩中使用的离散余弦变换(DCT) 是否可以用作有损压缩技术。基本上,这是对数据进行量化,以便平滑几乎相等的相邻值,从而可以通过无损压缩方法更好地压缩它们。

三:传统无损压缩

否则,相当快速的无损压缩技术,例如基于 Lempel-Ziv 的方法(LZ、LZH、LZW 等),也许还有快速LZO方法。

于 2010-08-20T18:03:29.643 回答
1

如果我没听错的话,表面会每秒测量一次。所以如果一秒内的变化不是很大,何不把数据当作视频,试试视频压缩算法。视频压缩还考虑了运动补偿。在算法的其他部分中,运动补偿对于高视频压缩率很重要。

于 2010-08-20T20:57:35.997 回答
1

首先,查看您的数据。你真的需要在这些浮点数中发送多少位信息?尝试切掉最低有效位,看看它是否足够准确。接下来从基本的无损算法开始。通过 LZ、无损方法(LZ78、LZW、...)对其进行压缩,获得具有快速解压缩速度的基线无损比率。然后尝试 BZip 之类的可能更好的压缩方法和更慢的解压缩。你现在有了无损限制。现在尝试一些有损算法。JPEG 等具有可调的有损率,并且仍然非常快速地解压缩。最后,添加一些过滤器。通过沿 X 或 Y 轴的简单差分传递,您的数据可能会很好地压缩(或尝试两者并将结果保存为 1 位。)这应该使您的数据更加可压缩。

总而言之,我猜你至少可以得到 x3 的当前带宽无损和 x10 的一点点损失。

于 2010-08-20T17:17:46.310 回答
1

好吧,矩阵只是一个二维信号。所以有很多不同的压缩方法。我会首先尝试简单的解决方案:在没有容器的情况下进行充气/放气(基本上是 Zip,没有 Zip)。http://en.wikipedia.org/wiki/DEFLATE 压缩级别取决于数据,所以我不能说,你必须自己尝试。

否则,更聪明的方法是只发送更改。如果您有权访问服务器端代码,则只需发送每秒更改的高度图的几个字节。这将是理想的解决方案,如果您愿意,您甚至可以使用 deflater 压缩更改的字节。

于 2010-08-20T16:59:56.483 回答
1

首先,我想知道您是否可以将基本编码从 32 位浮点更改为某种定点。假设您的值都在一个相当特定的范围内(这似乎很可能),这可能足以将您的带宽减少一半。根据所需的范围(和精度),您可能很想表示一个指数值,因此您正在捕捉一个相当不错的范围广泛的数量级概念,但小的差异大多被忽略。

我猜你不会(可能)期望从一个样本到下一个样本会有巨大的高度变化,并且(猜测)你可能会经常看到跨越多个样本的斜坡。

如果是这种情况,预测性增量压缩可能会很好地工作。基本思想是,对于每个(非边缘)点,您根据周围点预测该点的值,然后仅编码预测值与该点实际值之间的差异。根据您可能损失多少精度,您很可能能够将该增量编码为单个字节(或者甚至每个字节两个)。

完成此操作后,您可以考虑使用 Huffman 压缩甚至算术压缩,但其中任何一种都会大大减慢您的压缩速度。

于 2010-08-20T17:08:45.430 回答
0

我会尝试以下方法:

由于预计每秒的高度变化非常小,请尝试发送 2 次连续传输之间的高度差异。将这些数字与 10^n 相乘,这样我们就不必将它们作为浮点数发送,而是以整数形式发送。接下来,使用零压缩编码(请 google 为它),它可以显着减少要发送的字节数。之后,使用一些压缩算法来打包这些字节。

我认为它可以减少大约 50%(除非差异大到足以每个使用 3-4 个字节)。

于 2010-08-20T17:22:16.923 回答
-1

Well first off, how many levels of height do you need? What's the maximum difference in height from wave peak to trough? I bet you could represent it with only 256 or 65536 possible height values which immediately cuts your data to 1/2 or 1/4 without you having to modify your data structure. You can send the min/max values as floats as well each update, so the 256 levels are always used fully to get the most accuracy possible... as the sea gets rougher you lose accuracy.

You can also save an image of 256x256 using standard image algorithms. You've not quite got a standard format bitmap cut could treat it as a grayscale - if each vertex V is scaled to a value 0-255, you can build a color (V,V,V) and for free use a JPG library that already exists. Or you can probably find a DDS file format that has a single channel of 8/16/32-bit data too.

The first part of this I did in the past, successfully. The 2nd part, I'd be keen to avoid writing your own algorithm but get your data in a form it can use existing libraries, like D3DX for example.

于 2010-08-23T16:57:32.097 回答