如何从烧瓶关闭OpenCV视频流
我已经实施了一个系统,可以使用烧瓶和OpENCV从实时流捕获面孔。我现在面临关闭流并发布videocapture
对象的困难。这是下面我的代码的片段:
from flask import Flask, Response, render_template
import cv2, imutils
import face_recognition
from skimage.exposure import is_low_contrast
app = Flask(__name__)
cam_feed = cv2.VideoCapture(0) # to get feed from webcam, use 0 as argument
def gen_frames(): # generate frame by frame from camera
"""
Variable for counting number of images collected
List for saving encodings also declared here
"""
image_counter = 0
name = "John Doe"
known_names = []
known_encodings = []
if not cam_feed.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
success, frame = cam_feed.read() # read the camera frame
if not success:
print("Can't receive frame (stream end?). Exiting ...")
break
else:
ret, frame = cam_feed.read()
frame = imutils.resize(frame, width=640)
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
else:
# face location model can either be HOG or CNN but HOG is faster (but less accurate) and way better if you don't have a GPU
boxes = face_recognition.face_locations(frame, model='hog')
if boxes: # if a face is detected
for (top, right, bottom, left) in boxes:
if (image_counter < 20):
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
encodings = face_recognition.face_encodings(frame, boxes)
known_names.append(name)
known_encodings.append(encodings)
image_counter += 1
else:
break # break while True loop and end stream
ret, buffer = cv2.imencode('.jpg', frame) # encode the frame so that flask can return it as a response in bytes format
frame = buffer.tobytes() # convert each frame to a byte object
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # concat frame one by one and show result
以下是我的流媒体路线:
@app.route('/video_feed')
def video_feed():
#Video streaming route. Put this in the src attribute of an img tag
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
当我的图像计数达到20时,循环似乎不会破裂,因为我可以看到我的网络摄像头仍在运行。我试图做的是创建另一个路由,在其中我调用cam_feed.release()
,然后使用我的index.html
file file;这是代码:
@app.route('/done')
def done():
if cam_feed.isOpened():
print("Releasing cam feed")
cam_feed.release()
return "Done"
最后,这是运行烧瓶服务器的代码:
if __name__ == '__main__':
app.run(debug=True)
我的问题是:在收集图像后,如何停止流并关闭网络摄像头?谢谢。
I've implemented a system to capture faces on-the-fly from a live stream using flask and OpenCV. I'm now facing difficulties with closing the stream and releasing the VideoCapture
object. Here is a snippet of my code below:
from flask import Flask, Response, render_template
import cv2, imutils
import face_recognition
from skimage.exposure import is_low_contrast
app = Flask(__name__)
cam_feed = cv2.VideoCapture(0) # to get feed from webcam, use 0 as argument
def gen_frames(): # generate frame by frame from camera
"""
Variable for counting number of images collected
List for saving encodings also declared here
"""
image_counter = 0
name = "John Doe"
known_names = []
known_encodings = []
if not cam_feed.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
success, frame = cam_feed.read() # read the camera frame
if not success:
print("Can't receive frame (stream end?). Exiting ...")
break
else:
ret, frame = cam_feed.read()
frame = imutils.resize(frame, width=640)
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
else:
# face location model can either be HOG or CNN but HOG is faster (but less accurate) and way better if you don't have a GPU
boxes = face_recognition.face_locations(frame, model='hog')
if boxes: # if a face is detected
for (top, right, bottom, left) in boxes:
if (image_counter < 20):
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
encodings = face_recognition.face_encodings(frame, boxes)
known_names.append(name)
known_encodings.append(encodings)
image_counter += 1
else:
break # break while True loop and end stream
ret, buffer = cv2.imencode('.jpg', frame) # encode the frame so that flask can return it as a response in bytes format
frame = buffer.tobytes() # convert each frame to a byte object
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # concat frame one by one and show result
Here are my routes for streaming:
@app.route('/video_feed')
def video_feed():
#Video streaming route. Put this in the src attribute of an img tag
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
When my image count reaches 20, the loop doesn't seem to break because I can see my webcam is still functioning. What I've tried to do is to create another route where I call cam_feed.release()
and I add the route using the link in my index.html
file; here is the code:
@app.route('/done')
def done():
if cam_feed.isOpened():
print("Releasing cam feed")
cam_feed.release()
return "Done"
and finally, here is the code that runs the flask server:
if __name__ == '__main__':
app.run(debug=True)
My question is this: How can I stop the stream and turn off my webcam after I'm done collecting the images? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这是因为您启用了烧瓶应用程序
debug
模式(app.run(debug = true)
),默认情况下将使用Relioader模式。如果启用了重新加载模式,则您的烧瓶应用程序将被加载到单独的过程中,以便根据文件更改连续更新应用程序,这将导致cam_feed = cv.cv2.videocapture(0)
正在正在在两个分离的处理(主和烧瓶应用程序)中两次运行。当您运行cam_feed.release()
时,它仅在运行烧瓶应用程序的过程中关闭CAM,而主进程仍然具有cam_feed
打开。为了避免这种情况,您可以通过访问环境变量Werkzeug_run_main
添加该过程是否为主要过程,该检查是主要进程独有的。此外,您还可以关闭
debug
模式(app.run(debug = false)
)并调用cam_feed = cv2.videocapture(0)
就像您在原始代码中所做的一样I think it is because you enabled flask app the
debug
mode (app.run(debug=True)
) which will use reloader mode by default. If the reloader mode is enabled, your flask application will be loaded in a separate process in order to continuously update the app according to your file changes, which will leads tocam_feed = cv2.VideoCapture(0)
being run twice in two separated processed (main and flask app). When you runcam_feed.release()
, it only close the cam in the process that run the flask application while the main process still hascam_feed
opened. To avoid this scenario, you can add a check for if the process is main by accessing the environment variableWERKZEUG_RUN_MAIN
that is exclusive to main process.Additionally, you can also turn off
debug
mode (app.run(debug=False)
) and callcam_feed = cv2.VideoCapture(0)
like you did in your original code在每个请求中,您在后台运行的真实运行。
更改
为
并确保何时完成请求,
请在调用此方法时使用此方法发布资源,您的WARE循环在后台停止!
In every request, your while True running in the background.
change
to
and be sure when your request is done, release resources with this method
when you call this method, your while loop stop in the background!