[英]ImageMagick: combine multiple 'montage' commands into one to gain performance
我有一个脚本,可以拍摄4张图片并将其复制以一张生成8张小图片。 该脚本还将背景添加到输出中。
这是我期望的:
http://img11.hostingpics.net/pics/831624stack.png
我有一个运行良好的代码。 但是它需要保存多个临时图像。
因此,我一直在寻找是否可以合并脚本的命令以仅进行一次图像保存操作。 目的是使脚本更快地完成。
//Make image smaller:
convert /home/pi/images/*.png -resize 487x296 -flop \
-set filename:f "/home/pi/imagesResized/%t%p" '%[filename:f]'.png
//Make one column from 4 images:
montage /home/pi/imagesResized/*.png -tile 1x4 \
-geometry +0+15 -background none /home/pi/line.png
//Duplicate to two columns:
montage /home/pi/line.png /home/pi/line.png -tile 2x1 \
-geometry +45+0 -background none /home/pi/photos.png
//Add the background image:
suffix=$(date +%H%M%S)
montage /home/pi/photos.png -geometry +20+247 \
-texture /home/pi/data/background_photo.png \
/home/pi/photo_${suffix}.jpg
首先,我这样说:如果输入图像很大,将单独的命令放入一个ImageMagick命令链中,您将仅节省大量的处理时间。 但是,通过跳过写出和读入中间结果图像的需要,可以节省磁盘I / O时间。
您的代码使用两个不同的montage
命令以及一个convert
命令来实现第一个蒙太奇。 最后,您使用一个montage
将前一个结果放在背景上。
从头顶上,我可以快速想到一种将前三个命令组合为一个命令的方法。 将中间结果放到背景上的最后一个剪辑步骤不太容易正确,而且很可能也不会节省很多时间。 因此,我暂时将其保留。
不幸的是,您未提供任何指向源图像的链接。 为了回答这个问题,我必须自己创建一个。 它们还可以用来演示我的答案的有效性。
要创建四个800x600像素大小的PNG,我在命令行上使用了Ghostscript和一点PostScript代码:
for i in 1 2 3 4 ; do
gs -o t${i}.png \
-g800x600 \
-sDEVICE=pngalpha \
-c "0.5 setgray" \
-c "0 0 800 600 rectfill" \
-c "1 0 0 setrgbcolor" \
-c "3 setlinewidth" \
-c "10 10 780 580 rectstroke" \
-c "0 setgray" \
-c "/Helvetica-Bold findfont" \
-c "560 scalefont setfont" \
-c "230 60 moveto" \
-c "(${i}) show " \
-c "showpage" ;
done
然后,我首先用图像测试了您的代码。 这是OP命令的结果。 结果是完整的,包括
从我自己的股票
( 已更新 )中
提取
的背景图像上的蒙太奇图像
,
该图像是由马克·谢彻尔的答案启发而创建的:
convert -size 200x200 xc:gray +noise gaussian background.png
以下是我想出一个命令的第一枪。 它应该获得与前两个输出line.png
命令相同的结果。 我已经知道它在某些方面不能完全按预期工作,但我仍然尝试过。 我尝试了一下,以查看该命令是否还有其他地方会出现我没有想到的问题。 不用担心,完整的最终代码的解释将在答案的结尾。 阅读完整的答案后,您可以尝试弄清楚以下命令的工作方式:
_col1=blue ;
_col2=red ;
convert t*.png -flop -resize 487x296\! \
\( -size 15x15 \
-clone 0 xc:${_col1} \
-clone 1 xc:${_col1} \
-clone 2 xc:${_col1} \
-clone 3 \
-append \
+write f.png \
\) null:
这是我的命令(右)的结果与第二个命令(左)之后的中间结果的比较:
所以,有一件事我所预料的事情发生了:有每个图像之间的间隔蓝色。 我出于调试原因对其进行了着色。 可以通过将color变量设置为none
(透明)来解决此问题。
我没有想到的事情,只有在打开结果图像f.png
后才发现的f.png
:
我的背景是白色而不是透明。 可以通过在正确的位置添加-background none
来解决此问题。
我在各列中各图像的间距太窄,只有15个像素。 这是因为在OP的中间文件line.png
中,间距不是15像素,而是30像素。 他的montage
创建列的参数-geometry +0+15
确实在每个图像的顶部和底部添加了15个像素。 我的命令(使用convert ... -append
而不是montage
)不允许使用其他具有相同效果的-geometry
设置。 但是可以通过在我的命令中添加更多的xc:{_col1}
分隔xc:{_col1}
来解决他的问题。
所以这是下一个迭代。 它集成了来自OP的第三条命令的效果。 这可以通过添加+duplicate
来复制第一个创建的列来实现。 然后,它添加+append
以水平地添加重复的列( -append
可以垂直地添加):
_col1=blue ;
_col2=red ;
convert t*.png -flop -resize 487x296\! \
\( -size 15x15 \
-background none \
xc:${_col1} \
-clone 0 xc:${_col1} xc:${_col1} \
-clone 1 xc:${_col1} xc:${_col1} \
-clone 2 xc:${_col1} xc:${_col1} \
-clone 3 \
xc:${_col1} \
-append \
+duplicate \
-size 45x45 xc:${_col2} \
+append \
+write f2.png \
\) null:
再次发生了我所期望的一件事:
两列之间的红色垫片位于右侧,而不是位于两列之间。 我们可以通过交换获得+append
-ed的最后两个图像来解决此问题。 这可以通过在正确的位置添加+swap
运算符来完成。
同样,与第一列中的图像间间距相同的事物将应用于两列之间的间距:我必须将其加倍。
此刻,我不会在意向左和向右+append
append-列添加相同的空间(45像素)。
因此,这里还有一个迭代:
_col1=red ;
_col2=blue ;
convert t*.png -flop -resize 487x296\! \
\( -background none \
-size 15x15 \
xc:${_col1} \
-clone 0 xc:${_col1} xc:${_col1} \
-clone 1 xc:${_col1} xc:${_col1} \
-clone 2 xc:${_col1} xc:${_col1} \
-clone 3 \
xc:${_col1} \
-append \
+duplicate \
-size 90x90 xc:${_col2} \
+swap \
+append \
+write f3.png \
\) null:
结果如下:
photos.png
。 现在缺少的是对我打包到单个命令中的各个操作的细分的解释:
\\(
: \\)
: -size 15x15
: xc:${_col1}
: xc:
只是canvas:
的别名,但是键入速度更快。 -clone 0
: t1.png
的副本。 -clone 1
份t2.png
, -clone 2
份t3.png
等-clone
或+clone
工作最好内部侧向处理链,因此前面所解释的使用\\(
和\\)
-append
: t1.png
,... t4.png
的4个副本。 +duplicate
: +clone
。 它复制当前加载的图像堆栈中的最后一个图像。 在这种情况下,最后一个图像(并且在横向管道中仅剩下一个)是先前-append
操作的结果。 此操作已创建第一列的4张图像,并用红色的分隔符隔开。 +append
: -append
操作的结果,由+duplicate
创建的+duplicate
以及大小为90x90
的xc:
-canvas。 +swap
: +write
: +write
操作之后,先前加载的图像将全部保留在堆栈中。 这些图像保持不变,并且处理可以继续。 但是,我们现在已经完成,在这种情况下将不会继续。 因此,我们使用\\)
关闭横向过程。 null
:
现在,我们关闭了sideway过程,ImageMagick将结果图像从sideway再次放入主管道。 请记住, +write
并没有完成处理,而是将一个文件写入了磁盘,这是中间结果。 在t1.png
道中,现在仍然有原始的t1.png
... t4.png
以及横向处理的结果。 但是,我们不会对他们采取任何措施。 我们将+write
的中间结果作为最终结果。 但是convert
命令现在期望看到一个输出文件名。 如果没有看到它,它将抱怨并向我们显示错误消息。 因此,我们告诉它注销所有已加载的内容,并丢弃堆栈中的所有图像。 为此,我们使用null:
作为输出文件名。
(如果您喜欢冒险,请使用out.png
作为文件名而不是null:
。您将看到ImageMagick实际上创建了多个out-0.png
, out-1.png
,... out-3.png
文件名。您将发现out-4.png
与f.png
相同, out-{0,1,2,3}.png
与输入图像相同-您也可以将null:
替换为-append output.jpg
,然后看看会发生什么...)
现在进行速度比较...
对于第一个粗略的基准测试,我确实以100次迭代的循环运行了OP的前三个命令。 然后我也执行了100次自己的命令。
结果如下:
因此,与OP中的原始命令相比,我的单个命令节省了大约20%的时间。
与旋转的硬盘相比,假定我的磁盘I / O性能相当快(测试系统具有SSD),因此合并命令(避免了过多的临时文件读/写)带来的速度提升可能是在磁盘速度较慢的系统上更为明显。
为了检查命令的一些重新架构(在结尾处不会丢弃太多加载的图像,可以通过null:
输出文件名看到)来获得更多的改进,我还尝试了以下操作:
convert t*.png -flop -resize 487x296\! \
-background none \
-size 0x15 \
xc:red \
-duplicate 7 \
-insert 0 \
-insert 2 \
-insert 3 \
-insert 5 \
-insert 6 \
-insert 8 \
-insert 9 \
-append \
\( +clone -size 45x0 xc:blue +swap \) \
+append \
f4.png
该命令的体系结构有所不同。
首先,它加载所有图像。 -flop
它们,并-resize
它们的大小。
其次,它创建一个15x15像素的画布,然后还将其放置在图像堆栈上。
第三,它将创建该画布的其他7个副本。 现在,堆栈上有12张图像:4个输入文件,1个xc:
-canvas和7个画布副本。
然后,它使用一系列-insert N
操作。 -insert N
操作可操纵图像堆栈的顺序。 它从堆栈中删除最后一张图像,并将其插入图像索引位置N
当-insert
系列操作开始时,堆栈上有4个图像( t1
, t2
, t3
, t4
),外加8个“间隔符”( s
)。 这是他们的原始顺序:
index: 0 1 2 3 4 5 6 7 8 9 10 11 image: t1 t2 t3 t4 ssssssss
我以某种方式选择了索引号,以便在所有-insert N
操作完成之后,从原始顺序上方更改后的新顺序为:
index: 0 1 2 3 4 5 6 7 8 9 10 11 image: s t1 ss t2 ss t3 ss t4 s
由于所有的间隔件s
是15个像素宽,这实现相同的间隔作为我的初始命令。
接下来,发生类似的横向处理:这次+clone
上一个-append
操作的结果并创建水平间隔符。
最后, +append
(对上一个-append
和f4.png
处理的结果进行运算)创建最终结果f4.png
。
当我对这最后一条命令进行基准测试时,对于每个命令100次重复,我得到以下结果:
因此,速度增益并不是那么显着,如果您想相信这些数字,速度大约可以提高3%。
(应该注意,我确实在同一台机器上并行运行两个循环,以在基准测试竞争中创造更多的公平性。通过并行运行,它们都必须处理相同的CPU和I / O负载,这可能会导致本身以及计算机上同时发生的其他进程。)
由于我没有您的图像,纹理或大小,因此我将向您展示一些类似的内容,以使您适应...
制作一些输入图像:
convert -size 500x400 xc:black 1.png
convert -size 500x400 xc:red 2.png
convert -size 500x400 xc:green 3.png
convert -size 500x400 xc:blue 4.png
和背景纹理:
convert -size 2000x2000 xc:gray +noise gaussian background.png
现在按照您的要求执行操作,但没有将中间文件存储到磁盘:
montage [1234].png -background none -tile 1x4 -geometry +0+15 miff:- |
convert -background none :- -size 15 xc:none -clone 0 +append png: |
convert -gravity center background.png :- -composite z.png
第一行将这4张图像依次排列,然后将合并结果以MIFF
(多图像文件格式)通过管道发送到下一个命令。 第二个命令从管道读取图像,并附加一个15像素宽的“分隔符”,然后复制图像的第一列(带有clone
),并作为PNG
通过另一个管道写入下一个命令。 最后的命令读取组合的8张小图像,并将它们放在背景的中央。
如果图像的右手栏应该是左手栏反映出的-从您的糟糕示例中很难看出哪个显示了扁平的黑框-您可能需要将命令的第二行更改为
convert -background none :- -size 15 xc:none -clone 0 +append png: |
至
convert -background none :- -size 15 xc:none \( -clone 0 -flop \) +append png: |
这是另一个答案。 它从Mark Setchell的方法中获得启发。 在这里,我提出了一个新的命令管道。 不同的是,我...
montage
命令(Mark在其管道中使用了1个montage
和2个convert
s),并且我 作为输入,我在另一个答案t{1,2,3,4}.png
使用了Ghostscript命令创建的四个图像。
为了创建合适的背景图像,我使用了Mark的命令,但对其进行了修改:我将图像缩小了一点,以便OP中的-texture
运算符可以有意义地使用:
convert -size 200x200 xc:gray +noise gaussian background.png
然后我对所有三个命令/脚本进行了基准测试,...
为了进行基准测试,我每个都进行了100次重复。 这样做时,我几乎同时在一个单独的终端窗口中启动了每个脚本/命令。 测试机上的CPU有4个内核。 因此,当命令并行运行时,它们必须分别处理相同的CPU和I / O负载,相互竞争资源。 这是我可以想到的最“公平”的临时性能测试设置。
我还确认了这3个测试( photo_test1.jpg
, ms+kp_test2.jpg
和kp_test3.jpg
)创建的输出文件在kp_test3.jpg
方向上(几乎)相同。 如果将输出切换到PNG(而不是JPEG,而是OP要求的方式),则这三种方法之间的微小差异也将消失。
结果如下:
mkdir ./imagesResized
time for i in {1..100}; do
convert t*.png -resize 487x296\! -flop \
-set filename:f "./imagesResized/%t%p" '%[filename:f]'.png
montage ./imagesResized/*.png -tile 1x4 -geometry +0+15 \
-background none line.png
montage line.png line.png -tile 2x1 -geometry +45+0 \
-background none photos.png
montage photos.png -geometry +20+247 \
-texture background.png \
photo_test1.jpg
done
结果:
真正的2m13.471s
用户1m54.306s
SYS 0分14.340秒
以此为100%的时间消耗。
time for i in {1..100}; do
montage t[1234].png -resize 487x296\! -flop -background none \
-tile 1x4 -geometry +0+15 miff:- \
| montage :- -background none -clone 0 -tile 2x1 -geometry +45+0 miff:- \
| montage :- -geometry +20+247 -texture background.png ms+kp_test2.jpg ;
done
结果:
真正的1m50.125s
用户1m32.453s
sys 0m16.578s
与原始命令相比,耗时约83%。
time for i in {1..100}; do
convert t*.png -flop -resize 487x296\! \
-background none \
-size 0x15 \
xc:white \
-duplicate 7 \
-insert 0 \
-insert 2 \
-insert 3 \
-insert 5 \
-insert 6 \
-insert 8 \
-insert 9 \
-append \
\( +clone -size 90x0 xc:white +swap \) \
+append \
-transparent white \
miff:- \
| montage :- -geometry +65+247 -texture background.png kp_test3.png
done
结果:
真正的1m34.786s
用户1m20.595s
sys 0m13.026s
与原始命令相比,耗时约72%。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.