使用yield而不是return来创建函数以连续地从http流生成帧 [英] Creating a function using yield instead of return to generate frames from an http stream continuously

查看:106
本文介绍了使用yield而不是return来创建函数以连续地从http流生成帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个使用请求并返回每个帧。但由于流读取器基于迭代器对象(如果我理解正确),返回帧会破坏流。

I would like to create a function that reads frames from an HTTP stream using requests and returns each frame. But because of the fact that the stream reader is based on an iterator object (if I understand correctly), returning a frame is breaking the stream.

我正在使用的代码(完全正常,来自答案):

The code I am using (works perfectly fine, from this answer):

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 for iterator):

Concept of what I'd like to do (with the return that I'd like to work if it was a while function instead of a for using iterator):

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究竟是如何允许原始代码连续工作的。

So basically I'd like to return each frame where the original code is displaying the frame so that I can perform some processing on it. But I don't understand how exactly is the iter_content allowing the original code to work continuously.

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

(I didn't know how to name the question - will welcome a better title)

推荐答案

Python有一个非常漂亮的概念 生成器 ,这可能是你正在寻找的东西,所以基本上要制作一个生成器我们使用关键字 yield 而不是 返回 。这两个关键字之间的基本区别在于 return 语句只会在遇到函数时暂停执行,而另一方面 yield keyword让执行继续并继续生成值直到alive。它可以通过一个简单的例子显示为:

Python has a very beautiful concept of generators, which may be the thing you are looking for, so basically to fabricate a generator we use keyword yield instead of return. The basic difference between these two keywords is that the return statement simply halts the function execution once encountered, while on the other hand yield keyword let's the execution to continue and keeps on generating value until alive. It can be visualized in a simple example as:

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 语句重现相同的场景,然后它可能看起来像:

If We would had reproduce the same scenario using return statement then it may look like:

def sample_function(i):
    return i**2

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

因此,在上面的代码中,如果您将 return 关键字替换为 yield ,然后您可以将帧迭代为:

So in the above code if you replace the return keyword with yield, then you can iterate the frames as:

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

有这种情况下不需要循环,除非并且直到此流存活,该方法将继续生成帧。

There is no need of a while loop is this case, unless and until this stream is alive, the method would keep on generating frames.

这篇关于使用yield而不是return来创建函数以连续地从http流生成帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆