我正在开发基于机器学习的应用程序的演示器。
为了简单起见,我们假设:
我正在使用两个文件,run_ml.py 和 video_stream_flask.py。
run_ml.py 文件基本上从相机捕获图像,进行所有处理,并在原始图像上绘制内容。然后,最终图像放入队列中。
此队列与其他参数一起传递给运行 video_stream_flask.py 的 main() 的子进程。
这里的目标是从队列中获取图像,并将其显示在网页上。事实上,最初的目标只是能够在网页上显示最终的图像。
这基本上是 video_stream_flask.py 的代码:
import subprocess
from subprocess import PIPE
from flask import Flask, Response, render_template
import cv2
import multiprocessing
import logging
VERBOSE_DEBUG = 0
if not VERBOSE_DEBUG:
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
TARGET = None
queue=multiprocessing.Queue()
global image
image=cv2.imread("output.jpg")
def get_queue(queue):
try:
data = queue.get(block=False)
print("Data retrieved from queue")
return data
except Exception as e:
# print("except : ",e)
# print("Queue is empty, no data to retrieve.")
return None
def get_current_ip():
"""
Get current IP Address by testing IP route
"""
process_get_ip = subprocess.Popen(["ip route get 1.2.3.4 | awk '{print $7}'"], shell=True, stdout=PIPE)
output = process_get_ip.communicate()[0].decode("utf-8")
return output
app = Flask(__name__)
@app.route('/')
def index():
return render_template("index.html")
def gen():
while True:
global image
global queue
# image = cv2.imread("output.jpg")
image=get_queue(queue)
if image is not None:
image = cv2.flip(image, 1)
ret, jpeg = cv2.imencode('.jpg', image)
frame = jpeg.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
print("Frame sent")
@app.route('/video_feed')
def video_feed():
return Response(gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
def main(lan, target,QUEUE):
global TARGET
TARGET = target
global queue
queue=QUEUE
if bool(lan):
subprocess.Popen(["ifconfig eth0 10.0.0.20 netmask 255.255.255.0 up"], shell=True, stdout=PIPE)
print("\nCONNECT TO : 10.0.0.20:5000")
app.run(host="10.0.0.20", port=5000, threaded=True)
else:
if TARGET:
ip_address = get_current_ip()[:-2]
print("\nCONNECT TO : " + repr(ip_address)[1:-1] + ":5000")
app.run(host=ip_address, port=5000, threaded=True)
else:
print("\nCONNECT TO : localhost:5000")
app.run(host="localhost", port=5000, threaded=True) #, use_reloader=False
我面临的问题是延迟。在我的网页上查看结果时,我立即遇到了近十秒的延迟。
我不明白为什么。
我正在运行一个基本示例,其中图像是从相机捕获的,直接在同一文件和同一进程中,并且它运行完美。
但是在这里,当我尝试从主进程中检索图像时,它会滞后。
我尝试了其他方法,例如将图像保存在文件系统中并再次读取它,使用互斥体来确保不存在冲突。
当我运行我的应用程序时,我可以在输出中看到图像一旦准备好就生成了:
Data retrieved from queue
Frame sent
Model Inference time: 926.544ms
Data put into queue successfully.
Data retrieved from queue
Frame sent
Model Inference time: 923.772ms
Data put into queue successfully.
Data retrieved from queue
Frame sent
Model Inference time: 914.210ms
Data put into queue successfully.
Data retrieved from queue
Frame sent
您知道问题出在哪里吗?或者如何做我想做的事情,这意味着如何流式传输在另一个脚本中生成的图像,并在准备好时仅流式传输一次?
非常感谢,
我意识到问题不是来自flask,而是来自OpenCV捕获。
有关根本原因的说明可在此处找到:由于捕获缓冲区导致 OpenCV VideoCapture 滞后