8

我正在编写一个项目,我需要通过网络传输一组相似的图像。为了加快速度,我考虑做大多数电影编解码器所做的事情。拥有关键帧,然后发送更改。

现在,我得到的是一组BufferedImages,因此类似于文本文件,我基本上只想区分它们并发送补丁。但是,我以前从未真正使用过图像,所以如果我这样做,那将是相当糟糕的。

那么,实现这样的事情的最佳方式是什么,或者已经有这样的事情的良好实现?

我猜想将图像存储在字节数组中并且二进制差异它们不会非常有效。

编辑:我需要流式传输这些图像。Edit2:与其说是实现的细节,不如说是:算法最有效的想法是什么。就像只使​​用 5px 块而不忽略 px,如果它的变化很小,眼睛不会注意到(我可以忍受一些质量损失)

4

6 回答 6

6

一种简单的方法是对两个图像进行等效的 XOR 操作。这将显示相​​同的像素(将为零)和已更改的像素(非零)。

如果您不关心几乎察觉不到的差异,那么或者,使用“减法”混合然后右移以丢弃一到两位差异。

然后,您可以计算边界(可能是一个简单的矩形)并仅传输增量。增量可能包含很多零或最多包含很少最右边差异位的字节 - 即,它将具有低“熵”,这意味着它理论上应该使用当代压缩算法高度可压缩。

在接收端,相反的过程同样简单。给定增量和边界框,解压缩增量,然后将其应用(异或,或左移然后相加)到先前/现有图像的受影响区域。

对于更复杂、无损的方法,请查看动画 GIF/PNG 的动画方式以及用于计算/编码帧之间的增量信息的算法。例如,请参阅使用算法制作动画 GIF 的最佳方法是什么?

对于更复杂的方法,在处理真实世界的图像时,如果你愿意走有损路线——那么你已经暗示过了。查看视频编解码器如何编码/传输帧,例如MPEG Video Encoding

不言而喻,因为在(编码/解码过程的)复杂性和传输数据大小的减少之间存在权衡,所以您必须决定在任一端增加的计算开销是否值得节省传送。

于 2011-08-19T03:47:45.580 回答
3

您可以使用 来遍历 BufferedImage 的所有像素getRGB(int x, int y)

for (int x = 0; x < img.getWidth(); ++x)
{
    for (int y = 0; y < img.getHeight(); ++y)
    {
        int oldARGB = oldImg.getRGB(x, y);
        int newARGB = img.getRGB(x, y);
        if (oldARGB != newARGB)
        {
            // handle the diffrence
        }
    }

}
于 2011-07-07T18:00:53.660 回答
2

我有一个想法,其实这很简单。逐个比较像素

如果像素相等,则另存为 RGBA(0, 0, 0, 0)。然后将差异存储为PNG。

这是演示结果。差异非常小。

stackoverflow 说you need at least 10 reputation to post images。所以我只能在这里发布图片地址。

http://oi61.tinypic.com/2vs5ifl.jpg

于 2014-12-22T10:18:59.457 回答
0

根据您要投入的工作量,我会建议一个相当简单的解决方案,将这些图像保存为位图并让 7z 压缩它们。然后发送存档。

于 2011-07-07T16:32:36.027 回答
0

如果您不介意质量下降,并且想要在带宽方面真正有效的解决方案而无需大量手动工作,您也可以使用真正的电影编解码器对图像进行编码。特别是你有一个 GPU 来卸载计算,这种方法在计算工作量方面也非常有效。

于 2016-07-08T22:25:27.717 回答
-2

您的时间最好花在开发应用程序上,然后在出现问题时评估性能改进。我猜这整件事将是 YAGNI。

为了加快速度,我想过做...

这不是一个要求,只是一个“如果……会不会很酷”。以今天的网络速度,甚至可以在不到一分钟的时间内完成几百兆的传输。

于 2011-08-18T22:58:46.537 回答