简体   繁体   中英

VIDEOIO ERROR from opencv ONLY when streaming with flask

I know that this is an opencv error, and I know that Flask has nothing to do with opencv. However, please stick with me through the end. I'm getting this really weird error ONLY when I'm streaming the CV frames:

VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV
Unable to stop the stream: Device or resource busy

My code:

// my camera_detector class does some AI works on the camera frame, other than that nothing special
camera = camera_detector(my_arguments)

@app.route('/')
def index():
    return render_template('index.html')

def gen(camera):
    while True:
        print('getting frame')
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/feed')
def video_feed():
    return Response(gen(camera), mimetype='multipart/x-mixed-replace; boundary=frame')

Now here is why I said this only happens with Flask, if I just grab the camera frame like this:

while True:
  frame = camera.get_frame()

without ever using flask, everything runs just fine o_0

If it makes any difference, I'm using python3.7 on the pi4. My camera also does some AI works on camera_frame produced by open cv, draw boxes, labels, before returning the frame to Flask:

def get_frame(self):
  ret, frame = self.camera.read()
  # processing, does AI works, draw boxes and labels
  ret, jpeg = cv2.imencode('.jpg', frame)
  return jpeg.tobytes()

[Edit] camera info if it helps:

{20-04-22 15:39}raspberrypi:~/detect pi% v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
        [1]: 'MJPG' (Motion-JPEG, compressed)

[SOLVED]: Answer is below for those who are interested.

For those who got had the same issue, I found out what was causing it. The problem was that I created a camera instance like this:

camera = camera_detector(my_arguments)

and then passed that into my route function:

@app.route('/feed')
def video_feed():
    return Response(gen(camera), mimetype='multipart/x-mixed-replace; boundary=frame')

Turn out opencv did not like that so much. I found this very odd, but it works fine after I changed it to:

@app.route('/feed')
def video_feed():
    return Response(gen(camera_detector(my_arguments)), mimetype='multipart/x-mixed-replace; boundary=frame')

Any body who have an explanation for this would be nice!

It looks like you're borrowing code fromhttps://blog.miguelgrinberg.com/post/video-streaming-with-flask

Comparing the two, your snippet has an extra \r\n' at the end of each frame. Try removing that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM