ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

视频流处理与摄像头接入:7小时搭建YOLO实时视觉管线

视频流处理与摄像头接入:7小时搭建YOLO实时视觉管线 1. 写在前面为什么先折腾视频流我见过太多人拿着 YOLO 的预训练权重一上来就让摄像头画面里的物体框满屏飞结果卡在打开摄像头这一步一卡就是两三天。YOLO 只是实时视觉的大脑它需要的是持续不断的视频帧输入而视频流通向 YOLO 的地基这一步——摄像头接入与视频流处理恰恰是很多教程里一笔带过、却最能劝退新手的地方。这篇文章是从 YOLO 到实时视觉系列的第一篇目标很明确7 小时之内让你在自己电脑上把摄像头画面稳定拉起来完成从设备到代码的完整通路。我会按 43 小时拆成两段前 4 小时打通视频流获取与处理管线后 3 小时把画面格式化成 YOLO 能吃的形状并搭出多线程框架。适合刚接触 YOLO、OpenCV 的初学者也适合那些被 RTSP 流、摄像头打不开、画面卡顿折磨过的老同学。整体方案以 Python 为主Windows 和 Linux 环境我都实测过可以直接照着抄。2. 整体设计7小时从零到实时视觉管线2.1 为什么视频流接入是实时视觉的第一道坎很多人的第一反应是从 YOLO 官方仓库 clone 代码下载预训练模型然后跑detect.py --source 0不就完事了吗没错YOLOv5 确实支持直接用摄像头标号0作为输入源看起来 一条命令打通。但你在实际项目中没法这么干原因有三个。第一官方脚本的摄像头读流逻辑过于简化。detect.py里用LoadStreams类去管理摄像头如果摄像头分辨率、驱动后端和 OpenCV 版本不匹配画面要么黑屏要么直接崩溃。更别提多路摄像头接入时它压根没有做合理的缓冲和丢帧策略。第二你需要把视频帧接入到自己的业务逻辑里。比如我要做的是一个工地安全帽检测演示需要在画面上叠加工地区域规则在检测到违规行为的时候联动告警——这就必须自己掌控每一帧的流向而不是让官方脚本一把梭。第三实时性的本质是延迟可控而不是帧率最高。摄像头接入只是开始真正难的是让视频流处理的速度跟上采集速度让 YOLO 的推理结果尽快显示到屏幕上。这个链路设计直接决定成败。所以 7 小时的时间规划必须分清楚前 4 小时解决看得见后 3 小时解决用得上。2.2 7小时时间线与交付物我按照环境搭建 - 单路摄像头接入 - 视频流处理优化 - 格式化成YOLO输入 - 多线程管线的顺序排了一张表每一步都有明确的验收标准时间段任务验收标准第 1 小时Python 虚拟环境、OpenCV、基础依赖安装import cv2不报错能运行一个打开图片的脚本第 2~3 小时本地摄像头接入USB/内置解决驱动问题能看到实时画面流畅显示分辨率 640x480 达到 30FPS第 3~4 小时接入 RTSP 网络摄像头/手机摄像头画面不花屏、不断流延迟 1 秒第 5 小时把视频帧格式化为 YOLO 输入letterbox、BGR转RGB、归一化能从一个 1920x1080 的帧生成 640x640 的模型输入张量第 6 小时用线程分离采集和推理加入帧队列缓冲画面流畅CPU 占用不再忽高忽低队列不溢出第 7 小时整合 YOLOv8 官方模型做一次实时检测 demo视频画面中能够稳定框出目标物体保持 10 FPS 以上我的建议是给自己掐表不要在每个环节上过分停留。比如说摄像头驱动问题如果 30 分钟内解决不了就换一种接入方式比如从 USB 切换到 RTSP 或者本地视频文件别在一棵树上吊死。因为后续的视频流处理方法都是通用的只要最终能拿到一帧一帧的图像数据管它是摄像头来的还是视频文件来的。3. 摄像头接入三种典型方案实测3.1 USB摄像头最简单也最容易翻车USB 摄像头是入门首选内置笔记本摄像头本质上也是USB/UVC 摄像头。OpenCV 用cv2.VideoCapture(0)打开其中的0是设备索引代表系统里第一个摄像头设备。我自己的实战体会是这段代码本身十分钟就能写出来但实际运行时的坑远比想象中多。第一个坑是驱动后端。在 Windows 上OpenCV 默认用 MSMFMicrosoft Media Foundation后端而在 Linux 上默认用 V4L2。如果你在 Linux 下装了 OpenCV 的 pip 包有时会因为没有 v4l2 驱动支持而打不开摄像头。解决方法是显式指定后端import cv2 # 0 表示第一个摄像头设备 cap cv2.VideoCapture(0, cv2.CAP_V4L2) # Linux 上显式指定 V4L2 # Windows 上可以尝试cv2.VideoCapture(0, cv2.CAP_DSHOW)第二个坑是分辨率设置不生效。很多人喜欢写cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)和cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)但读出来的实际分辨率还是 640x480。原因很简单摄像头硬件支持的分辨率是离散档位并不像显示器那样任意值都能输出。比如罗技 C270 就只支持 640x480、1280x720 这两档你设置 800x600 它就会静默失败。正确做法是设置完之后立刻读回数值确认width cap.get(cv2.CAP_PROP_FRAME_WIDTH) height cap.get(cv2.CAP_PROP_FRAME_HEIGHT) print(f实际分辨率: {int(width)}x{int(height)})如果只有 640x480我个人建议就直接用这个分辨率做实时视觉。对 YOLO 这类模型来说输入分辨率才是瓶颈采集分辨率反而没那么关键——摄像头端 640x480 的画面经过 letterbox 之后照样能检测出目标。采集分辨率太高反而会在传输和解码上浪费大量时间。第三个坑是帧率读取。cap.get(cv2.CAP_PROP_FPS)在 Windows 上经常会返回 0.0 或者夸张的数值这是 OpenCV 后端和相机驱动沟通不畅导致的不是你电脑性能不行。遇到这种情况不用纠结这个数字直接循环读帧、统计实际帧率就行import cv2 import time cap cv2.VideoCapture(0) start_time time.time() frame_count 0 while True: ret, frame cap.read() if not ret: break frame_count 1 if time.time() - start_time 1: fps frame_count / (time.time() - start_time) print(f实时帧率: {fps:.2f} FPS) frame_count 0 start_time time.time() cv2.imshow(Camera, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()实测来说640x480 分辨率下无论是 Windows 10 还是 Ubuntu 20.04只要不是配置特别差的老机器这个脚本都应该能稳定跑到 30 FPS。注意cv2.waitKey(1)的括号里的参数——它是等待键盘输入的毫秒数在显示画面时必须大于等于 1否则看不到实时画面。3.2 RTSP 网络摄像头监控场景的通用方案如果你做的是监控、安防、智慧工地这类场景摄像头多半是 IP 网络摄像头通过 RTSP 协议传输视频流。典型的海康、大华、宇视摄像头RTSP 地址格式各不相同但通常长这样rtsp://用户名:密码IP地址:端口/路径比如海康威视的常见路径是/Streaming/Channels/1大华的是/cam/realmonitor?channel1subtype0。建议去查对应品牌的官方文档或者用 VLC 播放器去验证地址是否正确——VLC 能放出来代码里基本也能读。接入 RTSP 流最简单的代码也是cv2.VideoCapture(rtsp_url)但实际效果往往很差。我在工地上测试过直接这样读 RTSP 流经常出现三种问题连接 5~10 秒才出画面、画面断断续续、内存占用不断增长。更麻烦的是OpenCV 默认的 RTSP 实现依赖 FFmpeg不同版本的表现差异很大。我的解决思路是用 FFmpeg 做拉流把视频流推给 OpenCV 用。这里分享一个我常用的管道方案ffmpeg -i rtsp://your_rtsp_url -f rawvideo -pix_fmt bgr24 -s 640x480 -r 30 pipe:1在 Python 里可以用subprocess启动这个命令然后从标准输出读原始帧数据。虽然代码量多一些但对 RTSP 的支持稳定得多而且能直接用 FFmpeg 的参数控制解码缓冲大小。不过对于 7 小时时间线来说我不建议一上来就搞这么复杂。你可以先用 OpenCV 直连试一下如果画面能稳定 2 分钟以上不卡顿就直接用 OpenCV如果不行再切 FFmpeg 管道方案。这里还有一个判断网络状况的经验值RTSP 流的延迟和画质严重依赖路由器带宽。1080P 主码流大概需要 4~6 Mbps 的码率如果 Wi-Fi 信号不好画面会频繁花屏。优先用有线网或者把摄像头切换成子码流subtype1通常是 640x480 或 704x576这对实时视觉来说至关重要。反正后续 YOLO 推理也主要是吃子码流的分辨率没必要非用主码流。3.3 手机摄像头作临时替代方案如果你手头暂时没有 USB 摄像头也没有 IP 摄像头别急着去买。手机摄像头可以临时顶上而且效果不差。这里推荐一个很老的思路用手机上的 IP Webcam 类 App 把摄像头变成 RTSP/MJPEG 服务端然后在电脑上用 OpenCV 拉流。我自己试过的是安卓端的 IP Webcam 应用手机和电脑连同一个局域网之后App 会显示一个类似http://192.168.1.5:8080/video的地址。在电脑上就可以这样接入import cv2 # 手机 IP Webcam 的 MJPG 流地址 url http://192.168.1.5:8080/video cap cv2.VideoCapture(url)这个方案的好处是零硬件成本而且手机摄像头的画质比大多数几十块钱的 USB 摄像头好得多。需要注意的是延迟Wi-Fi 传输 手机编码 电脑解码整体延迟大概在 300~500 毫秒之间。这个延迟对实时检测 demo 来说完全可以接受但别指望用这个方案做远程操控类项目。另外如果你的手机是 iPhone可以用类似的思路把手机摄像头变成网络摄像头。这类 App 的操作逻辑大同小异核心都是生成一个 HTTP/RTSP 流地址。7 小时时间线里如果 USB 摄像头折腾了 30 分钟还打不开直接切换到手机摄像头方案别浪费时间。4. 视频流处理核心OpenCV 管线搭建4.1 读取-解码-显示的最小闭环在摄像头接入跑通之后接下来要做的就是往工程化方向走。最小闭环就是读帧 - 解码 - 显示。这一步的目标是把前面 3 小时零散的代码整合成一个可以反复使用的类为后续 YOLO 接入做准备。我个人的习惯是不要把VideoCapture裸写在主循环里而是封装成下面这样的一个基础类import cv2 import threading class VideoStream: 把摄像头/RTSP/视频文件统一成同一个接口 def __init__(self, source, width640, height480): self.cap cv2.VideoCapture(source) # 尝试设置分辨率失败也没关系 self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) self.running True def read(self): ret, frame self.cap.read() if not ret: return None return frame def release(self): self.running False self.cap.release()为什么要封装成类因为后面接 YOLO 的时候你会需要在read()和推理之间插入 frame queue、预处理、缩放等步骤。如果现在不把获取帧抽象出来后面所有代码都要大改。这种先搭骨架、再填内容的习惯能帮你少踩很多重构的坑。这段基础代码的运行注意点我直接罗列出来cv2.VideoCapture打开文件路径也可以所以同一套代码既可以接摄像头也可以接一段录像。这个特性在调试 YOLO 检测器的时候非常有用——你可以先拿一段固定的视频调精度再切到实时摄像头。显示窗口的名字不要和 OpenCV 内部窗口冲突否则可能引起窗口闪烁。read()在读取 RTSP 流断流时会一直阻塞后面要加上超时判断。4.2 帧率、分辨率与延迟的权衡这是实时视觉最核心的决策问题。我把关键参数讲透采集分辨率决定原始图像信息量。640x480 和 1920x1080 之间的差距是 6 倍像素量但 YOLO 的输入通常会被缩放到 640x640所以 1080P 采集并不会直接提升检测精度反而会让 CPU/GPU 花更多时间去缩放。我实测过 YOLOv8n 模型输入从 640 提高到 1280精度提升大约 3~5 个 mAP 点但推理时间增长 4 倍。在实时场景下我多数时候推荐采集分辨率与模型输入分辨率对齐,让采集端直接输出接近 640x480 或 1280x720 的画面。帧率很多初学者觉得帧率越高越好。实际上对于目标检测任务YOLO 每帧推理一次如果采集 60 FPS、推理 15 FPS意味着中间有 45 帧被丢弃。所以我更推荐让摄像头输出与推理速度匹配的帧率比如把摄像头设置为 15~20 FPS避免产生大量无效帧。延迟对实时交互而言画面从摄像头到屏幕的总延迟要小于 200 毫秒才跟手。延迟积累主要来自三个环节编码传输RTSP 网络流、解码缓冲OpenCV 内部的 FIFO、显示缓冲imshow。要降低延迟可以这样操作关闭 OpenCV 的帧缓冲cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)降低采集分辨率减少 imshow 的窗口尺寸全屏显示其实会拖慢渲染4.3 画面预处理别小看 resize 和颜色转换YOLO 系列模型的输入要求是 RGB 图像而 OpenCV 读出来的是 BGR。这个差异如果在接入模型时没处理就会出现目标检测完全失效这种诡异现象——尤其是当你用 OpenCV 做数据增强并可视化时画面颜色看起来怪怪的。另外YOLO 的输入尺寸固定v8 默认 640而摄像头大部分是 16:9。直接把画面拉伸到 640x640 会导致目标变形影响检测精度。正确做法是 letterbox等比缩放 四周填充import cv2 import numpy as np def letterbox(img, new_shape(640, 640), color(114, 114, 114)): # 计算等比缩放比例 h, w img.shape[:2] ratio min(new_shape[0] / h, new_shape[1] / w) new_w, new_h int(w * ratio), int(h * ratio) # 先缩放 resized cv2.resize(img, (new_w, new_h), interpolationcv2.INTER_LINEAR) # 计算填充 dw, dh (new_shape[1] - new_w) // 2, (new_shape[0] - new_h) // 2 top, bottom dh, new_shape[0] - new_h - dh left, right dw, new_shape[1] - new_w - dw # 四周填充灰色 result cv2.copyMakeBorder(resized, top, bottom, left, right, cv2.BORDER_CONSTANT, valuecolor) return result这段代码我几乎每次都直接用它有两个细节很关键一是dw和dh用的是整除当差值不是偶数时左下和右上填充会差一个像素但这对模型推理没有影响二是填充颜色默认用(114, 114, 114)灰色这是很多预训练模型训练时用的填充色保持一致能让模型表现更稳定。做完 letterbox 之后还要做 BGR 转 RGB 和归一化到 0~1这两个操作可以合并写# 一张 letterbox 后的图片shape(640, 640, 3), BGR rgb_img cv2.cvtColor(boxed_img, cv2.COLOR_BGR2RGB) # YOLOv8 的预处理通常还包括除以255 input_tensor rgb_img.astype(np.float32) / 255.0 # 转换到 CHW 形式便于送入 PyTorch input_tensor np.transpose(input_tensor, (2, 0, 1))到这里摄像头输入 - YOLO 可用的张量这条通路就已经打通了。后面不管用什么模型预处理基本就是这么几步。5. 实操过程7小时Demo的完整记录5.1 第一阶段环境准备1小时我不推荐在一台机器上同时装 TensorFlow、PyTorch、多个版本的 OpenCV后面依赖冲突真的会让人崩溃。最靠谱的做法是创建一个独立的 Python 虚拟环境# 创建 YOLO 实战环境 conda create -n yolo python3.10 -y conda activate yolo # 安装基础依赖 pip install opencv-python numpy关于 Python 版本我建议 3.9~3.11 之间不要用 3.12 或者更新的版本否则一些老项目比如 PyTorch 对应版本还没出 wheel可能出现安装问题。OpenCV 用opencv-python这个 wheels 包就行它包含了常用模块不需要自己编译。numpy是核心依赖YOLO 和 OpenCV 都离不开它。如果是 NVIDIA GPU 用户安装 PyTorch 时注意 CUDA 版本匹配# 这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118这一步很多人会卡在下载速度建议用官方提供的镜像源或者等待时间换稳定。如果只是先测试 CPU 推理装 CPU 版 PyTorch 也完全没问题YOLOv8n 在 CPU 上也能跑 5 FPS 左右不至于完全不能看。5.2 第二阶段实现摄像头到屏幕约2小时这一段我不打算贴太长代码核心是把前面 3.1 节的代码做成一个可运行的脚本capture_demo.py。我的实操过程大致是这样的先用 USB 摄像头跑通 640x480 的画面过程中遇到摄像头打不开检查到是笔记本的物理摄像头开关没打开这是个很多人都会忽略的细节尤其是 ThinkPad 和部分商务本。然后尝试cap.open()报错换用cv2.CAP_DSHOW后端解决。接着在 Linux 虚拟机上测试 USB 摄像头发现 V4L2 设备节点没权限需要用sudo usermod -aG video 用户名把当前用户加入 video 组。这里我想强调一个排查方法论遇到摄像头打不开先区分是硬件问题、驱动问题还是软件问题。最简单的方法是用系统自带的相机软件Windows 的相机App、Linux 的cheese测试摄像头是否能打开。系统软件能打开就说明是 OpenCV 这边的问题系统软件也打不开那就是驱动或硬件问题直接换摄像头比折腾驱动更有效率。RTSP 接入阶段我用海康的摄像头测试OpenCV 直连 5 秒后画面卡住无响应。最后退回 FFmpeg 管道方案画面稳定但显示延迟大概 500 毫秒。排查原因是路由器不支持组播后来把 RTSP 的传输模式切换为 TCP 才解决问题。这也算一个经验遇到 RTSP 卡顿先尝试在地址后面加?tcp参数强制走 TCP 传输很多兼容性问题能立刻缓解。5.3 第三阶段YOLO 帧队列与多线程骨架约2小时当你把摄像头帧直接喂给 YOLO 推理时性能会很难看。原因是最常见的阻塞式编码cap.read()等待摄像头数据然后模型推理然后再回去读帧一条线走完每一步都在互相等待。摄像头采集帧率是 30 FPSYOLO 推理每帧 70 毫秒整个循环的实际速度就变成了推理 读帧等待的总和永远达不到高帧率。正确的做法是采集线程和推理线程分离中间用队列缓冲。采集线程持续从摄像头读取帧放入队列推理线程从队列取帧做检测这样两者互不阻塞import cv2 import threading import queue import time # 帧队列最大缓冲 2 帧超过则丢弃旧帧 frame_queue queue.Queue(maxsize2) def capture_thread(cap): while True: ret, frame cap.read() if not ret: continue # 如果队列已满说明推理线程来不及处理直接丢掉最旧的帧 if frame_queue.full(): try: frame_queue.get_nowait() except queue.Empty: pass frame_queue.put(frame) def inference_thread(model): while True: if frame_queue.empty(): time.sleep(0.001) continue frame frame_queue.get() # 这里调用 YOLO 的推理接口 # results model(frame) # 绘制结果、统计 FPS、显示画面队列大小我设置为 2 是很讲究的。如果设置成 10推理线程处理不过来时队列里堆着旧帧画面延迟会越来越大设成 2 则是一旦处理不过来就直接丢旧帧保证始终处理最新的画面。实时视觉追求的是眼手同步的延迟指标而不是每一帧都处理的丢帧率指标这一点一定要想明白。线程启动之后还有个问题Python 的 GIL 限制了多线程并行执行所以capture_thread和inference_thread并不能真正利用多核。但因为cap.read()和模型推理大部分时间都消耗在 C 扩展库内部执行时 GIL 会被释放所以实际效果还是接近并行。U 型差距很大但起码逻辑上是独立的后面改成多进程也容易。5.4 第四阶段接入 YOLOv8 跑起实时检测约2小时在 YOLO 系列里我目前最推荐 YOLOv8因为它的 API 封装得非常友好几行代码就能跑起推理from ultralytics import YOLO # 加载预训练模型第一次运行会自动下载权重 model YOLO(yolov8n.pt) # 直接用摄像头索引 0 推理 results model.predict(source0, showTrue)但你如果直接跑这段代码它会用 ultralytics 内部封装好的视频流逻辑这和我们前面自己搭的多线程管线是冲突的。实际开发中我更推荐下面的方式——用我们自己的管线取到帧之后喂给模型做单帧推理frame frame_queue.get() # YOLO 的单帧推理 results model.predict(frame, imgsz640, conf0.5, verboseFalse) # results 可以拿到检测框、类别、置信度 boxes results[0].boxes.xyxy.cpu().numpy() classes results[0].boxes.cls.cpu().numpy()这里有个很容易被忽略的细节model.predict()每次调用会做完整的预处理和后处理频繁调用会有一定的固定开销。在 7 小时 Demo 阶段直接调用没问题但到了性能优化阶段建议直接使用model(frame)或底层推理接口跳过一些额外的检查逻辑。我第一次跑通时用的就是笔记本 CPU YOLOv8n640x640 输入下大概 8~12 FPS画面勉强能看。换成 GPU哪怕是入门级 GTX 1650之后帧率直接翻到 40 FPS。如果你的目的是做实时 demo别纠结模型精度直接上 nan 版本模型YOLOv8n等所有流程跑通了再换大模型也不迟。6. 常见问题与排查技巧实录6.1 摄像头读不到帧现象可能原因排查步骤cap.read()一直返回 False设备被其他程序占用关闭所有可能占用摄像头的软件比如微信、Zoom权限不足Linux 下将用户加入video组驱动后端不匹配尝试cv2.CAP_DSHOW或cv2.CAP_V4L2画面黑屏摄像头物理开关关闭检查笔记本摄像头旁的指示灯和小拨片画面花屏USB 带宽不足换一个 USB 3.0 接口避免和键鼠共用 Hub我遇到最玄学的一次是同一个摄像头在 Windows 上正常在 Ubuntu 虚拟机里怎么都读不到帧。最后发现是 VMware 的 USB 直通设置问题需要手动把 USB 设备连接到虚拟机而不是让宿主机占用。如果你也是用虚拟机跑 OpenCV优先排查这个。6.2 RTSP 延迟大、画面卡顿RTSP 卡顿的排查思路我每次都会按这个顺序来用 VLC 打开 RTSP 地址看看是不是摄像头或网络本身有问题。如果 VLC 流畅而代码里卡问题出在 OpenCV 的解码缓冲尝试设置CAP_PROP_BUFFERSIZE1。如果 VLC 也卡用ping检查摄像头 IP 的丢包率丢包超过 1% 就说明网络不稳换有线网或者降低摄像头码率。如果延迟在 1 秒以上且画面清晰说明是缓冲过大优先考虑切 TCP 或调低分辨率。另外一条经验是RTSP 地址里经常带有用户名密码密码里如果包含字符需要 URL 编码否则解析时会截断地址。比如密码是admin123在地址里应该写成admin%40123这个问题排查起来很隐蔽。6.3 性能不达标卡在哪个环节一份实时视频检测管线的耗时分布我一般这样定位采集耗时: 约10ms (USB) 解码耗时: 约5ms (OpenCV imread/VideoCapture) 预处理耗时: 约3ms (resize, letterbox) 推理耗时: 约15~50ms (GPU) 或 100~200ms (CPU) 后处理耗时: 约2ms (NMS, 坐标恢复) 显示耗时: 约10ms (imshow)如果总耗时超过理想值用time.time()在各个环节打点计时找到瓶颈再针对优化。优化优先级是先降输入分辨率再换小模型再多线程最后才是换更贵的硬件。很多人一上来就买 GPU结果发现瓶颈出在摄像头读取上白花钱。7. 实操总结与个人体会七小时打底这个进度在我带过的几个同学里算是一个合理的平均值。有人两个小时就跑到实时检测 demo也有人两个礼拜还在折腾摄像头驱动。区别不在于天赋而在于是否愿意先花时间把问题定位清楚再动手——工具报错就去看错误信息对应的是哪个环节摄像头打不开就先拿系统软件验证硬件这种朴素的方法论比任何代码技巧都管用。我个人在实际项目中反复体会到一件事视频流接入这个环节做得够不够稳直接决定了后面整个视觉系统的可靠性。你把采集、缓冲、预处理这部分代码写扎实了后面无论换 YOLOv5 还是 YOLOv8无论是单路摄像头还是十六路 RTSP 矩阵核心框架都可以原地复用。这一篇所有代码我都建议你手敲一遍不为了别的就为了在每个环节踩一点点坑——踩过坑印象才深。如果你按这个思路跑通了下一步就可以进入本系列的第二篇把 YOLO 的推理结果做成结构化输出检测框、类别、跟踪 ID再往上游的业务逻辑对接。到时候我们会在这一篇的多线程骨架上继续扩展加入目标跟踪、区域规则判定和告警联动。先说这么多评论区聊你在摄像头接入阶段卡得最久的问题我每条都看。
返回列表