使用ImageMagick合成预乘图像

3

我有两张图片。一张是没有透明度的背景图像。另一张是白色云朵。云朵图像的alpha与黑色混合过。当我把它们组合在一起时,白色云层中会有黑色,因此看起来是灰色而不是应该是白色。我的做法是:

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
并且按照相同的顺序作为JPG文件在您的浏览器中查看: https://istack.dev59.com/tssTs.webp https://istack.dev59.com/mrDvh.webp https://istack.dev59.com/SeOf0.webp https://istack.dev59.com/rHZ7a.webp 我尝试了提供的所有模式,但是没有一个可以创建与After Effects相同的结果。
5个回答

1

如果您展示图片,将会更容易理解,但是请尝试在命令中添加-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

enter image description here

我认为 AtopDissolveSrcAtopSrcOver 可能会对你有用,但请查看全尺寸并决定哪个最适合你的需求。

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

1
不,但我非常感激你的努力。混合模式与预乘没有任何关系。在预乘之前,RGB不正确,没有任何混合模式可以解决这个问题。我进行了一些研究,发现Imagemagick和Graphicsmagick都不支持预乘alpha通道。这真的很令人恼火,因为大多数专业的2D和3D软件默认产生预乘图像。所有专业的合成软件包也都假定有预乘alpha通道,包括After Effects、Fusion、Nuke、Harmony等等。但Imagemagick并不提供这个功能。为什么呢?我会去问问他们的列表。 - whereisalext
好的,谢谢您的反馈。如果有一个可以执行/撤销预乘的公式,那么可以尝试在ImageMagick中使用-fx运算符或模块来实现它,所以如果您找到更多信息并愿意稍后添加注释或链接,可能可以解决这个问题。 - Mark Setchell

1

常规的 alpha 混合操作(Duff-Porter Over operator)执行以下操作:

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

当 alpha 被预乘时,它只是意味着源的颜色已经是 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

以下是输出结果:

This is the output

供参考,这里有几张中间图像:

  • 云的 alpha 通道

The alpha channel of the cloud

  • 背景与云的alpha值的倒数相乘

Background multiplied with the inverse alpha of the cloud

将其分成几个步骤的好处在于,如果您的图像具有错误的 alpha 通道或其他问题,那么调试起来会更容易。

这仍然是个问题让人感到疯狂,但是有一个好的解决方案! - whereisalext

1

我知道你要求一个imagemagick的解决方案,但如果其他库也可以,libvips支持带有预乘alpha的porter-duff合成。

我为您的云图像制作了一个PNG文件(在浏览器中看起来会很奇怪,因为alpha是预乘的):

enter image description here

然后运行:

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

制作:

enter image description here

我认为这与后期效果相匹配。

这里是合成运算符的文档:

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


0

这里是一个可以实现你想要的功能的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 从预乘 alpha 转换为“正常”格式。max() 运算符是一种特殊情况,以避免除以零。
  2. +swap 命令:使 bg.tga 成为第一张图像,修订后的 whitecloud.tga 成为第二张图像。
  3. 合成这两个常规的、非预乘的图像。
  4. -fx 命令 #2:取得结果,并返回到预乘 alpha 格式。

这与 After Effects 完全相同。

请注意,如我所写,它仅适用于不透明的 bg.tga。你需要做一些额外的工作来处理透明背景图像。


我尝试了这个,但它产生了一个带有黑色背景的灰色云。bg.tga是不透明的,所以我不确定我是否漏掉了什么... - endavid

-1
如果你想要复制After Effects的效果,那么我认为在ImageMagick中你需要做以下操作 -- 使用云朵作为遮罩,将背景图像与白色图像合成:
convert bg.tga \( -clone 0 -fill white -colorize 100 \) whitecloud.tga -compose over -composite cloud_blue.tga

enter image description here

我已经发布了一个JPG结果,但我的.tga结果是相同的。


这个结果不正确。如果你看到在问题中发布的AfterEffects的结果,你会发现云朵比你的略微灰一些。你所描述的并不是他们想要的。我在我的答案中用数学方式描述了它。 - endavid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接