python opencv从bytearray创建图像

python opencv从bytearray创建图像,opencv,python-3.7,opencv4,Opencv,Python 3.7,Opencv4,我正在用理光西塔V摄像机拍摄视频。要获取视频,您必须执行HTTP POST,这意味着我不能使用cv2.VideoCapture(url)功能 因此,通过在网络上发布大量帖子来实现这一点的方法如下: bytes = bytes() while True: bytes += stream.read(1024) a = bytes.find(b'\xff\xd8') b = bytes.find(b'\xff\xd9') if a != -1 and b != -1:

我正在用理光西塔V摄像机拍摄视频。要获取视频,您必须执行HTTP POST,这意味着我不能使用
cv2.VideoCapture(url)
功能

因此,通过在网络上发布大量帖子来实现这一点的方法如下:

bytes = bytes()
while True:
    bytes += stream.read(1024)
    a = bytes.find(b'\xff\xd8')
    b = bytes.find(b'\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)

这实际上是可行的,只是速度很慢。我正在处理一个1920x1080JPEG流。在运行OSX 10.12.6的Mac Book Pro上。调用
imdecode
处理每个图像大约需要425000微秒

你知道如何在不使用
imdecode
的情况下实现这一点,或者让
imdecode
更快吗?我希望它能以60帧/秒的速度播放高清视频(至少)


我正在使用Python3.7和OpenCV4。

我建议使用turbo jpeg。它有一个python API:。

再次更新

我使用PyTurboJPEG从内存缓冲区查看了JPEG解码,代码如下,与OpenCV的
imdecode()

答案是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标记,因为没有相应开始的帧结束对您没有任何用处-它是不完整的


我的假设可能是错误的,(我以前也有过!)但至少如果它们是公开的,比我聪明的人可以检查它们

这可以是评论而不是回答。相关问题性能问题与
cv2.imdecode
有关。这是我无论如何都想回答的问题。也许我没说清楚?如果我写入磁盘并从磁盘读取,而不是执行
imdecode
,速度会快得多。我想知道谁/什么在对写/读操作进行解码。操作系统?当我有时间的时候,我会仔细检查我关于imread的声明。但尽管如此,根据您自己的计时,您甚至无法使用imdecode每秒获得10帧。这不是很好的视频!我们正在处理一个视频源。这是假设python代码尽可能快,但可能不像您所说的那样快。因此,imdecode无法以10 fps以上的速度处理MJPeg视频流,而我测试的图像实际上具有异常高的熵。我只是用一个低熵、更正常的图像再次尝试了一下,两种方法都用了大约30毫秒,相当于30+fps。此外,这只是顺序代码,如果使用多线程或多处理,在大多数现代多核台式机上可能会将帧速率提高2-4倍。我正在处理1920x1080 jpeg流。在macbookpro上。OSX 10.12.6。imdecode处理每张图像大约需要425000微秒。请忘记我关于读/写速度更快的评论。那是一个骗局。我已经更新了我的问题。
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