繁体   English   中英

在Python中从单个大图像创建多个缩略图的最快方法

[英]Fastest way to create multiple thumbnails from a single large image in Python

我有一个大图像库(8000x6000px~13mb),我想生成多个尺寸较小的缩略图,宽度分别为3000px,2000px,1000px,500px,250px和100px。

源图像存储在平面文件中,生成的缩略图也将存储在平面文件中。

我一直在考虑在Python中执行此操作的最佳方法,这些都是立即浮现在脑海中的潜在问题:

  • 从源图像生成每个缩略图是否有意义,还是可以从任何略大的缩略图创建较小的缩略图? 例如,8000px - > 3000px,3000px - > 2000px,1000px - > 500px等等......运行得不会那么快?
  • 在生成缩略图之前将源图像加载到内存中是否有意义?
  • 我应该使用ImageMagick吗? 从命令行,还是通过API?
  • 有没有什么方法可以进入GPU?
  • 在这种情况下,多线程是否有意义?

优化缩略图生成时还有其他事项要记住吗? 入门时非常感谢示例代码。 谢谢。

我做了一些图像并做了一些测试,这样你就可以看到各种技术对性能的影响。

我使图像包含尺寸和文件大小的随机,难以压缩的数据以匹配您的图像,即

convert -size 8000x6000 xc:gray +noise random -quality 35 image.jpg

然后, ls给出这样的13MB:

-rw-r--r--  1 mark  staff    13M 23 Aug 17:55 image.jpg

我制作了128个这样的随机图像,因为它很好地可以被我机器上的8个CPU内核整除 - 稍后会看到并行测试。

现在的方法......

方法1

这是天真的方法 - 你只需要一个接一个地创建你要求的所有文件。

#!/bin/bash
for f in image*jpg; do
   for w in 3000 2000 1000 500 250 100; do
      convert $f -resize ${w}x res_${f}_${w}.jpg
   done 
done

时间:26分46秒

方法2

这里我们只读取一次图像,但是从一个输入图像生成所有输出尺寸,并且速度要快得多。

#!/bin/bash
for f in image*jpg; do
   convert $f -resize 3000x -write res_${f}_3000.jpg \
              -resize 2000x -write res_${f}_2000.jpg \
              -resize 1000x -write res_${f}_1000.jpg \
              -resize 500x  -write res_${f}_500.jpg  \
              -resize 250x  -write res_${f}_250.jpg  \
              -resize 100x  res_${f}_100.jpg
done

时间:6分17秒

方法3

在这里,我们提前建议ImageMagick,我们将需要的最大图像仅为3000x2250像素,因此它可以使用更少的内存并读取更少的DCT级别并减少I / O. 这称为“负载收缩”。

#!/bin/bash
for f in image*jpg; do
   convert -define jpeg:size=3000x2250 $f            \
              -resize 3000x -write res_${f}_3000.jpg \
              -resize 2000x -write res_${f}_2000.jpg \
              -resize 1000x -write res_${f}_1000.jpg \
              -resize 500x  -write res_${f}_500.jpg  \
              -resize 250x  -write res_${f}_250.jpg  \
              -resize 100x  res_${f}_100.jpg
done

时间:3分37秒

顺便说一句,为了展示缩短的时间,I / O和内存需要预先告诉ImageMagick你需要预先设置一个图像,比较这两个命令,两者都读取你的8000x6000,13MB图像和两者生成相同的缩略图:

/usr/bin/time -l convert image.jpg -resize 500x result.jpg 2>&1 | egrep "resident|real"        
1.92 real         1.77 user         0.14 sys
415727616  maximum resident set size

即415 MB和2秒

/usr/bin/time -l convert -define jpeg:size=500x500 image.jpg -resize 500x result.jpg 2>&1 | egrep "resident|real"

0.24 real         0.23 user         0.01 sys
23592960  maximum resident set size

即23 MB和0.2秒 - 输出图像具有相同的内容和质量。

方法4

在这里我们全力以赴并使用GNU Parallel以及所有上述技术来发送您的CPU,风扇和功耗疯狂!

#!/bin/bash
for f in image*jpg; do
   cat<<EOF
convert -define jpeg:size=3000x2250 $f          \
              -resize 3000x -write res_${f}_3000.jpg \
              -resize 2000x -write res_${f}_2000.jpg \
              -resize 1000x -write res_${f}_1000.jpg \
              -resize 500x  -write res_${f}_500.jpg  \
              -resize 250x  -write res_${f}_250.jpg  \
              -resize 100x  res_${f}_100.jpg
EOF
done | parallel

时间:56秒

总之,我们可以通过预先告诉ImageMagick需要读取多少输入图像并使用GNU来避免不必要地读取图像并尽可能多地输入每个输入,从而将处理时间从27分钟缩短到56秒并行保持所有可爱的CPU内核忙碌。 HTH。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM