问题描述
在我的烧瓶应用程序中,我经常遇到断管错误(Errno 32)。我有一个在带有相机的RPi上运行的Flask服务器。应用程序非常简单:阅读相机镜框并在网站上显示视频流。但是,我希望有两个摄像头流:一个带对象检测,另一个不带对象检测,因此,为了实现这一点,我创建了两个类来表示它们。他们有带相机框架的队列,他们所做的只是用html生成框架。 Camera和Streams类在线程中工作。
以下是Camera类的外观:
from threading import Thread
from copy import deepcopy
import queue
import cv2
class Camera(Thread):
def __init__(self,cam,normalQue,detectedQue):
Thread.__init__(self)
self.__cam = cam
self.__normalQue = normalQue
self.__detectedQue = detectedQue
self.__shouldStop = False
def __del__(self):
self.__cam.release()
print('Camera released')
def run(self):
while True:
rval,frame = self.__cam.read()
if rval:
frame = cv2.resize(frame,None,fx=0.5,fy=0.5,interpolation=cv2.INTER_AREA)
_,jpeg = cv2.imencode('.jpg',frame)
self.__normalQue.put(jpeg.tobytes())
self.__detectedQue.put(deepcopy(frame))
if self.__shouldStop:
break
def stopCamera(self):
self.__shouldStop = True
以下是normalStream类的外观:
from threading import Thread
import traceback
import cv2
class normalVideoStream(Thread):
def __init__(self,framesQue):
Thread.__init__(self)
self.__frames = framesQue
self.__img = None
def run(self):
while True:
if self.__frames.empty():
continue
self.__img = self.__frames.get()
def gen(self):
while True:
try:
if self.__img is None:
print('normal stream frame is none')
continue
# print(f'Type of self.__img: {type(self.__img)}')
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + self.__img + b'\r\n')
except:
traceback.print_exc()
print('normal video stream genenation exception')
以下是DetectionStream类的外观:
from threading import Thread
import cv2
import traceback
class DetectionVideoStream(Thread):
def __init__(self,framesQue):
Thread.__init__(self)
self.__frames = framesQue
self.__img = None
self.__faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
def run(self):
while True:
if self.__frames.empty():
continue
self.__img = self.__detectFace()
def gen(self):
while True:
try:
if self.__img is None:
print('Detected stream frame is none')
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + self.__img + b'\r\n')
except:
traceback.print_exc()
print('Detection video stream genenation exception')
def __detectFace(self):
retImg = None
try:
img = self.__frames.get()
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = self.__faceCascade.detectMultiScale(gray,1.1,4)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x + w,y + h),(255,0),2)
(_,encodedImage) = cv2.imencode('.jpg',img)
retImg = encodedImage.tobytes()
except:
traceback.print_exc()
print('Face detection exception')
return retImg
这里是我的主要外表:
from flask import Blueprint,render_template,Response,abort,redirect,url_for
from flask_login import login_required,current_user
from queue import Queue
from . import db
from .Camera import Camera
from .normalVideoStream import normalVideoStream
from .DetectionVideoStream import DetectionVideoStream
from .models import User
import cv2
main = Blueprint('main',__name__)
# Queues for both streams
framesnormalQue = Queue(maxsize=0)
framesDetectionQue = Queue(maxsize=0)
print('Queues created')
# RPi camera instance
camera = Camera(cv2.VideoCapture(0),framesnormalQue,framesDetectionQue)
camera.start()
print('Camera thread started')
# Streams
normalStream = normalVideoStream(framesnormalQue)
detectionStream = DetectionVideoStream(framesDetectionQue)
print('Streams created')
normalStream.start()
print('normal stream thread started')
detectionStream.start()
print('Detection stream thread started')
@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,detectionState=current_user.detectionState)
@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}')
global detectionStream
global normalStream
stream = None
if current_user.detectionState:
stream = detectionStream
print('Stream set to detection one')
else:
stream = normalStream
print('Stream set to normal one')
return Response(stream.gen(),mimetype='multipart/x-mixed-replace; boundary=frame')
@main.route('/detection')
def detection():
if not current_user.is_authenticated:
abort(403)
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',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
我通过以下方式启动应用:python3 -m flask run —host=ip —port=port —with-threads
。对我来说很奇怪的是,该应用程序始终可以正常运行。但是当我尝试更改流时,管道显示断开了,并呈现给用户。我在def detection()中更改流,这非常简单,所以我想问题出在其他地方。
在这里出现问题的日志:
127.0.0.1 - - [12/Aug/2020 15:40:06] "GET /video_stream/3 HTTP/1.1" 200 -
Traceback (most recent call last):
File "/Users/piotrekgawronski/Library/Python/3.7/lib/python/site-packages/werkzeug/serving.py",line 295,in execute
write(data)
File "/Users/piotrekgawronski/Library/Python/3.7/lib/python/site-packages/werkzeug/serving.py",line 276,in write
self.wfile.write(data)
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/python3.framework/Versions/3.7/lib/python3.7/socketserver.py",line 799,in write
self._sock.sendall(b)
brokenPipeError: [Errno 32] broken pipe
During handling of the above exception,another exception occurred:
Traceback (most recent call last):
File "/Users/piotrekgawronski/Documents/programowanie/git_projects/Peephole/server/normalVideoStream.py",line 29,in gen
b'Content-Type: image/jpeg\r\n\r\n' + self.__img + b'\r\n')
GeneratorExit
normal video stream genenation exception
Exception ignored in: <generator object normalVideoStream.gen at 0x11b8d7750>
RuntimeError: generator ignored GeneratorExit
之后,我可以看到cpu使用率为100%,整个应用程序开始出现滞后。我相信我的RPi足够强大,可以正确处理此应用程序(RPi 4B 4GB)。
也许有人知道问题出在哪里?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)