图像的差异/补丁

发布于 2024-11-18 20:15:53 字数 361 浏览 3 评论 0原文

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

现在,我得到的是一组 BufferedImage ,因此与文本文件类似,我基本上只想比较它们并发送补丁。 然而,我以前从未真正处理过图像,所以如果我这样做,那将是相当蹩脚的。

那么,实现这样的事情的最佳方法是什么,或者是否已经有一个很好的实现这样的事情?

我想将图像存储在字节数组中并进行二进制比较它们不会非常有效。

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

I'm writing a project where I need to transfer a set of similar images over the net. To speed things up, I thought about doing what most movie codecs do. having keyframes and then just send the changes.

Now, what I got is a set of BufferedImages so in an analogy to text file I basically just want to diff them and send the patch.
However I've never really worked with images before so if I will do this, it will be rather crappy.

So, what's the best way of implementing something like this, or is there already an good implementation for something like this?

I guess storing the images in a byte array and binary diff them wont be very effective.

Edit: I need to stream this the images.
Edit2: It's not so much about the specifics of the implementation it's more: what is the most efficient idea for an algorithm. Like only work with 5px chunks and not ignore a px if it has only changed so little the eye won't notice (I can live with some quality loss)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

少女七分熟 2024-11-25 20:15:54

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

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

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

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

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

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

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

A simplistic approach would be to do the equivalent of an XOR operation on the two images. This will reveal the pixels that are identical (will be zero) and the pixels that have changed (non-zero).

If you don't care for nearly imperceptible differences then alternatively, use a 'subtract' blend then right-shift to discard one or two bits difference.

You could then calculate the bounds (maybe a simple rectangle) and only transmit the delta. The delta will likely contain a lot of zeroes or at most bytes with few rightmost bits of difference—i.e., it will have low 'entropy' which means it should theoretically be highly compressible using contemporary compression algorithms.

On the receiving end, the reverse process is just as simple. Given the delta and the bounding box, decompress the delta, then apply it (XOR, or left-shift then add) to the affected region of the previous/existing image.

For a more sophisticated, lossless approach, look into how animated GIF/PNGs are animated and what algorithms are used to compute/encode the delta information between frames. See, for example, What's the best way to make an animated GIF using an algorithm?

For an even more sophisticated approach, when dealing with real-world imagery and if you're willing to go the lossy route—then you already hinted at it. Look at how video codecs encode/transmit frames, for example MPEG Video Encoding.

It goes without saying that because there's a tradeoff between complexity (of the encoding/decoding process) and the reduction in size of transmitted data at some point you'll have to decide whether the added overhead in computation on either end is worth the savings in transmission.

伏妖词 2024-11-25 20:15:54

您可以使用 getRGB(int x, int y) 迭代 BufferedImage 的所有像素。

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
        }
    }

}

You can iterate over all the pixels of a BufferedImage using 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
        }
    }

}
花期渐远 2024-11-25 20:15:54

我想到了一个主意,其实这很简单。逐一比较像素,

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

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

stackoverflow 上说您需要至少 10 个声誉才能发布图片。所以我只能在这里贴出图片地址。

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

I got an idea, actually this is very simple. Compare pixel one by one

If pixel equal, then save as RGBA(0, 0, 0, 0). Then store the diff as PNG.

This is the demo result. the diff is very small.

The stackoverflow say you need at least 10 reputation to post images. So I can only post image address here.

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

幻梦 2024-11-25 20:15:54

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

Depending on the amount of work you want to invest I would suggest a rather easy solution, save those images as bitmaps and let 7z compress them. Then send the archive.

彩扇题诗 2024-11-25 20:15:54

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

If you don't mind some decrease in quality and want a really efficient solution in terms of bandwidth without a lot of manual work for you, you could also just encode you images with a real movie codec. Especially you have a GPU to offload the computation that approach can also be very efficient in terms of computational effort.

千と千尋 2024-11-25 20:15:54

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

为了加快速度,我考虑做...

这不是一个要求,只是一个“如果...岂不是很酷”。以当今的网络速度,即使传输几百兆数据也可以在一分钟内完成。

Your time is probably better spent developing the app, and then evaluating performance improvements if it is a problem. I am guessing this whole thing will be YAGNI.

To speed things up, I thought about doing...

This isn't a requirement, just a 'wouldn't it be cool if...'. With network speeds of today, transferring even a couple hundred megs can be done in less than a minute.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文