Композиция предварительно умноженных изображений с использованием ImageMagick

У меня есть два изображения. Одним из них является фон без альфа. Другое белое облако. Альфа-изображение облака предварительно умножается на черный. Когда я объединяю их, в белом облаке есть черное, поэтому оно выглядит серым, а не белым, как должно. Я делаю:

convert -gravity Center bg.tga whitecloud.tga -composite comp.tga

Есть ли способ сложения предварительно умноженных изображений в ImageMagick, или изображение должно быть без предварительного умножения? Можно ли сделать предварительно умноженное изображение без предварительного умножения с помощью ImageMagick?

Обновить:
Хорошо, вот изображения в формате TGA для скачивания:

http://acatysmoof.com/posting/problems/imagemagick/premultiplication/bg.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/whitecloud.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/aftereffects.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/imagemagick.tga

и в том же порядке, что и jpgs для просмотра в вашем браузере:

bg.jpgwhitecloud.jpgaftereffects.jpgimagemagick.jpg

Я перепробовал все предоставленные режимы, но ни один из них не дал того же результата, что и After Effects.

5 ответов

Решение

Было бы проще, если бы вы показали свои изображения, но попробуйте добавить -compose lighten до -composite в вашей команде, вот так:

convert a.tga b.tga -compose lighten -composite out.tga

По сути, это заставит ImageMagick выбрать более светлый пиксель двух изображений в каждой точке.

Если это не сработает, попробуйте другие режимы наложения

for b in $(identify -list compose); do 
   convert -label "$b" bg.tga whitecloud.tga -compose $b -composite miff:- 
done | montage - -tile 5x out.png

Я вроде думаю Atop, Dissolve, SrcAtop а также SrcOver может быть ваши друзья, но посмотрите в натуральную величину и посмотрите, что плавает на вашей лодке. Это было бы

convert a.tga b.tga -compose Atop -composite out.tga

Обычная операция альфа-смешивания ( оператор Duff-Porter Over ) делает это:

      output.rgb = src.rgb * src.a + (1-src.a) * dst.rgb

Когда альфа предварительно умножается, это просто означает, что цвет источника ужеsrc.rgb * src.a, поэтому вам нужно только добавить(1-src.a) * dst.rgb.

В шейдере это очень быстро. Но в ImageMagick это, похоже, сбивает с толку, потому что, похоже, нет прямого оператора, который бы это делал.

Однако вы можете вычислить его, если разобьете его на несколько шагов:

      # extract alpha channel from cloud
convert whitecloud.tga -auto-orient -alpha extract -colorspace gray alpha.png
# invert alpha channel
convert alpha.jpg -negate alpha-inv.png
# (1-cloud.a) * bg.rgb
composite -compose Multiply alpha-inv.png bg.tga bg-pre.png
# remove alpha channel to obtain cloud.rgb
convert whitecloud.tga -auto-orient -alpha off whitecloud-rgb.png
# cloud.rgb * cloud.a + (1-cloud.a) * bg.rgb
composite -compose plus whitecloud-rgb.png bg-pre.png output.png

Вот результат:

Для справки, вот пара промежуточных изображений:

  • альфа-канал облака

  • фон, умноженный на обратную альфу облака

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

Я понимаю, что вы просили решение imagemagick, но если возможны другие библиотеки, libvips поддерживает композицию porter-duff с предварительно умноженной альфой.

Я создал PNG для вашего изображения облака (в браузере это будет выглядеть странно, поскольку альфа умножается заранее):

Затем побежал:

      $ vips composite2 bg.jpg white-cloud.png x.png over --premultiplied

Делать:

Что, я думаю, соответствует последствиям.

Вот документы для составного оператора:

https://www.libvips.org/API/current/libvips-conversion.html#vips-composite

Вот команда Imagemagick, которая делает то, что вы хотите:

convert -gravity Center whitecloud.tga -fx "u/max(u.a, 1/255)" bg.tga +swap -composite -fx "u*u.a" comp.tga

Что тут происходит?

  1. -fxкоманда №1: преобразовать whitecloud.tga из предварительно умноженного альфа-канала в "нормальный". В max() Оператор - это особый случай, позволяющий избежать деления на ноль.
  2. +swap команда: Сделать bg.tga первое изображение и исправленное whitecloud.tga секунда.
  3. -composite эти два обычных изображения без предварительного умножения.
  4. -fx команда №2: взять результат и вернуться к предварительно умноженному альфа-формату.

Это дает точно такой же результат, как и After Effects.

Обратите внимание, что, как я писал, это работает только для непрозрачных bg.tga. Вам нужно будет проделать дополнительную работу, чтобы обработать прозрачное фоновое изображение.

Если вы хотите продублировать результат After Effects, то я считаю, что вы хотите сделать в ImageMagick следующее - объединить фоновое изображение с белым изображением, используя облако в качестве маски:

       convert bg.tga \( -clone 0 -fill white -colorize 100 \) whitecloud.tga -compose over -composite cloud_blue.tga

Я опубликовал результат в формате JPG, но мой результат в формате.tga такой же.

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