我的要求是透视将用户提交的图像旋转到预渲染的背景图像(实际上是视频中每帧的图像)。
最简单的方法是使用ImageMagick,我编写了一个非常粗糙的简单bash脚本来实现我需要的内容如下:
#!/bin/bash
# @author: neurosys
# @Description: Perspective transforms and projects an alpha image
# onto a background image.
if [ $# -ne 11 ]
then
echo 'Usage: ./map_image.sh background.jpg image.png output.jpg x1 y1 x2 y2 x3 y3 x4 y4';
exit;
fi
BG=$1
IMAGE=$2
DEST=$3
TEMP='temp.png'
BG_SIZE_W=$(convert $BG -print "%w\n" /dev/null)
BG_SIZE_H=$(convert $BG -print "%h\n" /dev/null)
IMAGE_W=$(convert $IMAGE -print "%w\n" /dev/null)
IMAGE_H=$(convert $IMAGE -print "%h\n" /dev/null)
X1=$4
Y1=$5
X2=$6
Y2=$7
X3=$8
Y3=$9
X4=${10}
Y4=${11}
OFFSET=15
TRANSFORM="$OFFSET,$OFFSET, $X1,$Y1 $(($IMAGE_W+$OFFSET)),$OFFSET $X2,$Y2 $OFFSET, $(($IMAGE_H+$OFFSET)) $X3,$Y3 $(($IMAGE_W+$OFFSET)), $(($IMAGE_H+$OFFSET)) $X4,$Y4"
echo "Transform matrix: $TRANSFORM"
convert $IMAGE -background transparent -extent $BG_SIZE_W\x$BG_SIZE_H-$OFFSET-$OFFSET $TEMP
convert $TEMP -background transparent -distort Perspective "$TRANSFORM" $TEMP
convert $BG $TEMP -composite $DEST
rm -f $TEMP
但是,大约需要4秒才能在我的计算机上生成所需的图像,如下所示:
[neuro@neuro-linux ~]$ time ./map_image.sh bg.png Hp-lovecraft.jpg output.jpg 494 108 579 120 494 183 576 196 && nomacs output.jpg
Transform matrix: 15,15, 494,108 195,15 579,120 15, 267 494,183 195, 267 576,196
real 0m3.852s
user 0m3.437s
sys 0m0.037s
[neuro@neuro-linux ~]$
我在上面的ImageMagick脚本中使用的操作顺序和参数可能不是最佳的。因此,非常欢迎任何达到我需要的意见或替代方案。
用于上述示例的图像是
我想知道是否有办法加速这么快,以便我可以在几秒钟内为一分钟长的视频(25 fps * 60秒)生成帧?
事实上,如果这种方法失败,我可能会专门为此编写OpenGL程序,我相信在硬件利用的情况下会更快。
有些偏离主题的注意事项:背景图像是在动画软件(3ds Max)中预呈现的。如果我求助于编写一个opengl渲染器,我可以从3ds Max导入网格和相机,这样做可以获得更好的透视和照明。
感谢。
修改
在ImageMagick论坛的帮助下,瓶颈在-extent的第一次转换中出现了,这是不必要的。
我最终将所有命令合并为一个:
convert image.png -background transparent +distort Perspective "1,1, 494,108 201,1 579,120 1, 201 494,183 201, 201 576,196" -compose DstOver -composite bg.png out.png
它在0.6秒内运行,但透明度不知何故不起作用,因此输出图像最终只是带有黑色背景的扭曲图像。
修改
ImageMagick论坛上的某个人写了一个非常快速和干净的脚本,将其缩短为0.13秒。
以下是链接,万一有人需要它: https://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=29495&p=132182#p132141
答案 0 :(得分:2)
尝试使用MPC格式作为$ TEMP而不是PNG。 MPC的编码速度要快得多。它设计用作临时文件,与ImageMagick一起使用。
MPC实际上创建了两个文件,* .mpc和* .cache,所以你需要 删除两者。在您的脚本中,设置TEMP = temp.mpc和TEMPCACHE = temp.cache, 然后在脚本的末尾,rm $ TEMP TEMPCACHE
请参阅ImageMagick Formats页面上的MPC条目。
答案 1 :(得分:1)
如果我使用您的技术获得图像的尺寸,宽度需要大约0.4秒,高度需要0.4秒。我的意思是这样的:
BG_SIZE_W=$(convert $BG -print "%w\n" /dev/null) # 0.48 sec
BG_SIZE_H=$(convert $BG -print "%h\n" /dev/null) # 0.48 sec
如果同时获得宽度和高度,请在我的机器上完成0.006秒:
read BG_SIZE_W BG_SIZE_H < <(identify -ping -format "%w %h" bg.png)
我仍在查看其余的代码。