Быстрый способ импортировать и обрезать JPEG в Python lib - PullRequest
0 голосов
/ 04 марта 2019

У меня есть приложение на python, которое импортирует 200k + изображений, обрезает их и представляет обрезанное изображение в pyzbar для интерпретации штрих-кода.Обрезка помогает, потому что на изображении несколько штрих-кодов, и, по-видимому, pyzbar работает немного быстрее при меньших изображениях.

В настоящее время я использую подушку для импорта и обрезки изображения.

В среднемимпорт и обрезка изображения занимают 262 мсек, а pyzbar - 8 мсек.

Типичный цикл составляет около 21 часа.

Интересно, может ли библиотека, отличная от Pillow, существенно улучшить загрузку / обрезку?,В идеале библиотека должна быть доступна для MacOS, но я также мог бы запустить все это на виртуальной машине с Ubuntu.

Я работаю над версией, которая может работать в параллельных процессах, что будет большим улучшением, но если бы я могполучить увеличение скорости на 25% или более из другой библиотеки, я бы также добавил это.

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Поскольку вы не предоставили образец изображения, я создал фиктивный файл с размерами 2544x4200 и размером 1,1 МБ, который указан в конце ответа.Я сделал 1000 копий этого изображения и обработал все 1000 изображений для каждого теста.

Поскольку вы указали свой код только в области комментариев, я взял его, отформатировал и сделал все, что мог.Я также поместил его в цикл, чтобы он мог обрабатывать множество файлов за один вызов интерпретатора Python - это становится важным, когда у вас есть 20 000 файлов.

Это выглядит так:

#!/usr/bin/env python3

import sys
from PIL import Image

# Process all input files so we only incur Python startup overhead once
for filename in sys.argv[1:]:
   print(f'Processing: {filename}')
   imgc = Image.open(filename).crop((0, 150, 270, 1050))

Я подозреваю, что я могу сделать это быстрее, используя:

  • GNU Parallel и / или
  • pyvips

Вот версия pyvipsвашего кода:

#!/usr/bin/env python3

import sys
import pyvips
import numpy as np

# Process all input files so we only incur Python startup overhead once
for filename in sys.argv[1:]:
   print(f'Processing: {filename}')

   img = pyvips.Image.new_from_file(filename, access='sequential')
   roi = img.crop(0, 150, 270, 900)
   mem_img = roi.write_to_memory()

   # Make a numpy array from that buffer object
   nparr = np.ndarray(buffer=mem_img, dtype=np.uint8,
                   shape=[roi.height, roi.width, roi.bands])

Вот результаты:

Последовательный исходный код

./orig.py bc*jpg
224 seconds, i.e. 224 ms per image, same as you

Параллельный исходный код

parallel ./orig.py ::: bc*jpg
55 seconds

Параллельный оригиналкод, но передавая столько имен файлов, сколько возможно

parallel -X ./orig.py ::: bc*jpg
42 seconds   

последовательные пивипы

./vipsversion bc*
30 seconds, i.e. 7x as fast as PIL which was 224 seconds

параллельные пивипы

parallel ./vipsversion ::: bc*
32 seconds

параллельные пивипы, но передавая столько имен файлов, сколько возможно

parallel -X ./vipsversion ::: bc*
5.2 seconds, i.e. this is the way to go :-)

enter image description here


Обратите внимание, что вы можете установить GNU Parallel на macOS с homebrew :

brew install parallel
0 голосов
/ 23 мая 2019

Вы можете взглянуть на PyTurboJPEG , который является оболочкой Python libjpeg-turbo с безумно быстрым масштабированием (1/2, 1/4, 1/8) при декодированиибольшое изображение JPEG, возвращающий numpy.ndarray удобно для обрезки изображенияКроме того, скорость кодирования изображений JPEG также замечательна.

from turbojpeg import TurboJPEG

# specifying library path explicitly
# jpeg = TurboJPEG(r'D:\turbojpeg.dll')
# jpeg = TurboJPEG('/usr/lib64/libturbojpeg.so')
# jpeg = TurboJPEG('/usr/local/lib/libturbojpeg.dylib')

# using default library installation
jpeg = TurboJPEG()

# direct rescaling 1/2 while decoding input.jpg to BGR array
in_file = open('input.jpg', 'rb')
bgr_array_half = jpeg.decode(in_file.read(), scaling_factor=(1, 2))
in_file.close()

# encoding BGR array to output.jpg with default settings.
out_file = open('output.jpg', 'wb')
out_file.write(jpeg.encode(bgr_array))
out_file.close()

предустановленные исполняемые файлы libjpeg-turbo для macOS и Linux также доступны здесь .

...