Hello
I have created flask app which uses two objects of opencv cameras. At the start I am creating cameras objects and stores them in a list. Added debug print statement just to know that my cameras are created. However just after flask start I can see that only one camera is created and whole app freezes. Checked that on my desktop computer and it's working, but sometimes I can see my debug print four times, instead of two, which is very weird.
Code look's like this:
main.py from flask import Blueprint, render_template, Response, abort, redirect, url_for from flask_login import login_required, current_user from . import db from .CamerasPool import CamerasPool from .models import User
import cv2
main = Blueprint('main', __name__)
# Create two cameras
camerasPool = CamerasPool()
camerasPool.registerCamera(0, False)
camerasPool.registerCamera(1, True)
@main.route('/')
def index():
return render_template('index.html')
@main.route('/profile', methods=["POST", "GET"])
def profile():
if not current_user.is_authenticated:
abort(403)
return render_template('profile.html', name=current_user.name, id=current_user.id)
@main.route('/video_stream/<int:stream_id>')
def video_stream(stream_id):
if not current_user.is_authenticated:
abort(403)
print(f'Current user detection: {current_user.detectionState}')
print(f'Current user fisheye: {current_user.fisheyeState}')
global camerasPool
camera = camerasPool.getCamWithParameters(current_user.detectionState)
return Response(camera.gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
@main.route('/fisheye')
def fisheye():
if not current_user.is_authenticated:
abort(403)
global camerasPool
if current_user.fisheyeState:
current_user.fisheyeState = False
else:
current_user.fisheyeState = True
user = User.query.filter_by(id=current_user.id)
user.fisheyeState = current_user.fisheyeState
db.session.commit()
return redirect(url_for('main.profile', id=current_user.id, user_name=current_user.name))
@main.route('/detection')
def detection():
if not current_user.is_authenticated:
abort(403)
global camerasPool
if current_user.detectionState:
current_user.detectionState = False
else:
current_user.detectionState = True
user = User.query.filter_by(id=current_user.id)
user.detectionState = current_user.detectionState
db.session.commit()
return redirect(url_for('main.profile', id=current_user.id, user_name=current_user.name))
@main.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@main.errorhandler(403)
def page_forbidden(e):
return render_template('403.html'), 403
CamerasPool.py
from .CameraHandler import CameraHandler
import cv2
class CamerasPool:
def __init__(self):
self.__cameras = []
def registerCamera(self, id, detection):
self.__cameras.append(CameraHandler(id, cv2.VideoCapture(0), detection))
print('Camera registered')
def getCamWithParameters(self, detection):
camera = None
for cam in self.__cameras:
if cam.getDetectionState() == detection:
# if cam.getFisheyeState() == fisheye:
camera = cam
break
return camera
and CameraHandler.py import cv2
class CameraHandler():
def __init__(self, id, cam, detectionState):
self.id = id
self.cam = cam
self.current_frame = None
self.__shouldDetect = detectionState
self.__shouldRemoveFisheye = False
print('Camera created')
def __del__(self):
self.cam.release()
def getDetectionState(self):
return self.__shouldDetect
def getFisheyeState(self):
return self.__shouldRemoveFisheye
def __detectFace(self, img):
faces, confidences = cv.detect_face(img)
for face in faces:
(startX, startY) = face[0], face[1]
(endX, endY) = face[2], face[3]
cv2.rectangle(img, (startX, startY), (endX, endY), (0, 255, 0), 2)
return img
def __removeFisheye(self, img):
# TO DO
return img
def __getFrame(self):
rval, frame = self.cam.read()
if rval:
frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
try:
if self.__shouldRemoveFisheye:
frame = self.__removeFisheye(frame)
except:
print('Fisheye effect exception')
try:
if self.__shouldDetect:
frame = self.__detectFace(frame)
except:
print('Face detection exception')
cv2.imwrite('t.jpg', frame)
(flag, encodedImage) = cv2.imencode(".jpg", frame)
self.current_frame = bytearray(encodedImage)
def gen(self):
while True:
self.__getFrame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + self.current_frame + b'\r\n')
I am running it on RPi 4B, with the newest Raspbian. Immediately after start CPU usage on raspberry shows 100%, but I can't believe that something like this is too much for raspberry. If this code is not enough: heres my git with the whole project: Project.
Thanks in advance for the hints