Search code examples
pythonopencvflaskrefresh

Python (Flask) refresh on page gives problem with OpenCv camera object


I have python app with Flask framework. I display video stream from camera on my index page like that:

  <img id="bg2" src="{{ url_for('video') }}" width="400px" height="400px">

Everything works great, but if I directly refresh the page strange things begin to happen. If I go to another page and come back to index everything works too. These are the errors that I get (it's one of them every time):

error for object 0x7fc579e00240: pointer being freed was not allocated

Assertion fctx->async_lock failed at libavcodec/pthread_frame.c:155

or

segmentation fault 11

This is endpoint where the data is coming from:

@app.route('/video')
def video():
    return Response(video_stream(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

def video_stream():
    global video_camera # Line 1 ----------------------

    if video_camera == None: # Line 2 ----------------------
        video_camera = VideoCamera()

    while True:
        frame = video_camera.get_frame()

        if frame != None:
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

If I remove the commented lines everything works but it's slow and heavy because of the constant initialization of new objects.

Here is my camera object if it will help

class VideoCamera(object):
    def __init__(self):
        self.cap = cv2.VideoCapture(0)

    def __del__(self):
         self.cap.release()

    def get_frame(self):
        ret, frame = self.cap.read()
        print(ret)
        if ret:
            ret, jpeg = cv2.imencode('.jpg', frame)
            return jpeg.tobytes()

Solution

  • Ok, so one solution is to not use global object. This is the new video_stream() function:

    def video_stream():
        video_camera = VideoCamera();
        ...
    

    Another possible solution is to use threading lock like this :

    def video_stream():
        global video_camera
        if video_camera == None:
            video_camera = VideoCamera()
    
        while True:
            with lock:
                frame = video_camera.get_frame()
    
                if frame != None:
                    global_frame = frame
                    yield (b'--frame\r\n'
                           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')