news 2026/10/2 2:37:46

YOLOv8行人检测实战:数据集处理与PyQt界面集成全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv8行人检测实战:数据集处理与PyQt界面集成全流程

简介:面向有深度学习基础的行人检测开发者,这套YOLOv8行人检测工程包整合了标注数据集、训练权重与图形界面三个核心部分,基于YOLOv8算法在数千张街道和交通场景图像上训练,平均精度均值达90%以上,可直接用于行人识别,省去从零采集与标注数据的时间。压缩包内共2000个文件,以文本标注或配置文件为主,另含四个说明文档、三个环境配置与运行教程、两个程序源码模块,整体约456.56MB。除权重与数据集外,还提供训练曲线图、标注工具使用说明、图形界面代码与运行步骤,数据集图片为jpg格式,类别统一为person,可直接适配YOLO系列模型继续微调;代码模块划分清晰,注释和目录结构便于修改维护,可快速搭建检测演示系统或进行二次开发,资源涵盖了环境配置、模型训练到界面部署的完整链条,初学者可以按图索骥。目前已有817人学习下载,配套完整,能够帮助学习者避开数据准备与界面开发的重复工作,把精力集中在模型改进与业务落地之上,对目标检测方向的研究者与工程师都有实用价值。

1. 别只跑通YOLOv8,一个能交付的行人检测项目差在数据集和界面

有个很反直觉的现象:很多人跑通了 YOLOv8 的官方 demo,换到自己手上的行人检测项目却漏洞百出,一半时间耗在数据集上,另一半耗在“界面怎么不卡死”上。标题里的三件事——YOLOv8行人检测、数据集、PyQt界面,本质是一条链:模型提供检测能力,数据集决定检测上限,界面决定能不能交付使用。这篇笔记面向正在做毕设、演示系统或接单交付的工程师,按模型选型、数据集整理、模型训练、PyQt界面集成一条线讲透,每个环节给能直接复制的命令和脚本,并把最容易翻车的点提前标出来。

2. 为什么选YOLOv8做行人检测:模型、数据与界面的选型逻辑

在动手之前,先把“为什么”说清楚,不然参数全靠抄,出问题就是玄学。行人检测是把目标检测难点占全的场景:目标小、互相遮挡、密集排列、尺度变化大。选型直接决定后面每一步的工作量,也决定最后能不能在本地 CPU 机器上顺利跑起来。

2.1 YOLOv8 vs Faster R-CNN / SSD / YOLOv5:行人场景的取舍

我一般用三个标准来卡选型:单机演示必须实时、换数据集后调参量可控、社区资料多到能解决疑难问题。Faster R-CNN 两阶段精度高,但对 CPU 完全谈不上实时,在 PyQt 里演示基本不可用;SSD 小目标检测弱,行人这种远距离小目标漏检严重;YOLOv5 成熟,但 anchor-based 机制要求换数据集后重算 anchor,处理密集行人时 NMS 参数也得反复试。

YOLOv8 的改动正好踩在行人检测的需求上。它去掉了 anchor,把 head 拆成分类和回归两个独立分支,还引入 C2f 结构,小目标特征提取能力比 YOLOv5 的 C3 强一些。对做界面的人来说,最友好的地方是官方把训练、验证、导出封装成了 yolo 命令,不需要自己写训练循环。有人问我 yolov8网络结构图有没有必要看,其实你只要知道 backbone 负责提特征、neck 的 PAN-FPN 负责融合不同尺度、head 输出三组特征图就够了,其余细节交给官方实现。

方案CPU推理小目标换数据集调参界面集成
Faster R-CNN慢较好中重
SSD快差中中
YOLOv5中中anchor需重算中
YOLOv8中较好低低

这个对比表是我选型时常用的判断方式。行人检测项目通常不是只有训练这一环,后面还要做界面、演示、交付,越靠后的环节越需要省心,YOLOv8 的生态优势在这里体现得很明显。

2.2 行人数据集的三大难点:尺度、遮挡、难例

数据集不是“越多越好”,而是“难例越全越好”。行人检测项目里最常见的现象是:模型在训练集上 mAP 很高,一换场景就疯狂误检。原因多半是数据里只有近距离大目标,没有远距离小目标、遮挡行人和负样本。

常见做法是先用公开行人数据集做预训练,比如 COCO 里的 person 类别、CityPersons、CrowdHuman 这类,再用自己场景的图片增量标注。这里的坑是:公开数据集标注质量参差不齐,很多标签只框了可见部分,遮挡严重的行人是缺失的。如果直接拿来当训练标准,模型会对遮挡行人不敏感,现场一遇到拥挤路段就开始丢框。

另一个被忽略的是负样本。行人检测的误检往往来自背景中像人的物体,比如树干、路灯杆、广告牌上的人形图案。所以我在数据集里会专门放一批不包含行人的图片,让模型学会“这里没有行人”。这批负样本可以是一整个目录,标签为空 txt 文件,训练时会正常读取,只是正样本数量为零。数据集里加入负样本后,误检率通常能降一半以上。

2.3 PyQt 在项目里的定位:UI 线程只负责显示,推理必须单独开线程

PyQt 在这个项目里不是“画个窗口把检测框贴上去”那么简单。行人检测的推理耗时通常在几十到几百毫秒,如果直接在按钮的回调里跑推理,点击“开始检测”之后界面会立刻无响应,这就是常说的“ui界面卡顿”。我见过太多人把模型推理写在主循环里,最后只能靠 sleep 缓解,结果画面掉帧更严重。

正确结构是:主线程负责窗口和 QTimer 定时刷新画面,检测工作放在 QThread 子线程里,子线程读帧、推理、绘制,然后用 signal 把处理好的 QImage 发回主线程。子线程内部用循环控制帧率,而不是每次收到 UI 信号才跑一次。这样摄像头的帧率不会拖垮界面,界面操作也不会打断推理。

另外,读取摄像头建议用 OpenCV 而不是 PyQt 自带的多媒体框架。OpenCV 的 VideoCapture 在 ubuntu20.04 上对 USB 摄像头和网络流兼容性更好,而且它的帧格式是 BGR,YOLOv8 输入要的是 RGB,中间记得用 cvtColor 转换。这个细节看起来小,但正是检测框错位和颜色异常的常见原因。界面上的控件不需要多复杂,文件选择按钮、摄像头切换、置信度滑块、FPS 显示就够用。置信度滑块我强烈建议留出来,因为不同场景下行人检测的 conf 阈值差距很大,室内 0.3 能出效果,室外强光下可能要 0.5,把 conf 做成滑块实时传给推理线程,比每次改代码重跑快得多。

3. 数据集整理:一站式脚本把VOC/Labelme标注转成YOLO格式并切分数据集

模型训练前,数据集必须变成 YOLO 格式。很多人栽在格式上:标签路径对不上、坐标没归一化、图片和标签不在同名目录,导致训练时 mAP 一直为 0。这一章给你能直接跑的脚本,顺便把容易忽略的检查逻辑写进去。

3.1 目录结构与检查:先保证每个图片标签能对上

YOLO 格式的目录结构有约定俗成的规范,单类别行人检测的标准布局如下:

datasets/pedestrian/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练标签 │ └── val/ # 验证标签 └── data.yaml # 训练配置

图片和标签必须同名,只是后缀不同,比如0001.jpg对应0001.txt。标签文件每一行是class_id x_center y_center width height,这里的坐标是相对图片宽高的归一化值,范围在 0 到 1 之间。最容易犯的错是把像素坐标直接写进去,训练时 loss 会乱飘。

拿到数据集后先跑一遍检查脚本,看看有多少图片缺标签、有多少标签文件是空的。空标签对训练本身没影响,但如果你没有专门建负样本目录,空标签往往意味着漏标,这部分图片会让模型学到“有行人但不框”。

# check_labels.py:核对图片与标签是否一一对应 from pathlib import Path for split in ['train', 'val']: img_dir = Path(f'datasets/pedestrian/images/{split}') label_dir = Path(f'datasets/pedestrian/labels/{split}') imgs = sorted(img_dir.glob('*.*')) missing = 0 empty = 0 for img in imgs: label = label_dir / (img.stem + '.txt') if not label.exists(): missing += 1 print(f'missing label: {label}') elif label.stat().st_size == 0: empty += 1 print(f'empty label: {label}') print(f'{split}: {len(imgs)} images, {missing} missing, {empty} empty')

这个脚本的逻辑很简单:遍历图片目录,按 stem 找同名 txt。如果 missing 超过 1%,先补标注再训练,不要指望模型自己纠正错误标签。empty 数量如果超过 5%,确认一下是负样本还是漏标。负样本我会单独放在images/train/negative/子目录里管理,方便后续替换。

3.2 转换脚本:把VOC XML转成YOLO txt,处理坐标和类别映射

常见的数据来源是 VOC 格式的 XML,每张图一个 xml 文件,框的坐标是像素级的左上右下。转换脚本核心逻辑如下,class_names 的顺序决定了标签编号,必须和后续训练配置严格一致。

# voc_to_yolo.py:将VOC XML标注转成YOLO txt import xml.etree.ElementTree as ET from pathlib import Path class_names = ['person'] # 类别清单,顺序决定标签编号 def voc_to_yolo(xml_path: Path) -> list: tree = ET.parse(xml_path) root = tree.getroot() img_w = int(root.findtext('size/width')) img_h = int(root.findtext('size/height')) lines = [] for obj in root.findall('object'): name = obj.findtext('name') if name not in class_names: continue if obj.findtext('difficult') == '1': continue # 跳过difficult目标,避免干扰训练 cls_id = class_names.index(name) box = obj.find('bndbox') xmin = int(float(box.findtext('xmin'))) ymin = int(float(box.findtext('ymin'))) xmax = int(float(box.findtext('xmax'))) ymax = int(float(box.findtext('ymax'))) # 处理翻转坐标和越界 xmin, xmax = min(xmin, xmax), max(xmin, xmax) ymin, ymax = min(ymin, ymax), max(ymin, ymax) xmin = max(0, xmin) ymin = max(0, ymin) xmax = min(img_w, xmax) ymax = min(img_h, ymax) if xmax - xmin < 2 or ymax - ymin < 2: continue # 过滤小于2像素的碎片框 x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h bw = (xmax - xmin) / img_w bh = (ymax - ymin) / img_h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}") return lines for xml_path in Path('xml_all').rglob('*.xml'): lines = voc_to_yolo(xml_path) if not lines: continue out_path = Path('labels_all') / (xml_path.stem + '.txt') out_path.write_text('\n'.join(lines) + '\n', encoding='utf-8')

逻辑说明:VOC 的 bndbox 标签是左上右下像素坐标,YOLO 需要中心点和宽高的归一化值。转换时我做了两件容易被忽略的事——过滤 difficult 目标和小于 2 像素的碎片框。difficult 是 VOC 里表示“难以辨认”的标记,留下它会让训练信号变弱;碎片框通常是标注软件误操作产生的,留着会让模型对噪声敏感。

如果用的是 labelme标注用于yolov8,json 文件里存的是多边形点坐标,不是矩形框。转换逻辑是先取所有点的 x 最小值、y 最小值、x 最大值、y 最大值得到 bbox,再做同一套归一化。注意 labelme 的 imageWidth/imageHeight 字段必须和真实图片一致,否则转换后坐标整体偏移,训练时 loss 能降,但推理框会歪。

3.3 切分训练/验证集并生成data.yaml

数据转换完成后,按比例切分数据集。这里有一个人人都会踩的坑:只随机切分图片,忘了把同名标签一起移动,训练时报“label not found”或者隐式跳过。下面这个脚本把图片和标签一起复制,并且保留原始素材,切分不满意可以重新来。

# split_dataset.py:按比例切分train/val,图片和标签一起复制 import random import shutil from pathlib import Path random.seed(42) # 固定随机种子,保证可复现 val_ratio = 0.2 img_all = [p for p in Path('images_all').iterdir() if p.suffix.lower() in ('.jpg', '.jpeg', '.png')] img_all.sort() random.shuffle(img_all) val_num = int(len(img_all) * val_ratio) for split, imgs in [('train', img_all[val_num:]), ('val', img_all[:val_num])]: img_out = Path(f'datasets/pedestrian/images/{split}') label_out = Path(f'datasets/pedestrian/labels/{split}') img_out.mkdir(parents=True, exist_ok=True) label_out.mkdir(parents=True, exist_ok=True) for img in imgs: label = Path('labels_all') / (img.stem + '.txt') if not label.exists(): print(f'skip {img.name}: label not found') continue shutil.copy2(img, img_out / img.name) shutil.copy2(label, label_out / label.name) print(f'{split}: {len(imgs)} images')

这里用 shutil.copy2 而不是 os.rename,是因为复制不破坏原始目录,跑完检查发现划分不理想,删掉输出目录重新执行就行,这就是后悔药。val_ratio 设成 0.2,如果你的素材总量很大可以降到 0.1,但验证集图片太少会导致 mAP 波动大,不建议低于 50 张。

切分完成后在 datasets/pedestrian 下创建 data.yaml:

# data.yaml path: datasets/pedestrian # 相对路径,从运行yolo命令的工作目录解析 train: images/train val: images/val nc: 1 names: ['person']

注意 path 用相对路径而不是绝对路径,绝对路径在当前机器能跑,换台电脑或者打包给别人就会全部失效。names 的顺序必须和转换脚本里的 class_names 一致,这里只有 person 一个类别,顺序影响不大,但多类别时顺序错了就是灾难。

4. 用ultralytics训练YOLOv8行人检测:环境配置、训练参数与结果验证

数据准备好了,接下来进入训练环节。这一步要同时解决环境、参数和验证三个问题。先搭一个干净的虚拟环境,再跑训练命令,最后用验证集把模型表现量化出来,方便后面调阈值。

4.1 ubuntu20.04搭建yolov8环境cpu版本:最小可跑环境

我常用虚拟环境把项目隔离,避免和系统 Python 打架。CPU 版本训练行人检测是可行的,慢是慢一点,但小数据集完全能撑住。

python3 -m venv yolov8_env source yolov8_env/bin/activate pip install --upgrade pip pip install ultralytics opencv-python

说明:CPU 环境不需要手动装 CUDA 版 torch,pip 会自动匹配当前机器安装 CPU 版本。装完后先跑一次官方权重验证环境:

yolo predict model=yolov8s.pt source=test.jpg save=True

第一次运行会自动下载 yolov8s.pt 权重,网络慢的时候会卡在下载阶段。常见做法是先下载好权重文件放到用户目录的~/.cache/ultralytics/下,下次启动就直接读缓存。这一步和模型本身关系不大,但很多人以为环境坏了,实际上是权重没下完。

4.2 训练命令与关键参数:yolov8模型训练参数含义

训练行人检测模型的命令如下,我按 CPU 训练的场景给了保守参数:

yolo detect train \ model=yolov8s.pt \ data=datasets/pedestrian/data.yaml \ epochs=120 \ batch=8 \ imgsz=640 \ lr0=0.01 \ patience=20 \ seed=42 \ workers=4 \ device=cpu

每个参数在行人检测场景下的含义:

参数推荐值说明
modelyolov8s.pt用s而不是n,n快但漏检多;s在CPU上也能跑
epochs120配合patience早停,不必纠结具体轮数
batch8CPU内存有限,太大容易OOM
imgsz640小目标多时提高到768或896
lr00.01ultralytics默认值,除非loss震荡否则不动
patience20验证指标连续20轮不涨就停
seed42固定随机种子,实验可复现
devicecpuubuntu20.04 CPU环境直接写cpu

imgsz 是行人检测里最值得调整的参数。行人尺度变化大,640 输入下远处行人可能只有十几个像素,特征根本提不出来。我的习惯是先用 640 跑通流程,确认数据没问题后,再把 imgsz 提到 768 重新训练,通常 mAP50 能涨 3 到 6 个点。代价是训练时间变长,CPU 上会更明显。

密集行人场景还有一个容易翻车的点:ultralytics 默认开启 mosaic 数据增强,把四张图拼在一起训练,对常规目标有效,但对密集行人会让目标互相重叠,变成一团马赛克。我在拥挤场景会把 mosaic 调小到 0.5 甚至关闭。可以在训练命令里直接加mosaic=0.5,或者用 Python 接口设置:

from ultralytics import YOLO model = YOLO('yolov8s.pt') model.train( data='datasets/pedestrian/data.yaml', epochs=120, imgsz=768, batch=8, device='cpu', patience=20, seed=42, mosaic=0.5, cache=False, )

cache 参数我特意写成了 False。CPU 训练时如果把图片缓存到内存,几十 G 的数据会直接把内存打爆,虽然能加快读取速度,但得不偿失。

4.3 验证结果:用best.pt在图片上推理并看指标

训练结束后,runs/detect/train 目录下会有 best.pt 和 last.pt。best.pt 是验证集上表现最好的权重,后续界面接入用这个。先跑一次验证集评估,拿到量化指标:

yolo detect val \ model=runs/detect/train/weights/best.pt \ data=datasets/pedestrian/data.yaml

输出里主要看 mAP50 和 mAP50-95。行人检测这种单类别任务,mAP50 达到 0.8 以上可以进界面联调,mAP50-95 受小目标影响大,不要因为它低就疯狂调参。再看 Precision 和 Recall,如果 Recall 明显低,说明漏检严重,优先提高 imgsz 或降低 conf 阈值。

再用单张图片实测一下,顺便验证推理链路:

from ultralytics import YOLO model = YOLO('runs/detect/train/weights/best.pt') results = model.predict('test.jpg', conf=0.35, iou=0.45, imgsz=640) for r in results: print('boxes:', r.boxes.xyxy) print('conf:', r.boxes.conf) print('cls:', r.boxes.cls) r.show()

conf 和 iou 是两个需要在界面调试中反复调的值。conf 是置信度阈值,默认 0.25 对行人检测偏低,误检框会很多,我一般从 0.35 起步。iou 是 NMS 阈值,默认 0.7,密集人群场景建议调到 0.4 到 0.45,否则重叠的行人会被合并成一个框。

5. 落地避坑:行人检测从训练到PyQt界面的5个翻车点

这一章汇总我实际踩过的坑,每一条都按现象、原因、解决三个层面写清楚。项目做多了你会发现,模型训练本身很少卡人,反而是这些看起来不起眼的细节最耗时间。

5.1 训练了100个epoch,mAP50还是0

现象:训练日志里 loss 在降,验证集 mAP50 永远是 0,或者打印出来的类别全是错的。

原因:三个常见问题——标签类别索引和 data.yaml 对不上、标签坐标是绝对像素没归一化、图片和标签文件名不一致导致模型只学了空标注。

解决:在训练前画一批带标注框的图片,肉眼看一遍。画框脚本如下:

import cv2 from pathlib import Path img_path = Path('datasets/pedestrian/images/train/00001.jpg') label_path = Path('datasets/pedestrian/labels/train/00001.txt') img = cv2.imread(str(img_path)) h, w = img.shape[:2] for line in label_path.read_text().strip().splitlines(): cls, cx, cy, bw, bh = map(float, line.split()) x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite('check.jpg', img)

框位置偏了,问题在转换脚本;全是几像素的小点,说明坐标没有归一化或者读错了宽高;框完全画不出来,说明标签文件是空的。这一步跑通再训练,能省下一整天的调试时间。

5.2 PyQt界面一点“开始检测”就卡死

现象:点击按钮后窗口无响应,操作系统提示程序未响应,画面冻结。

原因:模型推理直接写在按钮回调里,阻塞了 PyQt 主线程的事件循环。摄像头读取也可能阻塞在视频流的 read() 上,尤其是网络摄像头。

解决:推理放进 QThread 子线程,只通过信号回传 QImage。核心结构如下:

class DetectThread(QThread): frame_ready = pyqtSignal(QImage) def run(self): cap = cv2.VideoCapture(0) while self.running: ok, frame = cap.read() if not ok: continue results = model.predict(frame, conf=self.conf, imgsz=640) annotated = results[0].plot() rgb = cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB) h, w, ch = rgb.shape qimg = QImage(rgb.data, w, h, ch * w, QImage.Format_RGB888) self.frame_ready.emit(qimg)

注意 QImage 构造时的 bytesPerLine 参数要用ch * w,如果写默认值,画面会显示成错位的条纹。模型对象要在子线程里初始化,不要在信号回调里反复加载,否则每帧都会重新读权重。

5.3 远距离小目标漏检,密集人群乱成一团

现象:近处的行人框得很准,远处行人漏掉,人群里多个框重合。

原因:输入分辨率太低,模型用的是 yolov8n 这种轻量级结构,NMS 的 iou 阈值太高导致重叠框被错误合并。

解决:分三步走。第一步训练时把 imgsz 从 640 提高到 768 或 896;第二步模型从 n 换成 s 或 m,s 在 CPU 上还能接受,m 就比较吃力;第三步推理时把 iou 降到 0.4。如果数据集里小目标占比本身低,还需要专门补充远距离行人图片,模型对小目标不敏感,数据层面不给案例是调不出来的。

5.4 界面里检测框画在错误位置,检测结果对不上画面

现象:框出现在目标的左边或右边,人明明在画面左侧,框却标到右侧。

原因:OpenCV 读进来是 BGR,YOLO 输入要 RGB;模型内部做了 letterbox 缩放,推理出的坐标是缩放后的坐标系,没有映射回原图;摄像头画面开了镜像但没有对 X 坐标做翻转。

解决:用 results 自带的 plot() 方法画框不会出错,手动画框时一定要做坐标还原。letterbox 的还原公式是固定的:

ratio = min(new_w / orig_w, new_h / orig_h) pad_x = (new_w - orig_w * ratio) / 2 pad_y = (new_h - orig_h * ratio) / 2 # 推理框x1从模型坐标还原到原图坐标 x1_orig = int((x1 - pad_x) / ratio)

如果开了镜像,记得再执行x1_orig = orig_w - x1_orig。这个坑在接入外部摄像头时特别常见,因为许多监控摄像头的画面本身就是镜像的。

5.5 验证指标虚高,实拍却一塌糊涂

现象:val 集 mAP50 高达 0.85,拿到现场一测漏检严重,感觉训练了个寂寞。

原因:数据划分时同一段视频的连续帧被随机拆进了 train 和 val,造成数据泄漏。模型在 validation 阶段见过高度相似的帧,指标自然虚高。

解决:划分数据集时按视频段而不是按帧切分。我的做法是先按视频来源给图片打标签,比如 surveillance_cam01_frame0001.jpg,然后以视频名为单位做切分,保证同一段视频的所有帧都在同一集合里。另外,现场测试一定要换一个完全没有参与训练的场景,哪怕只是隔着一条街拍的片段,都比 val 集上的数字有参考价值。

6. 进阶:把best.pt导出ONNX并接入PyQt,用视频离线验证效率高很多

训练出 best.pt 并且界面能跑起来之后,下一步通常是提速和稳定。我常用的做法是把模型导出成 ONNX,再用 onnxruntime 跑推理。这样做有两个好处:一是导出后推理逻辑不再依赖 ultralytics 这个大包,打包给客户时体积小很多;二是 onnxruntime 的 CPU 线程利用率更好,配合多线程能让推理速度接近实时。

导出命令很简单:

yolo export model=runs/detect/train/weights/best.pt format=onnx opset=12 imgsz=640

opset 别追求最新,客户端装的是 onnxruntime 1.x 时,opset 过高会报不兼容。导出后在 PyQt 里加载:

import onnxruntime as ort sess = ort.InferenceSession('best.onnx', providers=['CPUExecutionProvider']) outs = sess.run(None, {sess.get_inputs()[0].name: input_blob})

这里 input_blob 是 letterbox 预处理后的归一化张量,shape 是 (1, 3, 640, 640)。输出解析要看模型输出的 shape,通常是 (1, 84, 8400) 这种形式,需要转置后按行过滤置信度。解析逻辑建议画一张坐标变换图存在项目里,不然一周后回来看代码就是黑匣子。

离线验证是我最推荐的一条工作习惯:把现场录一段视频存成 mp4,先让脚本读取视频、跑推理、把每帧的 FPS 和漏检情况打印出来,确定没问题再接摄像头。在摄像头前反复测试,既浪费时间又难复现问题。有一次我直接在摄像头前调参,漏检情况无法定位,后来把录屏逐帧分析,才发现是现场逆光导致行人对比度低,加一个光照预处理就解决了。

这个教训让我后来坚持先录视频再动手。模型、数据、界面三部分分开测试,再串起来整体调试,是这个项目里最值得投入的习惯。希望这些内容能帮你少走一段弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 2:36:53

基于LSTM的股票价格预测与量化策略实战:从数据到回测的完整链路

简介&#xff1a;这份资源是面向计算机相关专业学生与项目实战学习者的深度学习股票价格预测与量化策略研究完整项目&#xff0c;源自大四毕业设计&#xff0c;经导师指导并获99分评审认可。内容涵盖股票价格预测模型构建与量化策略实现&#xff0c;适合作为毕业设计、课程设计…

作者头像 李华
网站建设 2026/10/2 2:36:26

开源大模型私有化部署与LoRA微调、LangChain应用全链路实战

简介&#xff1a;面向AI大模型应用开发与落地场景&#xff0c;这份资料围绕开源大模型的环境配置、私有化部署、LoRA微调与LangChain应用展开&#xff0c;覆盖DeepSeek、Yi、Qwen、Baichuan、ChatGLM、MiniCPM等主流模型&#xff0c;适合正在学习大模型技术栈并希望动手实践的开…

作者头像 李华
网站建设 2026/10/2 2:35:49

C++中的6种构造函数举例详解

在 C 中&#xff0c;构造函数是一种特殊的成员函数&#xff0c;用于初始化类对象。在对象创建时自动调用&#xff0c;构造函数的主要作用是分配资源、初始化数据成员等。根据不同的功能和使用场景&#xff0c;C 提供了多种类型的构造函数&#xff1a;1. 默认构造函数 (Default …

作者头像 李华
网站建设 2026/10/2 2:33:27

用 CodeArts AI 智能体零依赖打造「鲜拾 FreshKeep」食材保鲜管家

一键开通华为云码道 CodeArts 代码智能体&#xff1a;https://developer.huaweicloud.com/codeartsco.html?sourcedmzntgwatomgit1&sourceaddmzntgwatomgithd 引言&#xff1a;从家庭冰箱里的浪费说起 中国家庭每年因食材过期造成的浪费触目惊心。一项调研显示&#xff0…

作者头像 李华
网站建设 2026/10/2 2:33:20

基于单视频三维实时重构的危化园区人员/车辆无感定位与危险源空间关系持续感知技术方案

前言危化园区安全风险的核心管控难点&#xff0c;在于人员、车辆等动态流动要素与储罐、装置、高危管廊等静态危险源之间的实时空间耦合关系不可见、不可算、不可预。传统园区监测体系多采用独立摄像头二维观测、标签式人员定位、定点传感监测的离散模式&#xff0c;仅能实现单…

作者头像 李华