diff/patch для изображений

Я пишу проект, в котором мне нужно передать набор похожих изображений по сети. Чтобы ускорить процесс, я подумал о том, чтобы делать то, что делают большинство кодеков фильмов. имея ключевые кадры, а затем просто отправить изменения.

Теперь, что я получил, это набор BufferedImageТак что в аналогии с текстовым файлом я в основном просто хочу проверить их и отправить патч. Однако я никогда раньше не работал с изображениями, поэтому, если я это сделаю, это будет довольно глупо.

Итак, каков наилучший способ реализации чего-то подобного или уже есть хорошая реализация для чего-то подобного?

Я предполагаю, что хранение изображений в байтовом массиве и бинарном diff их не будет очень эффективным.

Изменить: мне нужно для потоковой передачи этого изображения. Edit2: Дело не столько в специфике реализации, сколько в том, что является наиболее эффективной идеей для алгоритма. Как работать только с 5px чанками и не игнорировать пиксель, если он только так изменился, что глаз не заметит (я могу жить с некоторой потерей качества)

6 ответов

Решение

Упрощенным подходом было бы сделать эквивалент операции XOR на двух изображениях. Это покажет пиксели, которые идентичны (будет ноль) и пиксели, которые изменились (не ноль).

Если вы не заботитесь о почти незаметных различиях, то альтернативно, используйте смесь "вычитания", а затем сдвиг вправо, чтобы отбросить разницу в один или два бита.

Затем вы можете рассчитать границы (возможно, простой прямоугольник) и передать только дельту. Дельта, скорее всего, будет содержать множество нулей или не более байтов с несколькими правыми битами разницы, т. Е. Она будет иметь низкую "энтропию", что означает, что она теоретически должна быть в высокой степени сжимаемой с использованием современных алгоритмов сжатия.

На приемном конце обратный процесс такой же простой. Учитывая дельту и ограничивающий прямоугольник, распакуйте дельту, затем примените ее (XOR, или добавление влево, затем добавьте) к затронутой области предыдущего / существующего изображения.

Для более изощренного подхода без потерь посмотрите, как анимируются GIF/PNG и какие алгоритмы используются для вычисления / кодирования дельта-информации между кадрами. Посмотрите, например, каков лучший способ сделать анимированный GIF-файл с использованием алгоритма?

Для еще более сложного подхода, когда речь идет о реальных изображениях и если вы готовы пойти по пути с потерями, - вы уже намекали на это. Посмотрите, как видеокодеки кодируют / передают кадры, например, MPEG Video Encoding.

Само собой разумеется, что, поскольку существует компромисс между сложностью (процесса кодирования / декодирования) и уменьшением размера передаваемых данных, в какой-то момент вам придется решить, стоит ли дополнительная накладная нагрузка в вычислениях на любом конце сэкономить на коробка передач.

Вы можете перебрать все пиксели 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
        }
    }

}

У меня есть идея, на самом деле это очень просто. Сравните пиксель один за другим

Если пиксель равен, то сохранить как RGBA(0, 0, 0, 0). Затем сохраните разницу как PNG.

Это демонстрационный результат. разница очень маленькая.

Скажем, стекопоток you need at least 10 reputation to post images, Так что я могу разместить здесь только адрес изображения.

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

Если вы не возражаете против некоторого снижения качества и хотите действительно эффективное решение с точки зрения пропускной способности без большой ручной работы, вы также можете просто кодировать свои изображения с помощью реального кодека фильма. Особенно у вас есть графический процессор для разгрузки вычислений, который также может быть очень эффективным с точки зрения вычислительных усилий.

В зависимости от объема работы, которую вы хотите вложить, я бы предложил довольно простое решение, сохранив эти изображения как растровые изображения и позвольте 7z сжать их. Затем отправьте архив.

Ваше время, вероятно, лучше потратить на разработку приложения, а затем на оценку улучшения производительности, если это проблема. Я предполагаю, что все это будет ЯГНИ.

Чтобы ускорить процесс, я подумал о том, чтобы сделать...

Это не требование, просто "не было бы круто, если...". При современных скоростях сети передача даже нескольких сотен мегабайт может быть осуществлена ​​менее чем за минуту.

Другие вопросы по тегам