ImageMagick:处理不同文件格式的速度
ImageMagick: speed of processing with different file formats
我正在使用 ImageMagick(版本:ImageMagick 6.9.7-4 Q16 x86_64 20170114)来创建一种特殊的合成叠加图像。使用 Python 作为控制结构,我本质上是 运行 一系列 shell 命令(convert
和 composite
)来执行以下操作:
create an initial (transparent) working image W
for n = 1 to numberOfOverlappingShapesWanted
use convert to create a transparent overlay image (O) with a random shape at a random place
use composite to merge down W (on top) with O (beneath) and produce WO
replace W with WO
use convert to change W into any desired final image format
目前,我以 PNG 格式创建 W、O 和 WO。我的问题仅与速度有关...使用我所拥有的非常粗糙的结构,是否可以选择一种图像格式来使处理过程 运行 比我当前选择的 PNG 格式更快。
根据真实示例的请求进行编辑...
#!/usr/bin/python3
import os
import random
# The overall algorithm here is to create a blank working image
# called w.png and then to drop a disc onto a new blank image
# calle l.png . The old working image is then combined with
# the newly dropped disc into an image called wl.png .
# And wl.png then becomes the new working image
# Python is used only for the control structure. The real
# work is done by ImageMagick from Python os.system commands.
nDroppingDiscs = 6
discRadius = 64
imageX = 2048
imageY = 2048
# Names for the three images
workingImage = 'w.png'
discImage = 'o.png'
combinedImage = 'wo.png'
# Create the first part of the ImageMagick 'convert' command
# of the form:
# convert -size 2048x2048 xc:transparent
baseWorkingCommand = 'convert -size ' + \
str( imageX ) + 'x' + str( imageY ) + ' ' + \
'xc:transparent '
# Create initial blank working image
# convert -size 2048x2048 xc:transparent w.png
os.system( baseWorkingCommand + workingImage )
for n in range( nDroppingDiscs ) :
# Create the initial portion of the ImageMagick 'convert'
# command for dropping a disc onto a transparent canvas
baseDiscCommand = 'convert -size ' + \
str( imageX ) + 'x' + str( imageY ) + ' ' + \
'xc:transparent +antialias -fill '
# Ensure that each disc is a different colour
discNAsColourString = "#%06x" % n
baseDiscCommand = baseDiscCommand + " '" + \
discNAsColourString + "' "
# Determine the drop-point for the disc
discDropPointX = random.randint(1, imageX)
discDropPointY = random.randint(1, imageY)
discRadiusIndicatorX = discDropPointX
discRadiusIndicatorY = discDropPointY + discRadius
# Put the pieces of the 'convert' command together
baseDiscCommand = baseDiscCommand + \
" -draw 'circle " + \
str( discDropPointX ) + "," + \
str( discDropPointY ) + " " + \
str( discRadiusIndicatorX ) + "," + \
str( discRadiusIndicatorY ) + "'"
# Use ImageMagick to create the new randomly dropped disc
os.system( baseDiscCommand + " " + discImage )
# Overlay the existing image onto the newly created dropped disc
# to produce a combined image
os.system('composite ' + workingImage + " " + discImage + " " + combinedImage )
# The combined image is now the new working image
os.system('mv ' + combinedImage + ' ' + workingImage )
# Final conversion. Convert the working image from whatever format
# I was using earlier to a final PNG format.
os.system('convert ' + workingImage + ' final.png')
请注意,常量 nDroppingDiscs
通常约为 4000。此外,值得补充的是,我的最终目的是探索有关此类图案的图像统计信息。
对于像这样的迭代过程,通过文件系统会非常慢。我认为 numpy.
之类的东西可能会让你过得更好
我很快进入了pyvips,因为我很了解它:
#!/usr/bin/python3
import random
import pyvips
n_dropping_discs = 1000
disc_radius = 64
image_width = 2048
image_height = 2048
image = pyvips.Image.black(image_width, image_height, bands=4) \
.copy(interpretation="srgb")
for i in range(n_dropping_discs):
ink = [(i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff, 0xff]
x = random.randint(0, image_width) - disc_radius
y = random.randint(0, image_height) - disc_radius
image = image.draw_circle(ink, x, y, disc_radius, fill=True)
image.write_to_file("final.png")
我在这台笔记本电脑上看到:
$ time ./disc2.py
real 0m6.086s
user 0m12.182s
sys 0m1.656s
所以 1,000 张光盘大约需要 6 秒。 pyvips 不太适合这种任务——numpy 会更快。
我有时间尝试 John 的建议,并将他的代码重新哈希为 Numpy 和 OpenCV,如下所示。在我的机器上,它似乎比 pyvips 快 40 倍:
#!/usr/bin/env python3
import random
import cv2
n_dropping_discs = 1000
disc_radius = 64
image_width = 2048
image_height = 2048
def numpyidea():
image = np.zeros((image_height,image_width,4), dtype=np.uint8)
for i in range(n_dropping_discs):
ink = [i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, 0xff]
x = random.randint(0, image_width) - disc_radius
y = random.randint(0, image_height) - disc_radius
cv2.circle(image, (x,y), disc_radius, ink, cv2.FILLED)
cv2.imwrite("numpy.png", image)
return
我正在使用 ImageMagick(版本:ImageMagick 6.9.7-4 Q16 x86_64 20170114)来创建一种特殊的合成叠加图像。使用 Python 作为控制结构,我本质上是 运行 一系列 shell 命令(convert
和 composite
)来执行以下操作:
create an initial (transparent) working image W
for n = 1 to numberOfOverlappingShapesWanted
use convert to create a transparent overlay image (O) with a random shape at a random place
use composite to merge down W (on top) with O (beneath) and produce WO
replace W with WO
use convert to change W into any desired final image format
目前,我以 PNG 格式创建 W、O 和 WO。我的问题仅与速度有关...使用我所拥有的非常粗糙的结构,是否可以选择一种图像格式来使处理过程 运行 比我当前选择的 PNG 格式更快。
根据真实示例的请求进行编辑...
#!/usr/bin/python3
import os
import random
# The overall algorithm here is to create a blank working image
# called w.png and then to drop a disc onto a new blank image
# calle l.png . The old working image is then combined with
# the newly dropped disc into an image called wl.png .
# And wl.png then becomes the new working image
# Python is used only for the control structure. The real
# work is done by ImageMagick from Python os.system commands.
nDroppingDiscs = 6
discRadius = 64
imageX = 2048
imageY = 2048
# Names for the three images
workingImage = 'w.png'
discImage = 'o.png'
combinedImage = 'wo.png'
# Create the first part of the ImageMagick 'convert' command
# of the form:
# convert -size 2048x2048 xc:transparent
baseWorkingCommand = 'convert -size ' + \
str( imageX ) + 'x' + str( imageY ) + ' ' + \
'xc:transparent '
# Create initial blank working image
# convert -size 2048x2048 xc:transparent w.png
os.system( baseWorkingCommand + workingImage )
for n in range( nDroppingDiscs ) :
# Create the initial portion of the ImageMagick 'convert'
# command for dropping a disc onto a transparent canvas
baseDiscCommand = 'convert -size ' + \
str( imageX ) + 'x' + str( imageY ) + ' ' + \
'xc:transparent +antialias -fill '
# Ensure that each disc is a different colour
discNAsColourString = "#%06x" % n
baseDiscCommand = baseDiscCommand + " '" + \
discNAsColourString + "' "
# Determine the drop-point for the disc
discDropPointX = random.randint(1, imageX)
discDropPointY = random.randint(1, imageY)
discRadiusIndicatorX = discDropPointX
discRadiusIndicatorY = discDropPointY + discRadius
# Put the pieces of the 'convert' command together
baseDiscCommand = baseDiscCommand + \
" -draw 'circle " + \
str( discDropPointX ) + "," + \
str( discDropPointY ) + " " + \
str( discRadiusIndicatorX ) + "," + \
str( discRadiusIndicatorY ) + "'"
# Use ImageMagick to create the new randomly dropped disc
os.system( baseDiscCommand + " " + discImage )
# Overlay the existing image onto the newly created dropped disc
# to produce a combined image
os.system('composite ' + workingImage + " " + discImage + " " + combinedImage )
# The combined image is now the new working image
os.system('mv ' + combinedImage + ' ' + workingImage )
# Final conversion. Convert the working image from whatever format
# I was using earlier to a final PNG format.
os.system('convert ' + workingImage + ' final.png')
请注意,常量 nDroppingDiscs
通常约为 4000。此外,值得补充的是,我的最终目的是探索有关此类图案的图像统计信息。
对于像这样的迭代过程,通过文件系统会非常慢。我认为 numpy.
之类的东西可能会让你过得更好我很快进入了pyvips,因为我很了解它:
#!/usr/bin/python3
import random
import pyvips
n_dropping_discs = 1000
disc_radius = 64
image_width = 2048
image_height = 2048
image = pyvips.Image.black(image_width, image_height, bands=4) \
.copy(interpretation="srgb")
for i in range(n_dropping_discs):
ink = [(i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff, 0xff]
x = random.randint(0, image_width) - disc_radius
y = random.randint(0, image_height) - disc_radius
image = image.draw_circle(ink, x, y, disc_radius, fill=True)
image.write_to_file("final.png")
我在这台笔记本电脑上看到:
$ time ./disc2.py
real 0m6.086s
user 0m12.182s
sys 0m1.656s
所以 1,000 张光盘大约需要 6 秒。 pyvips 不太适合这种任务——numpy 会更快。
我有时间尝试 John 的建议,并将他的代码重新哈希为 Numpy 和 OpenCV,如下所示。在我的机器上,它似乎比 pyvips 快 40 倍:
#!/usr/bin/env python3
import random
import cv2
n_dropping_discs = 1000
disc_radius = 64
image_width = 2048
image_height = 2048
def numpyidea():
image = np.zeros((image_height,image_width,4), dtype=np.uint8)
for i in range(n_dropping_discs):
ink = [i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, 0xff]
x = random.randint(0, image_width) - disc_radius
y = random.randint(0, image_height) - disc_radius
cv2.circle(image, (x,y), disc_radius, ink, cv2.FILLED)
cv2.imwrite("numpy.png", image)
return