python - 使用 yield 而不是 return 创建函数以连续从 http 流生成帧

标签 python opencv stream iterator python-requests

我想创建一个函数,使用 requests 从 HTTP 流中读取帧并返回每一帧。但由于流读取器基于迭代器对象这一事实(如果我理解正确的话),返回一个帧会破坏流。

我正在使用的代码(工作得很好,来自 this 答案):

import cv2
import requests
import numpy as np

r = requests.get('http://roofcam.warwick.ac.uk/cgi-bin/faststream.jpg', stream=True)
if(r.status_code == 200):
    bytes_buffer = bytes()
    for chunk in r.iter_content(chunk_size=1024):
        bytes += chunk
        a = bytes_buffer.find(b'\xff\xd8')
        b = bytes_buffer.find(b'\xff\xd9')
        if a != -1 and b != -1:
            jpg = bytes_buffer[a:b+2]
            bytes_buffer = bytes_buffer[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)
else:
    print("Received unexpected status code {}".format(r.status_code))

我想做的事情的概念(如果它是一个 while 函数而不是一个 for using 迭代器,我想工作的返回值):

import cv2
import requests
import numpy as np

r = requests.get('http://roofcam.warwick.ac.uk/cgi-bin/faststream.jpg', stream=True)

def get_frame_from_stream(r):
    if(r.status_code == 200):
        bytes_buffer = bytes()
        for chunk in r.iter_content(chunk_size=1024):
            bytes_buffer += chunk
            a = bytes_buffer.find(b'\xff\xd8')
            b = bytes_buffer.find(b'\xff\xd9')
            if a != -1 and b != -1:
                jpg = bytes_buffer[a:b + 2]
                bytes_buffer = bytes_buffer[b + 2:]
                i = cv2.imdecode(np.fromstring(
                    jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                return i

    else:
        print("Received unexpected status code {}".format(r.status_code))
        return None

while True:
    if img is not None:
        img = get_frame_from_stream(r)
        cv2.imshow('i', img)
        cv2.waitKey(0)
    else:
        break

所以基本上我想返回原始代码显示帧的每一帧,以便我可以对其执行一些处理。但是我不明白 iter_content 究竟是如何让原始代码连续工作的。

(我不知道如何命名这个问题 - 欢迎更好的标题)

最佳答案

Python 有一个非常漂亮的概念 generators ,这可能是您正在寻找的东西,所以基本上要制作一个 generator 我们使用关键字 yield而不是 return .这两个关键字之间的基本区别在于,return 语句只是在遇到函数时停止执行,而另一方面 yield 关键字让我们继续执行并继续生成值直到活着。它可以在一个简单的示例中可视化为:

def sample_function():
    # The body would be replaced by image generating code.
    for i in xrange(20):
        yield i**2

for x in sample_function():
    print x, 
>>> 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361

如果我们使用 return 语句重现相同的场景,那么它可能看起来像:

def sample_function(i):
    return i**2

for i in xrange(0, 20):
    print sample_function(i),

所以在上面的代码中,如果您将 return 关键字替换为 yield,那么您可以将帧迭代为:

for frame in get_frame_from_stream(r):
    cv2.imshow('i', frame)

在这种情况下不需要 while 循环,除非并且直到该流处于事件状态,该方法将继续生成帧。

关于python - 使用 yield 而不是 return 创建函数以连续从 http 流生成帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44157160/

相关文章:

python - 如何在 Python 中捕获 "OpenCV Error"

node.js - Nodejs上传并处理视频

c - 如何在不创建临时文件的情况下从 char * 创建 FILE*

python - 验证 s3 文件夹中的所有 cloudformation 文件

python - 如何在旧数组成员之间插入空白或无

opencv - 将经过训练的 SVM 从 scikit-learn 导入到 OpenCV

c# - 有没有一种好方法可以将结果从外部进程流式传输到 Visual Studio 输出 Pane 中?

python - 类实例化以及抽象/静态类的变量共享

python - 具有 dropout 设置的 Transformers 预训练模型

matlab - 相机标定后,棋盘格是否需要保持不变?