尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

YOLO实战:手机、玩手机、打电话数据集从清洗到训练部署全流程

发布时间:2026/9/23 16:20:26

资讯中心
01
ARTICLE

YOLO实战:手机、玩手机、打电话数据集从清洗到训练部署全流程

YOLO实战:手机、玩手机、打电话数据集从清洗到训练部署全流程
简介面向YOLO系列算法目标检测实践者提供一套手机、玩手机、打电话检测数据集含593张已标注图像可直接用于yolov5、yolov7、yolov8、yolov9、yolov10、yolo11等主流版本的模型训练与验证测试。压缩包共1780个文件以jpg原始图像、txt标签和xml标签为主另附一个yaml配置文件txt为归一化的YOLO标注格式类别、中心点、宽高xml采用VOC格式两类标签分别存放便于按需调用。数据集已完成训练/验证划分省去手动拆分工作。整体仅20.46MB轻量易用。目前已有190人学习下载适合入门或进阶目标检测的开发者快速上手用于课堂实验、算法对比或实际项目预研。1. 拿到yolo算法-手机-玩手机-打电话数据集-593张图像带标签.zip先别急着训练如果你在做工位行为分析、门店防损或者办公区域安全监测第一批要解决的需求十有八九是这个人是在看手机还是打电话。这份数据集从标题就能看出定位YOLO算法用的检测数据三类目标——手机、玩手机、打电话共593张图且每张都带标签。593张不算大但它聚焦在真实场景上足够让你把数据清洗、格式校验、训练和bad case分析这条链路完整跑通。它适合刚接触YOLO想训练自己数据集的初学者也适合被通用模型漏检率折磨、想用垂直场景数据微调的工程师。我先亮个态度不要让593张这个数字吓退你也不要把它当成现成的万能模型。这类小数据集的真正价值在于让你在几小时内踩完从标注格式到过拟合的所有坑之后再看什么数据都不慌。2. 先过数据关593张图像的配比、格式与标注质量检查标题里写得很清楚这是YOLO算法用的数据集。但YOLO只是个算法框架标签可以是YOLO txt、VOC XML、COCO JSON甚至某些平台导出的CSV。解压后的第一件事不是急着翻图而是把包里的目录结构和标签格式一次看清楚。我见过太多人把压缩包解压后直接扔给训练脚本最后训练到一半报index 2 is out of bounds for axis 0 with size 2其实就是标签里混了不存在的类别索引。2.1 拆包后先看目录结构和隐藏问题我一般把zip解压到一个干净目录然后一次性看清文件组织mkdir -p phone_dataset cd phone_dataset unzip ../yolo算法-手机-玩手机-打电话数据集-593张图像带标签.zip find . -maxdepth 3 -type f | head -30 echo 图片总数: $(find . -name *.jpg -o -name *.png | wc -l) echo 标签总数: $(find . -name *.txt -path *labels* | wc -l)第一行创建目录并进入unzip解压find输出前30个文件路径让我们一眼看清有没有images/、labels/这类标准目录还是所有文件都平铺在一个目录里最后两行统计图片和标签数。标签总数和593对不上时不要急着怀疑数据集缺失先看是不是有部分标签放在别的子目录、用了 .txt 之外的后缀或者有几张.png被上面的-name *.jpg漏掉了。把jpg和png分开数一次更稳。mkdir -p images labels for f in *.jpg; do mv -- $f images/; done for f in *.txt; do mv -- $f labels/; done这段是应对文件平铺的情况把所有jpg挪进imagestxt挪进labels。我特意用带引号的$f而不是裸变量是因为很多相机或数据集作者会用带空格的文件名例如play phone 001.jpg裸变量会把一个文件名拆成两段导致移动失败。YOLO对图片名没有硬性要求但带空格的文件名在Linux命令行里很容易埋雷建议顺手改名成纯英文和下划线。提示如果压缩包是Windows上打的解压后可能混入Thumbs.db、desktop.ini这类隐藏文件。它们不会影响YOLO训练但会影响你自己写的遍历脚本统计结果过滤时记得只保留图片后缀。如果你拿到的是用LabelImg打标完的YOLO格式目录通常长这样每张jpg对应一个同名txttxt第一列是类别索引后面四列是归一化中心坐标和宽高。这个格式本身没太多玄机真正的坑都在内容里。2.2 用Python脚本给593张图做体检脚本要做三件事统计图片后缀、统计每个类别的框数量、检查标签坐标是否越界以及行长度是否为5。下面是可直接保存运行的脚本import os from collections import Counter from pathlib import Path labels_dir Path(labels) img_dir Path(images) cls_counter Counter() img_counter Counter() total_boxes 0 bad_files [] for img in img_dir.iterdir(): if not img.is_file(): continue img_counter[img.suffix] 1 label_file labels_dir / (img.stem .txt) if not label_file.exists(): bad_files.append(f{img.name} 缺标签) continue with open(label_file, encodingutf-8) as f: for line in f: parts line.split() if len(parts) ! 5: bad_files.append(f{img.name}: 该行长度不对 - {line.strip()}) continue cls int(parts[0]) xc, yc, w, h map(float, parts[1:]) if not (0 xc 1 and 0 yc 1 and 0 w 1 and 0 h 1): bad_files.append(f{img.name}: 坐标越界 - {line.strip()}) cls_counter[cls] 1 total_boxes 1 print(图像扩展名分布:, dict(img_counter)) print(类别索引分布:, dict(sorted(cls_counter.items()))) print(总标注框数:, total_boxes) print(异常文件数:, len(bad_files)) for b in bad_files[:20]: print( -, b)代码逻辑是遍历images目录下所有文件为每张图找同名标签缺标签的记录一条读取每一行用split切分如果不是5列说明标注工具导出了多余空格或逗号把坐标值转成浮点后检查是否在[0,1]区间。这里有个容易忽略的细节YOLO格式的坐标是相对图片宽高的比例值不是像素值。如果之前有人把像素坐标直接写进txt画框时不会报错但训练时损失函数会按归一化计算结果永远收敛不了。这种问题只有体检能发现。类别索引分布很有用。比如看到索引0有1000多个框、索引1只有200个说明类别不均衡。后续训练要么给少数类提高损失权重要么做简单的过采样。对于593张图的小数据集类别失衡比图片数量少更要命因为少的那类基本学不出来。再补一个同样重要的统计每个类别出现在多少张图里。框数量多不等于覆盖广如果call类只有5张图哪怕一张图里有几十部手机模型也学不会泛化。cls_img_count Counter() for img in img_dir.iterdir(): if not img.is_file(): continue label_file labels_dir / (img.stem .txt) if not label_file.exists(): continue cls_in_img set() with open(label_file, encodingutf-8) as f: for line in f: cls_in_img.add(int(line.split()[0])) cls_img_count.update(cls_in_img) print(每个类别覆盖的图像数:, dict(sorted(cls_img_count.items())))这个脚本比框数统计更接近模型见过多少个场景的本质。假设call类有300个框但只来自10张图那么模型最多只见过10种打电话的姿态部署时换个角度立刻翻车。看到这种结果就应该知道想要好一点的call类精度光调参数没用必须找更多数据或者把已有的call图做裁剪合成。2.3 把标注画回原图眼睛比脚本更早知道哪里会翻车脚本能查数值问题查不出语义问题。玩手机、打电话这种行为类的检测最怕的是标注者把框的边界画得很随意。所以我会再跑一个可视化脚本随机抽三四十张图把框画出来一张张过import cv2 import random from pathlib import Path img_dir Path(images) labels_dir Path(labels) output_dir Path(vis_out) output_dir.mkdir(exist_okTrue) class_names [phone, play, call] # 按实际标签索引顺序改 imgs list(img_dir.glob(*.jpg)) random.seed(42) random.shuffle(imgs) for img_path in imgs[:40]: img cv2.imread(str(img_path)) if img is None: print(打不开:, img_path) continue h, w img.shape[:2] label_path labels_dir / (img_path.stem .txt) if not label_path.exists(): continue with open(label_path, encodingutf-8) as f: for line in f: cls, xc, yc, bw, bh line.split() cls int(cls); xc float(xc); yc float(yc) bw float(bw); bh float(bh) x1 int((xc - bw/2) * w) y1 int((yc - bh/2) * h) x2 int((xc bw/2) * w) y2 int((yc bh/2) * h) color (0, 255, 0) if cls 0 else (0, 0, 255) if cls 1 else (255, 0, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2) cv2.imwrite(str(output_dir / img_path.name), img)脚本原理是把归一化坐标乘回图片宽高得到像素坐标框再用cv2画出来。random.seed(42)固定随机种子保证你每次抽查到的图都一样方便和别人对齐问题。颜色按类别区分phone绿色、play红色、call蓝色。class_names的顺序必须和标签txt里的索引一致如果包的作者导出时把类别索引排得和我们猜的不一样画出来的标签名会张冠李戴这反而能帮你及时发现data.yaml里names顺序应该怎么排。这一步看到什么问题需要警惕如果发现玩手机的框经常把整个手掌和前臂一起框进去说明作者把行为目标画成了人体部位你训练出来的框会比实际手机大很多如果打电话只框了人头没框手机模型学的其实是人歪头而不是打电话。这些问题脚本查不出来但会在第一次部署时集体翻车。我个人的底线是如果一个类别里超过30%的框都存在边界含混就不要急着训练优先回标注工具改框。593张图重新过一遍标注也就两三个小时比训练完再回来排查bad case快得多。2.4 标签不是YOLO txt先做格式归一化再体检有时压缩包里带的是VOC XML标注因为很多打标工具默认导出格式就是XML。这种情况不要慌转YOLO txt的代码很固定关键不在遍历而在三处细节类别映射、坐标归一化、宽高是否和原始图一致。我一般会写一个简单的转换循环import xml.etree.ElementTree as ET from pathlib import Path xml_dir Path(annotations) img_dir Path(images) out_dir Path(labels) out_dir.mkdir(exist_okTrue) class_map {phone: 0, playing: 1, calling: 2} # 按实际XML里的object name调整 for xml_file in xml_dir.glob(*.xml): root ET.parse(xml_file).getroot() img_name root.find(filename).text img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) with open(out_dir / (xml_file.stem .txt), w) as out_f: for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: print(跳过未映射类别:, cls_name) continue xmin int(float(obj.find(bndbox/xmin).text)) ymin int(float(obj.find(bndbox/ymin).text)) xmax int(float(obj.find(bndbox/xmax).text)) ymax int(float(obj.find(bndbox/ymax).text)) xc ((xmin xmax) / 2) / img_w yc ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h out_f.write(f{class_map[cls_name]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}\n)代码做的事可以拆成几步解析XML根节点读取图片名和宽高遍历每个object取出bndbox的四个像素坐标按中心点公式算出归一化的xc、yc、w、h。最容易踩坑的是class_map没有把XML里所有object name覆盖到。如果XML里有texting这个标签而你只映射了三个类这条就直接被跳过图片少了一个标注框训练时模型不会报错但召回率会下降。因此转完格式后务必和2.2、2.3一样再跑一次体检和可视化不要信任转换过程的输出。如果数据集发布者给的是COCO JSON原理也一样先用pycocotools的loadRes把annotation读进来再按bbox字段和image的width/height归一化输出txt。唯一要格外注意的是COCO的bbox格式是[x, y, width, height]即左上角坐标加宽高和VOC的xmin/xmax表示方式不同别直接套同一个公式。到这里数据的格式、内容、语义你都有了底下一步才是真正开始训练。3. 用YOLOv8把这593张图训起来数据划分、配置文件与一条训练命令为什么用YOLOv8而不是YOLOv5原因主要是两个一是ultralytics官方维护安装配置简单不需要改源码二是训练日志和可视化比v5直观对于只有593张图的小数据集能更快看清过拟合趋势。网上yolov8训练自己的数据集教程很多但大多默认你已经准备好了能直接训练的数据目录这一步恰恰是本数据集最需要自己动手的地方。3.1 先按7:2:1切成train/val/test固定随机种子标题里只写了593张没有说是否已经划分过目录所以默认需要自己分。不能把全部图片送进去训练至少要留20%做验证有条件再留10%做最终测试。我一般写一个划分脚本import random from pathlib import Path images sorted(Path(images).glob(*.jpg)) sorted(Path(images).glob(*.png)) random.seed(0) random.shuffle(images) n len(images) train_imgs images[:int(n * 0.7)] val_imgs images[int(n * 0.7):int(n * 0.9)] test_imgs images[int(n * 0.9):] def move(imgs, split): img_out Path(fimages/{split}) lab_out Path(flabels/{split}) img_out.mkdir(parentsTrue, exist_okTrue) lab_out.mkdir(parentsTrue, exist_okTrue) for img in imgs: img.rename(img_out / img.name) lab Path(labels) / (img.stem .txt) if lab.exists(): lab.rename(lab_out / lab.name) move(train_imgs, train) move(val_imgs, val) move(test_imgs, test)逻辑不复杂先把所有图片路径洗牌按比例切片再通过move函数把图片和同名标签一起移动到对应子目录。random.seed(0)是这里最关键的参数它保证每次运行洗牌的顺序完全一致排错时能复现。如果不用固定seed今天跑一遍和明天跑一遍划分结果不同下次训练效果对比就没有可比性。我建议顺手再做一个检查统计每个类别在train和val里的框数比例差距不能超过一倍。如果某个类别在val里占比特别高说明切分不均衡可以使用分层抽样重新切。对593张图简单随机切分大概率没问题但遇到某一类只有二三十张的情况就要注意了。另外如果文件名里有camera_01、camera_02这类场景前缀说明图片可能来自连续视频抽帧连续的几十帧几乎一样绝不能同时进train和val否则验证集就是训练集的近亲mAP会虚高到没有参考价值。3.2 写出一份能跑的data.yaml5个参数说清楚YOLOv8要求一个yaml文件来指路数据和类别名。很多教程把这一笔带过实际上这里出的问题比训练命令多得多。我给你一份可直接改的模板path: /absolute/path/to/phone_dataset train: images/train val: images/val test: images/test nc: 3 names: 0: phone 1: play 2: call五个参数各是干什么的path是整个数据集的绝对路径它决定下面train和val是相对谁找的train、val、test写的是分割后的图片目录路径nc是类别个数必须和标签txt里最大类别索引1一致names是类别索引到字符串的映射。注意train值指向的是图片目录不要写成images/train/xx.jpg这类文件路径YOLO会自己找同名txt。最容易被忽略的是names顺序。它不是随意写的标签txt里索引0叫什么names[0]就必须叫什么否则训练时语义是反的损失函数照样能收敛但推理出来全是对不上号的东西。如果训练前你改了类别索引顺序那训练后所有历史标签都要跟着改最稳妥的办法是永远不重排标签只在可视化时映射。3.3 从Anaconda环境到一条训练命令yolo v8 anaconda环境配置要求不算苛刻Python 3.10、PyTorch 2.x、ultralytics包就够了。新建环境时顺手把opencv一起装上画图和后续推理都要用conda create -n yolo python3.10 -y conda activate yolo pip install ultralyticsultralytics会自动拉取pytorch。如果你公司网络下载慢可以先装CPU版pytorch把流程跑通再换成GPU版训练。装完以后先执行nvidia-smi看一眼显存这对后面的batch参数很关键。经验值是这样8G显存跑YOLOv8n可以用batch 166G显存建议16降为84G显存就不要考虑GPU训练了直接换小batch跑CPU一个100轮训练可能要四五个小时但至少能验证流程。启动训练的命令如下cd phone_dataset yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0参数含义分别是detect train是训练入口datadata.yaml指向配置文件modelyolov8n.pt表示从COCO预训练权重开始微调n是nano版本模型最小、速度最快适合593张小数据量场景epochs100训练100轮对这个数据量足够imgsz640输入分辨率保持默认batch16按显存调整device0是第一张显卡没GPU就写cpu。训练过程中终端会打印每一轮的box_loss、cls_loss、dfl_loss和mAP50。box_loss是边界框回归损失cls_loss是分类损失dfl_loss是分布焦点损失三者加权求和就是总损失。网上yolo损失函数的讲解材料很多你不需要背公式只要知道一个经验如果box_loss一直高位震荡不下降多半是标注框本身画得乱如果cls_loss下降但box_loss不降说明分类容易学而定位难学可以考虑把imgsz从640调到960或者换yolov8s试一次。3.4 训练完别只看loss验证集输出才是模型的真实嘴脸训练结束后runs/detect/train/下面会生成一组文件重点看confusion_matrix.png和results.png。results.png里面有两根mAP50曲线一根是训练集一根是验证集。如果训练集mAP接近1.0而验证集只有0.6说明模型已经开始背图片此时epochs设大反而有害。更直接的做法是用刚训好的权重跑一遍验证集图片把预测结果画出来yolo predict modelruns/detect/train/weights/best.pt sourceimages/val save_txtTruesourceimages/val会遍历验证集所有图save_txtTrue把每张图的预测结果存成txt你随便挑几张错图看看是漏检还是误检。我一般还会专门找一个只有手机放在桌上、没有任何人的视频片段来测因为这类数据在训练集里可能很少最容易暴露模型的定位偏差。到这里第一个版本的模型已经能用了但距离落地还差一次系统的排雷。4. 避坑手记三类目标为什么最容易互相打架以及五个典型翻车点手机、玩手机、打电话这三个类别在YOLO眼里并没有标题那么清晰。手机是一个静态物体玩手机是一个动作打电话是一个更细分的动作三者之间的边界在二维图像上非常模糊。下面五个问题是我在这个方向反复遇到过的每一条都按现象、原因、解决拆开讲。4.1 手机和玩手机同时出现时预测框在两者之间乱跳现象同一段监控视频里模型有时框住桌面上的一部手机有时框住手里握着手机的手类别在phone和play之间来回跳置信度还不低。原因标注数据里phone类的负样本不克制桌面手机和手持手机混在一起。在YOLO训练中如果手机类既标桌面手机又标手持手机模型学到的是所有长得像手机的东西而play类只出现在手部区域两个类特征重叠严重。解决把桌面手机和手持手机分开。最直接的办法是给phone类立一条规则phone只标桌面或支架上的手机手里拿的一律标play。然后去标注文件里把所有标注为phone但实际是手持手机的框找出来批量改类别。这类批量替换脚本很简单但前提还是靠人眼确认样本from pathlib import Path labels_dir Path(labels) for txt in labels_dir.glob(*.txt): lines txt.read_text(encodingutf-8).splitlines() new_lines [] for line in lines: # 这里假设类别0是phone类别1是play按实际索引调整 if int(line.split()[0]) 0: new_lines.append(line.replace(0 , 1 , 1)) else: new_lines.append(line) txt.write_text(\n.join(new_lines), encodingutf-8)注意你无法用纯脚本判断一个phone框是不是手持这步依赖目视抽检。所以更稳妥的做法是先从训练集里随机抽出20张含phone的图肉眼看到混标比例超过30%时就回标注工具统一修改。语义边界越暧昧越要在标注阶段用文字写清楚判定规则后续接手的人才知道该按什么标准标。4.2 打电话被识别成玩手机现象验证集里人在打电话、手机贴在耳边模型却输出play置信度还特别高有时甚至会框出耳朵而不是手机。原因这个数据集只有593张分布上玩手机样本通常远多于打电话样本而两类在人手握手机这个外观上高度相似。分类器学到的不是手机贴近耳朵这个动作而是手部有个矩形物体这个特征所以会把手部有手机的样本硬分到数量更多的play上。解决先确认call类的图像覆盖数。如果call只有几十张要做三件事一是对call类过采样把含call的图片在训练时重复读入ultralytics里最省事的做法是把这些图片复制一份放到同目录文件名加后缀再重新生成标签二是把imgsz增大到960让贴近耳朵这种空间关系更容易被卷积层捕捉三是把推理时的conf阈值设低一点比如0.25同时在业务逻辑里增加规则当play和call两个框高度重叠时只保留得分更高的那个避免同一个目标输出两个类别。4.3 训练集loss很低验证集mAP就是上不去现象results.png里训练集box_loss一路往下mAP50却一直在0.5左右抖动换成best.pt一测全是漏检。原因一种情况是数据量太小模型在训练集上过拟合另一种更隐蔽——切分时没有先按场景分组导致标注相似的连续帧同时出现在训练和验证里。监控视频抽帧得到的数据集连续几帧几乎一样如果随机切分验证集里全是训练集的近亲mAP虚高看起来很好的模型换个真实场景就崩。解决如果图片名能看出场景编号或视频编号在划分前先按这些编号做分组同一个场景的图只能整个进入训练集或整个进入验证集。你可以在3.1的划分脚本里加一层groupby逻辑先把图片路径按场景前缀分组再对分组列表洗牌最后把整组图片划到某个split。做完这一点再去看train loss和val loss分离点通常第20轮到第30轮开始明显拉开这时epochs就要往下调或者换用更小的yolov8n并增大weight_decay。对小数据量优先用小模型跑通再换大模型对比不要上来就训练yolov8x。4.4 暗光、反光和遮挡场景集体漏检现象白天拉上窗帘的工位、晚上路灯下的行人都检不到但画面整体很亮的时候一切正常。原因593张图大多来自正常光照模型没见过的暗光纹理被当成噪声抑制掉了。YOLO本身对光照变化有一定鲁棒性但数据集太小覆盖不了屏幕反光、手机屏幕高光和暗光环境这种高动态范围场景。解决最省钱的办法是在推理入口加一个预处理用OpenCV做自适应伽马校正import cv2 import numpy as np def gamma_fix(img, low0.5, high2.0): gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) mean_brightness gray.mean() if mean_brightness 80: gamma high elif mean_brightness 180: gamma low else: gamma 1.0 lut np.array([((i / 255.0) ** gamma) * 255 for i in range(256)]).astype(uint8) return cv2.LUT(img, lut)这个函数做的事很简单算整帧灰度均值暗图提亮、亮图压暗再通过查表映射完成伽马校正。它不是银弹但常常能把漏检变成低置信度检测。要真正根治还是要靠训练时保留mosaic、mixup和random_hsv这些增强ultralytics的augment参数默认全开小数据集下建议不要关同时收集新场景图用当前模型预标注后人工修正再混进训练集重训。4.5 标签坐标越界和空标注文件导致训练直接崩现象训练到一半报错提示某个gt框中心点下标越界或者Image has no labels看起来像程序bug其实是数据bug。原因空标注文件是标注工具导出时留下的空txt图片存在但没有标注内容坐标越界是画框时拖到了边缘外导出后中心点归一化值已经不在0到1之间。YOLO训练时数据增强会对框做仿射变换越界坐标会被放得更大轻则loss跳一下重则训练中断。解决回到第2章的体检脚本把异常文件筛出来。空标注文件直接删除对应图片要么删掉要么手工补标越界坐标做裁剪把xc、yc、w、h限制在[0,1]区间并保证w和h最小不小于0.01。这类问题肉眼看不见养成每次拿到新数据集先跑一遍体检的习惯能省掉后面大量排查时间。血的教训是不要相信任何数据集作者说的已经清理干净脚本跑一遍只要几秒但它能帮你挡掉一个小时的排错。5. 把best.pt用起来视频帧推理、置信度调参与数据自增闭环模型文件已经在runs/detect/train/weights/下面了最后讲讲怎么把它接进自己的代码里以及后续如何让它越用越准。先给一个最直接的推理脚本对视频流逐帧检测import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) cap cv2.VideoCapture(test.mp4) while True: ret, frame cap.read() if not ret: break results model(frame, conf0.35, imgsz640, verboseFalse)[0] for box in results.boxes: cls int(box.cls[0]) conf float(box.conf[0]) x1, y1, x2, y2 [int(v) for v in box.xyxy[0]] if cls in (1, 2): # play或call cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(frame, f{model.names[cls]} {conf:.2f}, (x1, max(0, y1 - 8)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imshow(monitor, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()代码逻辑是逐帧读取把帧交给模型推理然后只画play和call两个类别按q退出。conf0.35是置信度阈值误报多就往0.5调漏检多就往0.25调。imgsz尽量和训练时保持一致训练用640推理就别突然换960否则框的位置会整体偏移。有一个细节值得养成习惯推理输出里把类别名映射出来不要只记索引索引一旦和names顺序对不上线上判断就会全错。后续想让模型越用越准最有效的是做一个小闭环把真实业务视频抽帧先用当前best.pt自动打标再人工把错框删掉、漏框补上最后合并到训练集重新训练。这个流程每两周跑一次比换更大模型见效快得多。593张图启动的这套流程价值不在模型本身而在它逼你把数据迭代的每个环节都走通了一遍。我自己的习惯是每次训完模型第一时间把验证集里预测错误的图单独存一个目录命名带上真实类别和预测类别下次拿到新数据先看这些错图找共性。看多了以后你会发现手机、玩手机、打电话这类任务的核心从来不是模型多先进而是类别边界划得多清楚。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。