如何从烧瓶关闭OpenCV视频流

发布于 2025-01-30 03:10:30 字数 3345 浏览 2 评论 0原文

我已经实施了一个系统,可以使用烧瓶和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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朕就是辣么酷 2025-02-06 03:10:30

我认为这是因为您启用了烧瓶应用程序debug模式(app.run(debug = true)),默认情况下将使用Relioader模式。如果启用了重新加载模式,则您的烧瓶应用程序将被加载到单独的过程中,以便根据文件更改连续更新应用程序,这将导致cam_feed = cv.cv2.videocapture(0)正在正在在两个分离的处理(主和烧瓶应用程序)中两次运行。当您运行cam_feed.release()时,它仅在运行烧瓶应用程序的过程中关闭CAM,而主进程仍然具有cam_feed打开。为了避免这种情况,您可以通过访问环境变量Werkzeug_run_main添加该过程是否为主要过程,该检查是主要进程独有的。

import os
if os.environ.get('WERKZEUG_RUN_MAIN'):
    cam_feed = cv2.VideoCapture(0)

此外,您还可以关闭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 to cam_feed = cv2.VideoCapture(0) being run twice in two separated processed (main and flask app). When you run cam_feed.release(), it only close the cam in the process that run the flask application while the main process still has cam_feed opened. To avoid this scenario, you can add a check for if the process is main by accessing the environment variable WERKZEUG_RUN_MAIN that is exclusive to main process.

import os
if os.environ.get('WERKZEUG_RUN_MAIN'):
    cam_feed = cv2.VideoCapture(0)

Additionally, you can also turn off debug mode (app.run(debug=False)) and call cam_feed = cv2.VideoCapture(0) like you did in your original code

痴梦一场 2025-02-06 03:10:30

在每个请求中,您在后台运行的真实运行。

更改

while True:

while cap.isOpened()

并确保何时完成请求,

cap.release()

请在调用此方法时使用此方法发布资源,您的WARE循环在后台停止!

In every request, your while True running in the background.

change

while True:

to

while cap.isOpened()

and be sure when your request is done, release resources with this method

cap.release()

when you call this method, your while loop stop in the background!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文