用Maixcam制作的HTTP推流
1. 整体架构摄像头采集camera.Camera持续读取图像帧。工作线程Server.stream_worker负责不断从摄像头获取最新图像并压缩为JPEG通过事件通知主线程或HTTP请求。Flask HTTP服务提供/stream路由返回一个multipart/x-mixed-replace响应将JPEG帧逐个发送。线程同步使用threading.Eventimage_event协调工作线程和HTTP生成器之间的数据传递。2. 关键组件说明2.1Server类__init__初始化事件、照片保存路径并绑定Flask路由。stream_worker工作线程函数循环执行。get_stream生成器函数用于构建HTTP流。http_streamFlask路由处理器返回一个Response对象将get_stream生成器作为响应体并设置MIME类型为multipart/x-mixed-replace; boundaryframe。start_server启动工作线程和Flask开发服务器通过werkzeug的make_server在独立线程中运行。stop_server停止服务。2.2 Flask路由客户端访问http://设备IP:8080/stream即可开始接收JPEG图像流。3. 推流工作流程3.1 服务器启动阶段server Server()创建实例。server.start_server()执行启动stream_worker线程守护线程。启动Flask服务器线程守护线程。3.2 视频流处理阶段工作线程持续运行读取摄像头帧 → 编码JPEG → 设置image_event。无论是否有HTTP客户端该线程始终在运行保证最新图像随时可用。HTTP请求处理当有客户端请求/stream时Flask调用http_stream它返回一个Response其迭代器是get_stream生成器。生成器在每次迭代中等待image_event一旦被设置立即生成一个完整的multipart帧并yield。浏览器解析该流每个帧作为一张图片显示实现实时视频效果。3.3 同步机制image_event是threading.Event对象用于两个线程间的信号传递生产者工作线程每次捕获并编码完一帧后调用set()。消费者HTTP生成器调用wait()阻塞直到生产者set()后继续然后调用clear()重置准备等待下一帧。这种方式确保了生成器每次返回的都是最新的一帧图像且不会重复或丢失帧当没有客户端时工作线程依然运行但事件可能多次设置生成器只在有请求时才消费。注代码中有部分代码为单目测距的代码以及串口打印的代码可以自行裁剪。github链接https://github.com/T-T-sys/Distance.git# 导入必要的库 import socket,struct from typing import Text import threading as th import os from maix import camera, display, app, image, network,nn,time,touchscreen from flask import Flask, Response, jsonify, send_from_directory from flask_cors import CORS from werkzeug.serving import make_server from maix.v1.machine import UART # 初始化YOLOv5目标检测模型指定模型路径和启用双缓冲以提高性能 detector nn.YOLOv5(model/root/models/yolov5s.mud, dual_buffTrue) #串口 seUART(/dev/ttyS0, 115200) # 初始化摄像头、显示屏和触摸屏 disp display.Display() # 初始化摄像头设置分辨率为 640x480格式为 YVU420SP一种 YUV 格式 cam camera.Camera(640, 480, image.Format.FMT_YVU420SP) # 为摄像头添加一个通道将其输出调整为显示屏的宽度和高度用于显示 cam2 cam.add_channel(disp.width(), disp.height()) ts touchscreen.TouchScreen() # 创建Flask应用实例并启用CORS允许跨域请求 Flask_app Flask(__name__) CORS(Flask_app) #创建退出通道 img_exit image.load(./assets/exit.jpg).resize(50, 50) img_exit_touch image.load(./assets/exit_touch.jpg).resize(50, 50) # 记录上一次眼睛图标状态改变的时间毫秒用于触摸消抖 img_eye_last_change time.ticks_ms() # 定义触摸检测函数判断触摸点是否在指定矩形区域内 # t: 触摸信息t[0] 为 x, t[1] 为 y, t[2] 为触摸状态 # box: 矩形区域 [左上角 x, 左上角 y, 宽度, 高度] # oft: 额外偏移量用于调整检测区域 def touch_box(t, box, oft 0): if t[2] and t[0] oft box[0] and t[0] box[0] box[2] oft and t[1] oft box[1] and t[1] box[1] box[3] oft: return True else: return False # 标志变量是否需要退出程序 need_exit False #测距函数 def measure_distance(obj_size, err_distance, max_distance): #obj_size对象在图像中所占的像素位置 #err_distance摄像头倾斜导致的盲区距离 #max_distance摄像头能拍摄的最大范围不包括盲区距离 #actual_distance最后测得的距离 #obj_height摄像头的最大像素高度 obj_height detector.input_height() #计算距离 actual_distance max_distance - obj_size * (max_distance / obj_height) err_distance end_distance round(actual_distance,2) return end_distance #串口传输 def send_data(temp): data str(distance) \r \n se.write(data.encode(utf-8)) print(data) class Server(): def __init__(self): # 初始化事件和计数器用于控制图片捕获和存储 self.image_event th.Event() self.image_counter 1 self.save_path /root/photos # 确保照片保存目录存在 if not os.path.exists(self.save_path): os.makedirs(self.save_path) # 为Flask应用添加路由 Flask_app.route(/stream)(self.http_stream) Flask_app.route(/take_photo)(self.take_photo) Flask_app.route(/photos/path:filename)(self.send_photo) def stream_worker(self): # 摄像头视频流的工作线程 while self.running: self.img cam.read() self.jpg self.img.to_jpeg(90) if self.jpg is None: print(编码错误) os._exit(-1) self.image_event.set() def get_stream(self): # 生成视频流的生成器函数 while self.running: self.image_event.wait() self.image_event.clear() if self.jpg is None: continue yield ( bContent-Type: data/jpeg\r\n\r\n self.jpg.to_bytes(False) b\r\n\r\n--frame\r\n ) def http_stream(self): # 返回视频流的HTTP响应 return Response( self.get_stream(), mimetypemultipart/x-mixed-replace; boundaryframe ) def take_photo(self): # 拍摄照片并返回照片信息 if not hasattr(self, img): return jsonify({error: No image captured}), 400 filename f{self.save_path}/{self.image_counter}.jpg self.img.save(filename) self.image_counter 1 return jsonify({message: f照片已保存为 {filename}., image_url: f/photos/{self.image_counter - 1}.jpg}) def send_photo(self, filename): # 返回指定照片 return send_from_directory(self.save_path, filename) def start_server(self): # 启动服务器和视频流工作线程 self.running True self.stream_thread th.Thread(targetself.stream_worker, daemonTrue) self.stream_thread.start() self.server make_server(0.0.0.0, 8080, Flask_app, threadedTrue, processes1) self.server.log_startup() self.server_thread th.Thread(targetself.server.serve_forever, daemonTrue) self.server_thread.start() def stop_server(self): # 停止服务器和工作线程 self.running False self.server.shutdown() self.server_thread.join() self.stream_thread.join() # 初始化WiFi wifi network.wifi.Wifi() # 创建服务器实例并启动服务器 server Server() server.start_server() urlsserver.get_stream() disp_switch False while not app.need_exit(): # 从摄像头读取一帧图像 show_img cam2.read() # 读取触摸屏当前触摸状态 t ts.read() # 定义退出按钮的位置和大小在屏幕左上角距边缘 20 像素 box [20, 15, img_exit.width(), img_exit.height()] # 检测触摸是否落在退出按钮区域内 if touch_box(t, box, 0): # 如果触摸到退出按钮绘制按下状态的图片 show_img.draw_image(box[0], box[1], img_exit_touch) need_exit True else: # 否则绘制普通状态的图片 show_img.draw_image(box[0], box[1], img_exit) # 使用检测模型对图像进行目标检测设置置信度阈值和IOU阈值 objs detector.detect(show_img, conf_th0.45, iou_th0.45) # 遍历检测到的所有对象 for obj in objs: # 在图像上绘制矩形框表示检测到的对象 show_img.draw_rect(obj.x, obj.y, obj.w, obj.h, colorimage.COLOR_RED) #测量物体的距离 position obj.y obj.h distance measure_distance(position , 0.3, 5) send_data(distance) # 构造包含类别和置信度的字符串并在图像上绘制 msg f{detector.labels[obj.class_id]}: {distance:.2f} show_img.draw_string(obj.x, obj.y, msg, colorimage.COLOR_RED) disp.show(show_img) # 如果检测到退出按钮被按下跳出循环结束程序 if need_exit: break

相关新闻

OpenClaw 在Windows下的安装

OpenClaw 在Windows下的安装

OpenClaw 在Windows下的安装 安装参考文件: ● 微信文章:《2 万字 Openclaw 最细部署指南,30分钟手把手教程!Openclaw完全指南第一篇》 ● OpenClaw中国社区 保姆级安装教程 ● 如何在 OpenClaw (Clawdbot/Moltbot) 配置阿里云百…

2026/7/3 5:26:10 阅读更多 →
Protocol Launcher 系列:Atom 深度集成

Protocol Launcher 系列:Atom 深度集成

在介绍了 VSCodium 的协作能力后,今天,我们将介绍如何通过 Protocol Launcher 与 Atom 联动,让这款经典编辑器的使用更加高效。 Atom 是 GitHub 推出的经典开源编辑器,虽然已于 2022 年 12 月正式归档,但其优雅的设计和…

2026/7/5 1:24:38 阅读更多 →
C语言课程学习calss2

C语言课程学习calss2

#课堂笔记第二章部分2.1C语言的数据类型2.2标识符,常量和变量2.2.2常量2.2.3变量变量名: 用来标识这块内存,实际上代表了一个存储地址。变量如何定义要掌握2.3.整型数据类型2.3.1📌 整型数据的分类(不用记)…

2026/5/17 11:27:26 阅读更多 →

最新新闻

Python 加密与解密实战 18 招(一):散列哈希加密

Python 加密与解密实战 18 招(一):散列哈希加密

Python 加密与解密实战 18 招(一):散列哈希加密 系列文章导航 第一篇:散列哈希加密(招式1-4)第二篇:对称加密(招式5-9)第三篇:非对称加密数字签名密钥交换&am…

2026/7/7 5:57:40 阅读更多 →
3分钟搞定Calibre图书信息自动化:国家图书馆ISBN插件终极指南

3分钟搞定Calibre图书信息自动化:国家图书馆ISBN插件终极指南

3分钟搞定Calibre图书信息自动化:国家图书馆ISBN插件终极指南 【免费下载链接】NLCISBNPlugin 基于中国国家图书馆ISBN检索的calibre的source/metadata插件。https://doiiars.com/article/NLCISBNPlugin 项目地址: https://gitcode.com/gh_mirrors/nl/NLCISBNPlug…

2026/7/7 5:55:39 阅读更多 →
小草助手口令野草助手

小草助手口令野草助手

小草助手口令野草助手

2026/7/7 5:55:39 阅读更多 →
企业试用期合同管理的8个高频雷区与合规操作手册

企业试用期合同管理的8个高频雷区与合规操作手册

试用期是企业和员工互相了解的"缓冲期",但这个缓冲期同时也是劳动争议的高发区。很多企业管理者和HR误以为试用期是企业说了算的"观察期",可以随便定规则、随便辞人,却不知道试用期恰恰是劳动法律监管最严格的阶段之一。…

2026/7/7 5:55:39 阅读更多 →
行业科普:互联网全媒体广告代理的市场空间与盈利逻辑

行业科普:互联网全媒体广告代理的市场空间与盈利逻辑

一、市场刚需与行业基本面线上广告是数字营销体系的核心组成部分,如今已成为绝大多数企业的常规经营支出。从市场现状来看,规模不等的商家通常会按月度或季度制定广告投放预算,业务范围可覆盖全国市场,需求的普遍性支撑起了庞大的…

2026/7/7 5:53:39 阅读更多 →
FTC 框架详解:残差 RL、稠密奖励与人在环的真实世界机器人训练

FTC 框架详解:残差 RL、稠密奖励与人在环的真实世界机器人训练

FTC 框架详解:残差 RL、稠密奖励与人在环的真实世界机器人训练 先说结论FTC 通过残差 RL 将探索起点锁定在目标区域附近,大幅降低真实世界交互次数需求。基于关键帧的可供性稠密奖励比 VLM 推理更轻量、实时,但依赖示教数据质量。人类干预窗口…

2026/7/7 5:51:39 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻