ImageMagick批量调整大小的性能

15
convert \
   original.jpg \
  -quality 85 \
  -colorspace rgb \
  -profile /var/tmp/sRGB.icm \
  -strip \
  -profile /var/tmp/sRGB.icm \
  -filter Lanczos \
  -write mpr:17JPCONV1-original \
  +delete \
mpr:17JPCONV1-original -crop '3000x2001+0+491' -resize '190x126!>' -write thumbWide.jpg +delete \
mpr:17JPCONV1-original -crop '2981x2983+8+0' -resize '75x75!>' -write thumbStandard.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '163x163!>' -write hpSmall.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '1024x1019!>' -write jumbo.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '190x189!>' -write articleInline.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '2048x2037!>' -write superJumbo.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '592x589!>' -write tmagArticle.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '3000x2983!>' -write popup.jpg +delete \
mpr:17JPCONV1-original -crop '2981x2983+8+0' -resize '640x640!>' -write square640.jpg +delete \
mpr:17JPCONV1-original -crop '3000x1689+0+647' -resize '3000x1688!>' -write videoSmall.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '503x500!>' -write slide.jpg +delete \
mpr:17JPCONV1-original -crop '2981x2983+8+0' -resize '151x151!>' -write moth.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2001+0+491' -resize '337x225!>' -write hpMedium.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2001+0+491' -resize '395x264!>' -write sfSpan.jpg +delete \
mpr:17JPCONV1-original -crop '3000x1689+0+647' -resize '3000x1688!>' -write videoLarge.jpg +delete \
mpr:17JPCONV1-original -crop '3000x1689+0+647' -resize '511x288!>' -write hpLarge.jpg +delete \
mpr:17JPCONV1-original -crop '2981x2983+8+0' -resize '320x320!>' -write square320.jpg +delete \
mpr:17JPCONV1-original -crop '3000x1689+0+647' -resize '600x338!>' -write articleLarge.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2001+0+491' -resize '3000x2000!>' -write videoThumb.jpg +delete \
mpr:17JPCONV1-original -crop '2981x2983+8+0' -resize '150x150!>' -write thumbLarge.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '533x530!>' -write blog533.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '151x151!>' -write blogSmallInline.jpg +delete \
mpr:17JPCONV1-original -crop '3000x2983+0+0' -resize '362x360!>' -write tmagSF.jpg
我正在尝试使用一个命令从原始图像中生成约30个裁剪图像(使用一个命令比为每个裁剪图像使用一个命令要快得多)。然而,这需要相当长的时间(约30秒)才能完成。有什么建议可以加速吗?可不可以利用OpenCL通过GPU来进行调整大小操作?
更新:
  • 使用 -thumbnail 而不是 -resize 命令可以改善速度
  • (感谢 @A R 的提示)使用 libjpeg-turbo 编译 ImageMagick 还可以提高20%的速度。
3个回答

34

您应该检查您的ImageMagick安装是否具有OpenCL支持:

convert -list configure | grep FEATURES

如果成功了(像我的一样),你应该会看到类似这样的内容:

FEATURES      HDRI OpenCL

这个命令。
convert -version 

应该还需要提供有关支持功能的信息。

如果没有,您应该确保获取具有OpenCL支持编译的最新版本的ImageMagick。或者如果您从源代码构建软件包,请确保使用了OpenCL。


更新:

哦等一下。还有另一个可能会帮助您的功能,称为OpenMP(用于多处理器)。

启用OpenMP后,ImageMagick命令可以在系统所有核心上并行执行。因此,如果您有一个四核系统,并调整图像大小,则调整大小将在4个内核上完成(如果您使用超线程,则可达到8个内核)。

您现在还可以使用内置的-bench选项,使ImageMagick为您的命令运行基准测试。例如:

convert logo: -resize 500% -bench 10 logo.png
  Performance[1]: 10i 0.689ips 1.000e 14.420u 0:14.510

这个命令使用-resize 500%参数告诉ImageMagick运行convert命令来将内置的IMlogo:图像在每个方向上放大500%。部分-bench 10告诉它在循环中运行相同的命令10次,然后打印性能结果:

  • 由于我没有启用OpenMP,所以只有一个线程(Performance[1]:)。
  • 报告它运行了10次迭代(10i)。
  • 速度接近每秒0.7次迭代(0.689ips)。
  • 总计分配给用户的时间为14.420秒。

您可以使用以下命令找出系统的资源限制设置:

identify -list resource
  File       Area     Memory     Map       Disk    Thread         Time
  --------------------------------------------------------------------
   192    4.295GB       2GiB    4GiB  unlimited         1    unlimited

您可以看到我当前系统的默认设置(我没有进行调整)。您可以使用列标题中的每个关键字来优化您的系统。

  • files定义ImageMagick将使用的最大并发打开文件数。
  • memorymapareadisk资源限制以字节为单位。要将它们设置为不同的值,您可以使用SI前缀,例如500MB。

如果我在这个系统上有OpenMP for ImageMagick,我可以运行:

convert -limit thread 2

为了启用2个并行线程,请重新运行基准测试,看看是否真的有所区别,如果有的话,要看到多大的改善。然后我可以将限制设置为4甚至8,并重复练习。
最后,您可以尝试使用ImageMagick像素缓存的内部格式,称为MPC(Magick像素缓存)。有些人说,在大型操作中,性能会有所提高,但我个人没有经验。
首先将基础图片转换为MPC格式:
convert input.jpeg input.mpc

仅在此之后运行:

convert input.mpc [...your long-long-long list of crops...]

查看是否能显著节省时间。

很可能您甚至可以使用这种MPC格式“内联”(使用特殊的 mpr: 标记),类似于使用 mpr: 格式(即内存程序寄存器)将图像读入命名内存寄存器的技巧。但我从未尝试过这种方法解决实际问题,所以无法确定其在实际生活中的表现如何。


更新2:

另一个想法:

首先检查您的ImageMagick版本是否准确:运行 convert -version 命令。

如果您的ImageMagick版本字符串中有 Q16 (甚至是 Q32Q64)(这意味着其内部处理将所有图像视为具有16位通道深度,需要与 Q8 相比的双倍内存),则可以测试通过切换到Q8构建来获得的性能优势。 (您将用质量损失来换取性能的胜利,并且必须检查您是否能接受它....)


感谢您的回复。我可能应该注意到我的ImageMagick安装已启用OpenMP。换句话说,该命令在多个核心上并行化。还有其他加速的方法吗? - mantithetical
在Stackoverflow上,人们通常通过给有见地的答案点赞来表示感谢。 :-) - Kurt Pfeifle
啊,是的。不幸的是,我没有足够的声望来点赞你的回答。 - mantithetical
@mantithetical:我没想到你需要声望来赞同(或接受)回答你自己的问题.... - Kurt Pfeifle

11

你的 CPU 时间被分配给了 3 个任务:

  • JPEG 解压缩;
  • 调整大小;
  • JPEG 重新压缩

(裁剪本身可能只占用了 1% 的时间。)

为了解码 JPEG,只需解码一次,将结果保存在 RAM 中,并重复使用每个输出。(详见下文。) 这样,成本将是微不足道的。

要编码 JPEG,请使用 libjpeg-turbo;同样的 API,但如果您使用 x86-{32,64} 或 ARM 硬件,则可以提高 2-4 倍速度。

要调整大小,ImageMagick 以 ~100 倍于除 PhotoShop 和 GIMP 之外的任何其他软件的 CPU 使用率而闻名。这包括所有照片查看器。它对每个像素执行多个三角函数,而其他所有人只执行一个乘法。 有时,如果您查看图像边缘附近的像素,您可以看到 ImageMagick 选择比其竞争对手更好的颜色。 但是,如果您认为 HTML5、Flash、Silverlight、Java、GD(流行于 Perl、PHP 和 Python Web 应用程序)等看起来很好,那么您就不需要这种伪 AI (人工智能)。 您可能能够将 GPU (OpenCL) 计算能力或更多 CPU (OpenMP) 计算能力投入到 ImageMagick 中,但是为什么要这样做呢?

对于高效率,相当于 ImageMagick(事实上的标准)的软件是 Imlib2。它可以从几乎与 ImageMagick 相同的 OS/语言环境中使用。

你的 "convert" shell 命令相当于用高级语言调用 Imlib2 的 10-20 行代码:

解压缩 JPEG,然后重复裁剪、调整大小和压缩 JPEG。

一个没有裁剪(或多个输出)的例子是:使用 Perl 拉伸、调整大小或制作缩略图

如果您需要其他示例,请告诉我。


感谢您的回复。转向Imlib2不是一个选项。有没有办法使用ImageMagick和libjpeg-turbo? - mantithetical
@AR:我不确定你关于ImageMagick调整大小“每像素执行多个三角函数”和“伪人工智能”的说法是否正确。这只有在选择“-adaptive-resize”时才会发生吧? - Kurt Pfeifle
不,如果进行任何类型的EWA,权重是按每个像素计算的,这需要使用三角函数。 - Lilith River

0

虽然有点晚了,但这是我目前的方法,如果有人遇到同样的问题。 如果您正在批处理基本转换,但要处理成千上万张图像,根据我的经验,您不会从openMP中获得太多好处,因为它似乎适用于“多核”大型复杂转换。 我的解决方案是编写一个bash脚本以并行方式生成单个进程。

#!/bin/bash
counter=0
for i in tif/*.TIF;
do
    y=${i%.TIF}
    ((counter++))
    if [ -s gif$y.gif ];then
        :
    else
        gm convert $i gif$y.gif &
    fi
    if [ $counter -eq 30 ];then 
        ((counter =0))
        wait
    fi
done
wait  

这个脚本将会把'tif'文件夹中的所有TIF文件转换成'giftif'文件夹中的gif格式文件。如果你需要停止这个脚本,下次它会在离开的地方继续执行。目前我正在转换150,000张图片,使用这种方法会占用MBP上的所有16个核心,速度比单核心方法快12-14倍。


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