Обновлено снова
Я просмотрел декодирование JPEG из буфера памяти с помощью PyTurboJPEG, код выглядит следующим образом для сравнения с imdecode()
OpenCV:
#!/usr/bin/env python3
import cv2
from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY
# Load image into memory
r = open('image.jpg','rb').read()
inp = np.asarray(bytearray(r), dtype=np.uint8)
# Decode JPEG from memory into Numpy array using OpenCV
i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)
# Use default library installation
jpeg = TurboJPEG()
# Decode JPEG from memory using turbojpeg
i1 = jpeg.decode(r)
cv2.imshow('Decoded with TurboJPEG', i1)
cv2.waitKey(0)
И ответ в том, что TurboJPEG в 7 раз быстрее! Это 4,6 мс против 32,2 мс.
In [18]: %timeit i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)
32.2 ms ± 346 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [19]: %timeit i1 = jpeg.decode(r)
4.63 ms ± 55.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Спасибо @Nuzhny за то, что заметил это первым!
Обновленный ответ
Я провел несколько дополнительных тестов и не смог подтвердить ваше утверждение о том, что быстрее сохранить изображение на диск и прочитать его с помощью imread()
, чем использовать imdecode()
из памяти. Вот как я тестировал в IPython:
import cv2
# First use 'imread()'
%timeit i1 = cv2.imread('image.jpg', cv2.IMREAD_COLOR)
116 ms ± 2.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Now prepare the exact same image in memory
r = open('image.jpg','rb').read()
inp = np.asarray(bytearray(r), dtype=np.uint8)
# And try again with 'imdecode()'
%timeit i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)
113 ms ± 1.17 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Итак, я обнаружил, что imdecode()
примерно на 3% быстрее, чем imread()
на моей машине. Даже если я включу np.asarray()
в тайминг, он все равно будет быстрее из памяти, чем с диска - и у меня на машине очень быстрые диски NVME со скоростью 3 ГБ / с ...
Исходный ответ
Я не проверял это, но мне кажется, что вы делаете это в цикле:
read 1k bytes
append it to a buffer
look for JPEG SOI marker (0xffdb)
look for JPEG EOI marker (0xffd9)
if you have found both the start and the end of a JPEG frame, decode it
1) Теперь большинство изображений JPEG с любым интересным содержимым, которые я видел, имеют размер от 30 до 300 КБ, поэтому вы собираетесь выполнять 30-300 операций добавления в буфер. Я мало что знаю о Python, но я думаю, что это может привести к перераспределению памяти, что, я думаю, может быть медленным.
2) Далее вы будете искать маркер SOI в первых 1 КБ, затем снова в первых 2 КБ, затем снова в первых 3 КБ, затем снова в первых 4 КБ - даже если вы уже нашел это!
3) Точно так же вы будете искать маркер EOI в первом КБ, в первых 2 КБ...
Итак, я бы посоветовал вам попробовать:
1) выделение большего буфера в начале и получение непосредственно в него по соответствующему смещению
2) не искать маркер SOI, если вы его уже нашли — например. установите его на -1
в начале каждого кадра и попытайтесь найти его только в том случае, если он все еще -1
3) искать маркер EOI только в новых данных на каждой итерации, а не во всех данных, которые вы уже искали на предыдущих итерациях
4) кроме того, на самом деле, не утруждайте себя поиском маркера EOI, если вы уже не нашли маркер SOI, потому что конец кадра без соответствующего начала не является пользы тебе все равно - она неполная.
Я могу ошибаться в своих предположениях, (я был раньше!), но, по крайней мере, если они общедоступны, кто-то умнее меня может их проверить!!!
person
Mark Setchell
schedule
25.02.2019