I'm making a large program that has to use a webcam via OpenCV
and also has to act as a REST
server. The functionality of the two is not related, i.e. I'm not asking how to send a message via REST
, that is a different topic entirely.
The concern I'm having is if I start up a Flask app acting as a REST server, then the webcam can't connect. Here is small example that demonstrates the concern:
# test.py
import numpy as np
import cv2
from flask import Flask, jsonify, request
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
flaskApp = Flask(__name__)
def main():
flaskApp.run(debug=True)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Display the resulting frame
cv2.imshow('frame', frame)
keyPress = cv2.waitKey(10)
if keyPress == ord('q'):
break
# end if
# end while
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
# end function
@flaskApp.route('/post_number', methods=['POST'])
def post_number():
if not request.json or not 'data' in request.json:
print('error')
# end if
if request.json is None:
print('error, request.json is None')
# end if
if not 'data' in request.json:
print('error, \'data\' is not in request.json')
# end if
data = request.json['data']
print('data = ' + str(data))
return jsonify({'data': data}), 201
# end function
if __name__ == '__main__':
main()
If I comment out the flaskApp.run(debug=True)
line then the webcam connects and shows streaming frames in the OpenCV window as expected. However with the flaskApp.run(debug=True)
included as above, the OpenCV window never appears and I get this output:
$ python3 test.py
* Serving Flask app "cam_test" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
[ WARN:0] global /io/opencv/modules/videoio/src/cap_v4l.cpp (887) open VIDEOIO(V4L2:/dev/video0): can't open camera by index
* Debugger is active!
* Debugger PIN: 297-109-197
So the Flask
app starts successfully (I can even successfully send POST messages via a test client) but the OpenCV windows never appears, and please note the [ WARN:0] global /io/opencv/modules/videoio/src/cap_v4l.cpp (887) open VIDEOIO(V4L2:/dev/video0): can't open camera by index
line in the above output.
I'm using Ubuntu 18.04 if that matters. Video for linux (4VL) is the standard way (perhaps the only way?) to read from webcams on Ubuntu.
It seems there is a conflict between Flask
and OpenCV
/ V4L
for some resource, however I'm not sure what that resource is. Is there a way to configure Flask so it does not use the same resources as an OpenCV webcam, or some other way to resolve this so this example app can receive a webcam feed and act as a REST server at the same time?
--- Edit ---
@dtc just pointed out an oversight I made in the comments, that being that execution never gets past the flaskApp.run(debug=True)
line, so even if the webcam connected the OpenCV window would never show. This begs the question as to how the small example should be set up. I can't start flaskApp
as a separate multi-process because I need the the REST message received and the info for the image to both be accessed, and spawning a multiprocess would make the memory separate.