我为自己制作了一个小型的Python 3.x应用程序,它按照给定的百分比调整文件夹中的所有图像。
该应用程序支持多核CPU,因为它会分配在CPU所拥有的线程上完成的工作。
这里的瓶颈是CPU,因为我的RAM内存保持40%可用,运行时我的硬盘使用率为3%,但所有CPU核心都接近100%。
有没有办法处理GPU上的图像?我认为它会大大提高性能,因为GPU有超过4个核心。
以下是关于如何完成处理的一些代码:
def worker1(file_list, percentage, thread_no):
"""thread class"""
global counter
save_dir = askdir_entry.get() + '/ResizeImage/'
for picture in file_list:
image = Image.open(picture, mode='r')
image_copy = image.copy()
(width, height) = image.size
filename = os.path.split(picture)[1]
image_copy.thumbnail((width * (int(percentage) / 100), height * (int(percentage) / 100)))
info_area.insert('end', '\n' + filename)
info_area.see(tkinter.END)
image_copy.save(save_dir + filename)
counter += 1
if counter % 3 == 0:
update_counter(1, thread_no)
update_counter(0, thread_no)
def resize():
global start_time
start_time = timeit.default_timer()
percentage = percentage_textbox.get()
if not percentage:
info_area.insert('end', 'Please write a percentage!')
return
askdir_entry.config(state='disabled')
percentage_textbox.config(state='disabled')
file_list = glob.glob(askdir_entry.get() + '/*.jp*g')
info_area.insert('end', 'Found ' + str(len(file_list)) + ' pictures.\n')
cpu = multiprocessing.cpu_count()
info_area.insert('end', 'Number of threads: ' + str(cpu))
info_area.insert('end', '\nResizing pictures..\n\n')
if not os.path.exists(askdir_entry.get() + '/ResizeImage'):
os.makedirs(askdir_entry.get() + '/ResizeImage')
counter_label.config(text='-')
for i in range(0, cpu):
file_list_chunk = file_list[int(i * len(file_list) / cpu):int((i + 1) * len(file_list) / cpu)]
threading.Thread(target=worker1, args=(file_list_chunk, percentage, i + 1)).start()
答案 0 :(得分:7)
图像调整大小实际上并不占用大量CPU。您会发现很多时间都花在了图像解码和编码库上,而GPU几乎没有帮助。
一个简单的事情就是尝试将PIL换成pillow-simd。它与枕头兼容,但是许多内部循环已被手写的矢量代码取代。您通常可以期望a 6x to 10x speedup for image resizing。
libjpeg支持非常快速的负载缩减。作为图像解码的一部分,它可以进行x2,x4或x8的缩小-您可以轻松获得20倍的加速以进行大的缩小。您需要研究如何在枕头上启用此功能。
您还可以考虑其他图像处理库。 libvips具有用于图像缩小的快速且内存不足的命令行工具vipsthumbnail
。与GNU parallel结合使用,您可以轻松获得巨大的加速。
例如,我可以建立一个包含1000张大JPG图片的目录:
$ vipsheader ../nina.jpg
../nina.jpg: 6048x4032 uchar, 3 bands, srgb, jpegload
$ for i in {1..1000}; do cp ../nina.jpg $i.jpg; done
然后像这样用imagemagick缩小:
$ time for i in {1..1000}; do convert $i.jpg -resize 128x128 tn_$i.jpg; done
real 6m43.627s
user 31m29.894s
sys 1m51.352s
或者使用GNU parallel
和vipsthumbnail
像这样:
$ time parallel vipsthumbnail -s 128 ::: *.jpg
real 0m11.940s
user 1m15.820s
sys 0m11.916s
快33倍。
您可以将convert
与parallel
一起使用,但是每个convert
进程都需要约400mb的ram,并带有6k x 4k JPG图像,因此填充内存很容易。您可能需要对其进行微调。 vipsthumbnail
仅需要几mb的ram,因此您可以一次安全地运行多个实例。