计算机视觉---flask框架封装目标检测,应用线程提高程序运行效率

1.前言

上一篇文章flask部署 目标检测算法中讲到可以将检测算法封装到flask框架中进行web端展示,但在实际应用中发现一些问题并进行了解决,在本文中进行补充。

2.利用线程,提高flask程序运行效率

flask web端访问时,每次都会从头加载程序,导致每次访问页面刷新率很低或者需要等好一段时间才能刷新成功,可以利用线程达到仅在程序启动后第一次从头加载程序,而后刷新获取到实时视频流即可,不再从头加载程序。

实例(部分代码):

import threading
from flask import Flask, render_template, Response
app = Flask(__name__)

lock = threading.Lock()  #线程锁
result_img = None   #初始化检测结果,并定义为全局变量  

#zed获取视频,并进行目标检测,获取检测结果
def camera(cfgfile, weightfile):
    import cv2
    zed = sl.Camera()
    init_params = sl.InitParameters()
    init_params.camera_resolution = sl.RESOLUTION.HD720  #分辨率,分辨率越高,成像后的图像像素数就越高,图像就越清晰。
    init_params.camera_fps = 30  # Set fps at 30,帧率越高,视频越流畅,最低是30 

(。。。省略部分代码。。目标检测过程代码。。。。)
    
    ##结尾,获取检测结果图片,设为全局变量,便于后续函数调用
    global result_img 
    result_img = plot_boxes_cv2(img, boxes[0], savename=None, class_names=class_names)


##相机推流: 获取检测结果视频流,并返回
def generate():
    global result_img, lock  #result_img 设置为全局变量
    while True:
        with lock:
            if result_img is None:
                continue
            (flag, encodedImage) = cv2.imencode(".jpg", result_img)   #将 OpenCV 图像转换为 JPEG 图像
            if not flag:
                continue
        # yield the output frame in the byte format
        yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + bytearray(encodedImage) + b'\r\n')


#相机拉流:调用generate函数实现向网页返回每一帧图片的编码,将视频流传输到web浏览器
@app.route("/tt_demo")
def tt_demo():
    return Response(generate(),mimetype="multipart/x-mixed-replace; boundary=frame")


# 前端页面
@app.route('/bdlf')
def index():
    return render_template("bdlf.html")

#主函数,线程调用
if __name__ =="__main__":
    host="0.0.0.0"
    port=7000
    debug=False
    use_reloader=False
    t = threading.Thread(target=camera, args=(args.cfgfile, args.weightfile), daemon = True)
    # t.daemon()
    t.start() #线程启动
   # app.run(host,port,debug,use_reloader)
   t2 = threading.Thread(target=app.run, args=(host,port,debug,use_reloader))
   t2.start()

前端引用

   ##与后端入口函数名保持一致
3.知识小记
(1)线程传参
  • 使用args 传递参数 threading.Thread(target=sing, args=(10, 100, 100))
  • 使用kwargs传递参数 threading.Thread(target=sing, kwargs={“a”: 10, “b”:100, “c”: 100})
  • 同时使用 args 和 kwargs 传递参数 threading.Thread(target=sing, args=(10, ), kwargs={“b”: 100,“c”: 100})
(2) 守护线程
  • 设置守护主线程有两种方式:
    threading.Thread(target=show_info, daemon=True)
    线程对象.setDaemon(True)
  • 一定在线程执行start()之前
  • 守护线程就是会随着主线程的结束而结束。即:主进程在其代码结束后,守护进程在此时就被回收;主进程会一直等非守护子进程都运行完毕后回收子进程的资源
  • 主线程在有非守护线程存在的情况下,设置守护线程作用不大
(3)查看线程数
  • threading.enumerate()返回当前存活的threading.Thread线程对象列表
(4)线程锁
with temp_lock:
    # do something...

相当于以下代码

temp_lock.acquire() #上锁
try:
   # do something...
finally:
   temp_lock.release() #释放锁

也就是在运行的时候对语句块的内容上锁了,运行完后再释放了这个锁。

计算机视觉---flask框架封装目标检测,应用线程提高程序运行效率_第1张图片 图片怎么居中啊???

你可能感兴趣的:(计算机视觉,flask,目标检测)