再次更新
我使用 PyTurboJPEG 从内存缓冲区中查看 JPEG 解码,代码如下与 OpenCV 进行比较imdecode()
:
#!/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()
比imread()
我的机器快 3%。即使我np.asarray()
将时间包括在内,它仍然比内存更快 - 而且我的机器上有非常快的 3GB/s NVME 磁盘......
原始答案
我没有对此进行测试,但在我看来,您正在循环执行此操作:
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 图像都在 30kB 到 300kB 之间,因此您将在缓冲区上执行 30-300 次附加操作。我对 Python 了解不多,但我想这可能会导致重新分配内存,我想这可能会很慢。
2) 接下来,您将在前 1kB 中查找SOI标记,然后在前 2kB 中再次查找,然后在前 3kB 中再次查找,然后在前 4kB 中再次查找 - 即使您已经找到了!
3) 同样,您将在前 1kB、前 2kB 中寻找EOI标记...
所以,我建议你试试:
1)在开始时分配一个更大的缓冲区并在适当的偏移量处直接获取
2)如果您已经找到SOI标记,则不要搜索它 - 例如,将其设置-1
为每帧的开头,并且仅在它仍然存在时尝试查找它-1
3) 只在每次迭代的新数据中寻找EOI标记,而不是在之前迭代中已经搜索过的所有数据中
4)此外,实际上,除非您已经找到SOI标记,否则不要费心寻找EOI标记,因为没有相应开始的帧结束对您来说无论如何都没用 - 它是不完整的。
我的假设可能是错误的,(我以前做过!)但至少如果它们是公开的,比我聪明的人可以检查它们!!!