【ZED2-3】python同时实现websockets与flask

article/2025/10/16 0:47:55

上篇博客【ZED-2】基于WebSockets库,通过多线程方式推送数据流_WXG1011的博客-CSDN博客采用多线程方式,基于websockets库实现数据流的推送,这篇博客主要实现将前端(nx板)代码移植到flask框架中,通过http方式展示,便于其他客户端访问,主要难点在于flask app的ip地址与websockets ip地址冲突。

基础介绍-flask框架

注:该Demo解决了通过http访问时,视频流卡顿的问题。

flask_demo.py

# 测试rtsp视频流在前端的稳定性
from flask import Flask, render_template, Response
import cv2
import queue
import threading
import timeapp = Flask(__name__)@app.route('/video_feed')
def video_feed():# 通过将一帧帧的图像返回,就达到了看视频的目的。multipart/x-mixed-replace是单次的http请求-响应模式,如果网络中断,会导致视频流异常终止,必须重新连接才能恢复return Response(Display(), mimetype='multipart/x-mixed-replace; boundary=frame')@app.route('/')
def index():return render_template('index.html')q = queue.Queue()def Receive():print("start Reveive")cap = cv2.VideoCapture(0)# cap = cv2.VideoCapture("rtsp://admin:sdiit888@10.1.93.5/Streaming/Channels/1")while True:q.put(cap.read()[1])# 移除队列中的旧图q.get() if q.qsize() > 1 else time.sleep(0.01)def Display():print("Start Displaying")while True:if q.empty() != True:frame = q.get()ret, buffer = cv2.imencode('.jpg', frame)frame = buffer.tobytes()# 使用yield语句,将帧数据作为响应体返回,content-type为image/jpegyield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')if __name__ == '__main__':threads = [threading.Thread(target=Receive), threading.Thread(target=Display)]for t in threads:t.start()for t in threads:t.join()threading.Thread(target=app.run(debug=True)).start()

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>AI功能展示</title><style>.divcss5{text-align: center}</style>
</head>
<body><h1 align="center"><font size="6" face="arial" color="black">视频展示</font></h1><div class="divcss5"><img src="{{ url_for('video_feed') }}" height="900px" width="3400px">#}</div><h1 align="center"><font size="5" face="arial" color="black">*****</font></h1>
</body>
</html>

下面进入本博客重点!!!

nx板代码,为后端(服务器)提供视频流,并叠加显示推送的检测信息。

from flask import Flask, render_template, Response
import asyncio
import websockets
import threading
import pyzed.sl as sl
import cv2
import json
import numpy as npreceive_dict = []
receive_location = []
receive_count = ""
img = Noneinit = sl.InitParameters()
init.camera_resolution = sl.RESOLUTION.HD720
init.depth_mode = sl.DEPTH_MODE.NONE
cam = sl.Camera()
status = cam.open(init)
if status != sl.ERROR_CODE.SUCCESS:print(repr(status))exit(1)runtime = sl.RuntimeParameters()
mat = sl.Mat()stream = sl.StreamingParameters()
stream.codec = sl.STREAMING_CODEC.H264
stream.bitrate = 4000
status = cam.enable_streaming(stream)
if status != sl.ERROR_CODE.SUCCESS:print(repr(status))exit(1)print("  Quit : CTRL+C\n")# Websocket服务端
class WebsocketChatServer():def __init__(self):passasync def run(self, port):start_server = websockets.serve(self.handler, "", port, ping_interval=None)await start_serverprint(f'  > server start ok! on port {port}')await asyncio.Future()           # run foreverasync def handler(self, websocket, path):global receive_dict, receive_location, receive_countasync for message in websocket:receive_data = messagereceive_count = json.loads(receive_data)["person_count"]receive_dict = json.loads(receive_data)["detection_box"]receive_location = json.loads(receive_data)["location"]# print(receive_count)# 初始化和定义flask
app = Flask(__name__)@app.route('/')
def index():test_dict = 'Welcome to use the impediment perception web service!'return test_dict@app.route("/demo")
def demo():return render_template("index.html")@app.route("/video_feed")
def video_feed():return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame")# main函数主要实现向后端(服务器)推送视频流,并在视频流上叠加后端(服务器)推送的检测信息
def main():global imgwhile True:err = cam.grab(runtime)if (err == sl.ERROR_CODE.SUCCESS):cam.retrieve_image(mat, sl.VIEW.LEFT)# image = cv2.cvtColor(mat.get_data(), cv2.COLOR_RGB2BGR)# image_cv = mat.get_data()# image = image_cv[:, :, 0:3]image = mat.get_data()if len(receive_location) != 0 and len(receive_dict) != 0:if len(receive_location) != 1:last_data = receive_location[len(receive_location)-1]for i in range(len(last_data)):location_dict = last_data[i]# dict2strlocation_str = json.dumps(location_dict)# str2jsonlocation_json = json.loads(location_str)# print(location_json)if receive_count != 0:text = "(" + str(location_json['x']) + " " + str(location_json['y']) + " " + str(location_json['z']) + ")"cv2.circle(image, (int(location_json['x0']), int(location_json['y0'])), 2, (0, 0, 255),thickness=3)cv2.putText(image, text, (int(location_json['x0']), int(location_json['y0'])),cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 0, 255), 2)else:if len(receive_location[0]) != 0:# print(receive_location)location_str = json.dumps(receive_location[0][0])location_json = json.loads(location_str)if receive_count != 0:text = "(" + str(location_json['x']) + " " + str(location_json['y']) + " " + str(location_json['z']) + ")"cv2.circle(image, (int(location_json['x0']), int(location_json['y0'])), 2, (0, 0, 255),thickness=3)cv2.putText(image, text, (int(location_json['x0']), int(location_json['y0'])),cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 0, 255), 2)if len(receive_dict) == 1:# print(receive_dict)if len(receive_dict[0]) != 0:box_str = json.dumps(receive_dict[0][0])box_json = json.loads(box_str)if receive_count != 0:cv2.putText(image, "person", (int(box_json["x1"]), int(box_json["y1"])-5),cv2.FONT_HERSHEY_PLAIN, 2.0, (255, 0, 0), 2)img = cv2.rectangle(image, (int(box_json["x1"]), int(box_json["y1"])),(int(box_json["x2"]), int(box_json["y2"])), (255, 0, 0), 2)else:img = imagecv2.imshow("ZED", img)key = cv2.waitKey(1)else:last_box = receive_dict[len(receive_dict) - 1]# print(last_box)for i in range(len(last_box)):# print(receive_dict[len(receive_dict) - 1])box_dict = last_box[i]# dict2strbox_str = json.dumps(box_dict)# str2jsonbox_json = json.loads(box_str)# print(box_json)if receive_count != 0:cv2.putText(image, "person", (int(box_json["x1"]), int(box_json["y1"]) - 5),cv2.FONT_HERSHEY_PLAIN, 2.0, (255, 0, 0), 2)img = cv2.rectangle(image, (int(box_json["x1"]), int(box_json["y1"])),(int(box_json["x2"]), int(box_json["y2"])), (255, 0, 0), 2)else:img = imagecv2.imshow("ZED", img)key = cv2.waitKey(1)# else:#     cv2.imshow("ZED", image)#     key = cv2.waitKey(1)else:key = cv2.waitKey(1)cam.disable_streaming()cam.close()def generate():# global img_result, lock# loop over frames from the output streamwhile True:# wait until the lock is acquired# with lock:if img is None:continue# print("-----------------")# cv2.imshow("ZED", img)# key = cv2.waitKey(1)(flag, encodedImage) = cv2.imencode(".jpg", img)if not flag:continue# yield the output frame in the byte formatframe = encodedImage.tobytes()# yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +#       bytearray(encodedImage) + b'\r\n')yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +frame + b'\r\n')# 启动函数
def main01():# 在新线程中启动flask# print(app.url_map)# 启动websocket serverprint('> starting server...')server = WebsocketChatServer()tasks = [server.run(2333),]# loop = asyncio.get_event_loop()loop = asyncio.new_event_loop()asyncio.set_event_loop(loop)try:loop.run_until_complete(asyncio.wait(tasks))except KeyboardInterrupt:for task in asyncio.Task.all_tasks():task.cancel()loop.stop()loop.run_forever()loop.close()if __name__ == '__main__':flask_thread = threading.Thread(target=app.run, args=('0.0.0.0', 5000))flask_thread.start()# socket_thread = threading.Thread(target=main)# socket_thread.start()threads = [threading.Thread(target=main), threading.Thread(target=main01)]for t in threads:t.start()for t in threads:t.join()

:asyncio.wait()搜集所有任务;

运用线程,首先要生成一个loop对象,然后loop.run_xxx()就可以运行线程了,而如何创建这个loop, 方法有两种:1、对于主线程是loop=get_event_loop();2、对于其他线程需要首先loop=new_event_loop(),然后set_event_loop(loop)new_event_loop()是创建一个event loop对象,而set_event_loop(eventloop对象)是将event loop对象指定为当前线程的event loop。一个线程任务,不能运行在两个及两个以上不同的循环中一个循环体可以运行多个不同的协程任务。

index.html

<html><head><link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"><title>感知效果示意</title><style type="text/css">.item .pic { float:left;margin-left:39%;width:30px;height:30px; }.item .content {float:left;width:290px;}.item .pic2 { float:left;margin-left:0px;width:30px;height:30px; }</style><div class="item"><div class="pic"><img src="{{ url_for('static', filename='favicon.ico') }}" width='30px' height='30px'></div><div class="content" style="font-size:22px; ">&ensp;感知效果&ensp; </div><div class="pic2"><img src="{{ url_for('static', filename='favicon.ico') }}" width='30px' height='30px'></div></div><br><br></head><body><div style="text-align: center;" ><img src="{{url_for('video_feed')}}" width='1400px' height='800px'></div><div style="font-size:16px; text-align: center;">Copyright © ***</div></body>
</html>

 后端(服务器)代码与博客【ZED-2】基于WebSockets库,通过多线程方式推送数据流_WXG1011的博客-CSDN博客一致,这里不再粘贴。

参考链接 nohtypython | 同时使用flask和websockets - Mz1 - 博客园p


http://chatgpt.dhexx.cn/article/oAiolF9N.shtml

相关文章

【burpsuite安全练兵场-客户端16】测试WebSockets安全漏洞-3个实验(全)

前言&#xff1a; 介绍&#xff1a; 博主&#xff1a;网络安全领域狂热爱好者&#xff08;承诺在CSDN永久无偿分享文章&#xff09;。 殊荣&#xff1a;CSDN网络安全领域优质创作者&#xff0c;2022年双十一业务安全保卫战-某厂第一名&#xff0c;某厂特邀数字业务安全研究员&…

在python中使用websockets

WebSocket (WebSocket) Websocket is a communications protocol, providing full-duplex bi-directional communication over a single TCP connection. Websocket是一种通信协议,可通过单个TCP连接提供全双工双向通信。 To understand Websockets, first, we have to have …

django3 websockets

一、概述 现在Django 3.0附带了对ASGI的支持&#xff0c;将Websockets添加到Django应用中不需要任何额外的依赖关系。 在本文中&#xff0c;您将学习如何通过扩展默认的ASGI应用程序来使用Django处理Websocket。 我们将介绍如何在示例ASGI应用程序中处理Websocket连接&#xff…

websockets_WebSockets简介

websockets WebSockets are an alternative to HTTP communication in Web Applications. WebSocket是Web应用程序中HTTP通信的替代方法。 They offer a long lived, bidirectional communication channel between client and server. 它们在客户端和服务器之间提供了长期的双…

尝试Python的websockets库的最基础功能

目标 尝试最简单的代码创建一个服务器并在客户端收发信息。 主要参考的是官方文档的首页&#xff1a;https://websockets.readthedocs.io/ &#xff08;还需要 asyncio 库的一些知识&#xff0c;可见之前的博客 翻译《使用asyncio的一个指南》作者&#xff1a;Andrew Crozier…

python使用websockets库

python使用websockets库 serve:在server端使用&#xff0c;等待客户端的连接。如果连接成功&#xff0c;返回一个websocket。 connect: 在client端使用&#xff0c;用于建立连接。 send:发送数据 recv:接收数据 close:关闭连接 服务端 #!/usr/bin/python3 # 主要功能&am…

什么是WebSockets!?

到目前为止&#xff0c;我们已经深入到实时世界&#xff0c;因为许多应用程序使用实时数据。 现在正是以技术立场解释所有导致这一点的事件的时候了。 所以&#xff0c;这里...... 目前&#xff0c;应用程序正在从利用数据库中的陈旧数据或在实际事件之后的实时体验中事…

WebSockets介绍

Web sockets定义为在servers和clients之间的双向连接。意味着servers和clients可以同时交流并发送数据。这种协议是从底层就是双工连接。Web sockets技术上得到了质的飞跃。 握手是一个过程&#xff0c;确保server与client同步。握手是Web Socket protocol的基础概念。 下面的图…

websockets_将WebSockets与Node.js结合使用

websockets WebSockets are an alternative to HTTP communication in Web Applications. WebSocket是Web应用程序中HTTP通信的替代方法。 They offer a long lived, bidirectional communication channel between client and server. 它们在客户端和服务器之间提供了长期的双…

各大公司数据结构与算法面试题解答(一)

还有一年就要找工作了&#xff0c;从现在开始找些公司的数据结构和算法的题来做一做&#xff0c;不定时贴出笔试面试题代码。 1.创新工场&#xff1a; 求一个数组的最长递减子序列比如{9&#xff0c;4&#xff0c;3&#xff0c;2&#xff0c;5&#xff0c;4&#xff0c;3&…

数据结构面试题整理

一 数据结构 1.你熟悉什么数据结构&#xff1f; 数组 链表 栈 队列 哈希 二叉树 二叉查找树 二叉堆 b树 b树 2.b树 b树 b*树 b和b都是节点可以有很多子节点&#xff0c;区别是b树所有的节点都可以存储关键字&#xff0c;而b树只有叶子节点存储关键字&#xff0c;适用于数据库…

数据结构与算法三十题,弄懂这些面试就够了!

https://www.toutiao.com/a6649963989537128967/ 2019-01-24 15:36:35 国外 IT 教育学院 Educative.io 创始人 Fahim ul Haq 写过一篇过万赞的文章《The top data structures you should know for your next coding interview》,总结了程序员面试中需要掌握的 8 种数据结构知识…

数据结构与算法面试知识点汇总(超全)

文章目录 一、哈希函数和哈希表01 哈希函数02 哈希表 二、布隆过滤器三、一致性哈希四、并查集01 具体实现02 优化03 代码实现 五、前缀树&#xff08;trie树&#xff09;六、B树和B树七、线段树01 线段树的优势02 线段树实现 一、哈希函数和哈希表 01 哈希函数 哈希函数&…

《数据结构》十道链表经典面试题多种方法深度解析

目录 ⛰️一、题目解析 &#x1f5fb;1.1删除链表中等于给定值 val 的所有节点&#xff08;力扣&#xff09; &#x1f5fb;1.2反转一个单链表。&#xff08;力扣&#xff09; &#x1f5fb;1.3给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有…

数据结构和算法常见面试问题总结,含答案

0. 写在前面 总导航在此 这些问题是我备考数据结构和算法的过程中&#xff0c;详细总结的常见面试问题和答案。逐个搜索并记录下来&#xff0c;花了很大的精力&#xff01;如果想要获取源文件的话&#xff0c;可以关注我的微信公众号&#xff1a;小梁说代码&#xff0c;获取嘿…

(六)数据结构面试必问

什么是链表、队列、栈&#xff1f; 链表&#xff1a; 当需要存储多个相同数据类型的时候&#xff0c;可以使用数组存储&#xff0c;数组可以通过下标直接访问&#xff0c;但数组有个缺点就是无法动态的插入或删除其中的元素&#xff08;特别是操作第一个位置上的元素&#xff…

数据结构常见面试题

链表是最基本的数据结构&#xff0c;面试官也常常用链表来考察面试者的基本能力&#xff0c;而且链表相关的操作相对而言比较简单&#xff0c;也适合考察写代码的能力。链表的操作也离不开指针&#xff0c;指针又很容易导致出错。综合多方面的原因&#xff0c;链表题目在面试中…

面试中常见的数据结构

上次在面试时被面试官问到学了哪些数据结构&#xff0c;那时简单答了栈、队列/(ㄒoㄒ)/~~其它就都想不起来了&#xff0c;今天有空整理了一下几种常见的数据结构&#xff0c;原来我们学过的数据结构有这么多~ 首先&#xff0c;先来回顾下C语言中常见的基本数据类型吧O(∩_∩)O …

数据结构算法常见面试考题

&#xff08;1&#xff09; 红黑树的了解&#xff08;平衡树&#xff0c;二叉搜索树&#xff09;&#xff0c;使用场景 把数据结构上几种树集中的讨论一下&#xff1a; 1.AVLtree 定义&#xff1a;最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为…

八大数据结构及常见面试题

几乎所有的问题都需要面试者对数据结构有深刻的理解。无论你是初入职场的新兵(刚从大学或者编程培训班毕业)&#xff0c;还是拥有几十年经验的职场老鸟。 即便是对于一些非常基础的工作来说&#xff0c;学习数据结构也是必须的。那么&#xff0c;就让我们先从一些基本概念开始入…