我想创建一个函数,使用 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/