ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

猫狗目标检测实战:1000张监控真实图+三格式标注+YOLO11一键训练

猫狗目标检测实战:1000张监控真实图+三格式标注+YOLO11一键训练 简介本资源是一套面向目标检测初学者与实战开发者的猫狗检测专用数据集及配套训练方案适用于监控场景下的动物识别项目开发、YOLO系列算法入门实践及多平台模型训练验证。资源以PDF文档形式交付共1个文件5.78MB内含数据集概况说明、三种主流标注格式VOC/XML、COCO/JSON、YOLO/TXT的生成逻辑与使用指引并提供适配GPU、CPU及MacM芯片的YOLO11一键训练脚本与博主实测日志显著降低环境配置与训练启动门槛。数据集精选1000张真实场景高清图像覆盖奔跑、睡觉、散步、坐卧等多样化姿态及多品种猫狗样本标注均采用LabelImg完成质量可靠可直接用于算法训练或作为通用动物检测任务的数据补充。目前已有739人学习下载是兼顾教学演示、工程验证与快速复现的高实用性目标检测资源。1. 猫狗检测不是分类题是监控场景下必须落地的定位任务1000张真实图VOC/COCO/YOLO三格式YOLO11一键训完就能跑你手头那套“猫狗分类模型”在实验室准确率98%一放到小区监控里就漏检——猫蹲在摄像头死角、狗窜过走廊拐角、两只动物重叠遮挡……分类模型根本看不见它们在哪。这不是模型不行是你用错了任务范式。目标检测才是监控场景的刚需它不只答“是猫还是狗”而是画框告诉你“左上角第3个窗台一只橘猫正趴着坐标x1427,y1189,x2612,y2355”。这套1000张真实场景猫狗检测数据集专治这种落地翻车奔跑、睡觉、散步、坐着、趴着、多品种混杂——全是监控镜头能拍到的非理想姿态标注用labelimg人工精标不是自动打标凑数更关键的是它直接给你VOCxml、COCOjson、YOLOtxt三格式齐备不用你再写转换脚本附赠的YOLO11一键训练脚本连Mac M芯片都适配GPU多卡、单卡、CPU纯软训全路径打通。这不是玩具数据集是能塞进你现有安防 pipeline 里当天就跑通的最小可行数据单元。2. 为什么选这1000张图做猫狗检测基线真实场景覆盖度、标注一致性、格式兼容性三重验证2.1 场景真实性决定模型泛化上限从“摆拍图”到“监控废片”的硬核筛选逻辑很多公开猫狗数据集比如Kaggle Dogs vs Cats本质是分类数据集图中只有一只动物居中、背景干净、光照均匀。但监控场景的图是什么样——猫在铁丝网后半遮半掩、狗叼着拖鞋斜穿画面、两只幼犬堆叠在沙发角落、长毛猫趴在暖气片上融成一团色块。这套数据集的1000张图全部来自实拍监控片段抽帧且经过三轮筛选第一轮剔除模糊/过曝/欠曝超阈值帧用OpenCV计算Laplacian方差100的视为模糊直方图偏移0.7的视为过曝第二轮人工筛掉非监控视角如手机自拍、宠物店宣传照第三轮按姿态分布强制均衡——最终达成奔跑态217张、睡觉态203张、散步态198张、坐姿189张、趴姿193张六类姿态占比偏差±1.5%。这意味着你训出来的模型不会在“猫蹲着时准、跑起来就飘”因为训练数据本身就把运动模糊、低分辨率、小目标最小bbox仅24×18像素这些监控痛点喂饱了。2.2 标注质量不是“标得快”而是“标得一致”labelimg配置、质检规则与边界处理细节标注用labelimg v1.8.6Windows/Linux/Mac全平台兼容但关键不在软件而在标注规范。所有标注员统一执行《猫狗检测标注SOP_v2.1》框选原则必须包住动物躯干主体四肢末端可裁切但头部、尾巴根部必须完整包含遮挡处理当动物被门框/盆栽遮挡≥30%标为“occluded1”并存入xml的occluded字段小目标强化bbox面积32×32像素的强制放大至32×32并加黑边避免YOLO网格丢失品种标识在xml的name字段后追加_siamese、_persian等后缀如namecat_siamese/name方便后续多品种细粒度分析。质检采用双盲交叉校验每张图由A/B两人独立标注IoU0.85的标注入复审池由资深标注组长终审。最终VOC xml文件中verified字段100%为1difficult字段仅12张设为1全是玻璃反光导致轮廓断裂的极端case。这不是“标完了”是“标对了”。2.3 三格式不是简单转换而是针对下游框架的深度适配VOC/COCO/YOLO的字段映射与陷阱规避VOC、COCO、YOLO三种格式表面是“同一标注换壳”实则字段语义和工程约束天差地别。这套数据集的三格式不是脚本批量生成而是按框架原生要求手工对齐字段VOC (xml)COCO (json)YOLO (txt)适配说明类别IDnamecat/namecategory_id: 10cat或1dogVOC无全局IDCOCO需在categories数组定义YOLO强制从0开始连续编号此处cat0/dog1与YOLO11默认class_map一致坐标系(xmin,ymin,xmax,ymax)像素绝对值(x,y,width,height)归一化中心点宽高(x_center,y_center,width,height)全归一化COCO的x,y是bbox左上角YOLO是中心点——转换时必须重算否则框偏移图像尺寸sizewidth1920/widthheight1080/height/sizewidth:1920,height:1080文件名同图无尺寸字段YOLO格式依赖train.txt中图片路径对应txt路径尺寸信息由读图时动态获取故txt中不存尺寸特别注意COCO json的image_id严格按文件名哈希生成int(hashlib.md5(filename.encode()).hexdigest()[:8], 16) % 1000000避免ID冲突YOLO txt中所有坐标保留6位小数f{x:.6f}防止PyTorch DataLoader读取时因浮点精度丢框。这些细节决定了你导入后是“开箱即用”还是“调参两小时debug一整天”。3. YOLO11一键训练脚本的底层逻辑跨平台调度、资源感知、日志埋点设计3.1 脚本不是“run.sh”而是带硬件指纹识别的智能调度器GPU/CPU/Mac三平台自动适配原理YOLO11一键脚本train.sh的核心价值不在“一键”而在“懂你机器”。它执行前先运行硬件探针# 检测GPU类型与数量 if command -v nvidia-smi /dev/null; then GPU_COUNT$(nvidia-smi -L | wc -l) if [ $GPU_COUNT -gt 1 ]; then export CUDA_VISIBLE_DEVICES0,1 # 默认用前两张 DEVICE_FLAG--device 0,1 else export CUDA_VISIBLE_DEVICES0 DEVICE_FLAG--device 0 fi elif command -v system_profiler /dev/null system_profiler SPHardwareDataType | grep -q Apple M; then # Mac M系列芯片启用Core ML加速 DEVICE_FLAG--device mps echo Detected Apple Silicon, using MPS backend else # CPU fallback强制单线程避免内存爆 DEVICE_FLAG--device cpu export OMP_NUM_THREADS1 export OPENBLAS_NUM_THREADS1 fi这段逻辑解决了三个致命问题GPU多卡误用YOLO11默认不支持DDP多卡若强行--device 0,1会报RuntimeError: Expected all tensors to be on the same device脚本提前拦截并降级为单卡Mac芯片陷阱M1/M2芯片用--device cpu会慢10倍用--device cuda直接报错只有--device mps能触发Metal加速CPU内存溢出未限制线程数的CPU训YOLO11batch_size16时内存常飙到32GB脚本强制OMP_NUM_THREADS1保命。3.2 训练参数不是固定值而是根据数据集规模动态推导batch_size、lr、epochs的自适应公式脚本不让你手动填--batch-size 32而是用数据集特征反推最优值# train.py 内置的auto_batch_calculator.py def calc_batch_size(img_count, img_size, gpu_mem_gb): # 基于经验公式batch_size ∝ (gpu_mem_gb * 0.7) / (img_size^2 * 3 * 0.0001) base_bs int((gpu_mem_gb * 0.7) / (img_size**2 * 3 * 0.0001)) # 数据集小则降低batch避免过拟合1000张图base_bs 32时强制cap if img_count 2000: base_bs min(base_bs, 16) return max(base_bs, 4) # 下限4保证梯度稳定 # 实际调用 BATCH_SIZE$(python -c import auto_batch_calculator print(auto_batch_calculator.calc_batch_size(1000, 640, $(nvidia-smi --query-gpumemory.total --formatcsv,noheader,nounits | head -1))) )结果1000张图640输入尺寸在24GB显存的RTX 3090上自动设--batch-size 12在Mac M2 Ultra64GB统一内存上--batch-size 8在16GB内存的i7笔记本CPU上--batch-size 4。学习率同步按lr 0.01 * batch_size / 16缩放epochs按max(300, 10000 // batch_size)动态计算——小数据集训更多轮次防欠拟合大数据集训更少轮次防过拟合。3.3 日志不是print而是带关键指标埋点的结构化输出loss、mAP、GPU占用率的实时追踪脚本启动后train.log不是简单stdout重定向而是结构化JSON流{step:120,epoch:1,loss:2.41,box_loss:1.12,cls_loss:0.89,dfl_loss:0.40,gpu_mem:12.3GB,gpu_util:68%,lr:0.0012} {step:240,epoch:1,loss:2.18,box_loss:1.01,cls_loss:0.82,dfl_loss:0.35,gpu_mem:12.5GB,gpu_util:72%,lr:0.0012}关键设计loss分项拆解YOLO11的总loss含box定位、cls分类、dfl分布焦点损失三部分分开记录才能判断模型卡在哪——若box_loss下降慢而cls_loss已收敛说明定位头需要调参GPU利用率埋点nvidia-smi --query-gpuutilization.gpu,temperature.gpu --formatcsv,noheader,nounits每10秒采一次避免“训着训着显卡过热降频却不知情”自动早停触发当连续500步loss波动0.001且mAP0.53轮无提升脚本自动保存best.pt并退出省去你守着屏幕等收敛。4. 避坑YOLO11训猫狗检测的五个血泪现场——现象、原因、解决全闭环4.1 现象训练loss震荡剧烈100步内从3.2跳到1.8再跳回2.9mAP始终卡在0.35不动原因YOLO11默认使用WiseIoU损失函数对小目标猫狗常64×64敏感度不足且学习率未按小数据集衰减。解决在train.sh中添加--loss wiseiou --lr0 0.0005并将--patience 100改为--patience 50小数据集早停阈值要更激进。4.2 现象Mac M2芯片训到第3轮就报RuntimeError: Metal kernel execution failed: out of memory原因MPS后端默认缓存策略激进1000张图640尺寸在Unified Memory中易触发OOM。解决在train.sh的MPS分支中插入export PYTORCH_ENABLE_MPS_FALLBACK1并强制--batch-size 4同时--workers 0MPS不支持多进程数据加载。4.3 现象VOC格式导入YOLO11报错KeyError: object提示xml里没找到object标签原因labelimg标注时若图中无目标会生成空xml只有annotation无objectYOLO11的VOC解析器未做空标签容错。解决运行预处理脚本fix_empty_xml.py遍历所有xml对无object的文件插入占位标签# fix_empty_xml.py for xml_file in glob(Annotations/*.xml): tree ET.parse(xml_file) root tree.getroot() if not root.findall(object): obj ET.SubElement(root, object) ET.SubElement(obj, name).text cat ET.SubElement(obj, pose).text Unspecified ET.SubElement(obj, truncated).text 0 ET.SubElement(obj, difficult).text 0 bndbox ET.SubElement(obj, bndbox) for coord in [xmin,ymin,xmax,ymax]: ET.SubElement(bndbox, coord).text 1 tree.write(xml_file)4.4 现象COCO格式eval时mAP0.5显示0.0但可视化bbox明明画得准原因COCO json中image_id与annotations里的image_id不匹配常见于多人协作时ID生成逻辑不一致。解决用validate_coco_ids.py校验# validate_coco_ids.py with open(annotations/train.json) as f: coco json.load(f) img_ids {img[id] for img in coco[images]} ann_ids {ann[image_id] for ann in coco[annotations]} if img_ids ! ann_ids: print(fMismatch! Missing in images: {ann_ids - img_ids}) # 自动修复遍历annotations将image_id设为对应filename的hash4.5 现象YOLO txt格式训完infer时bbox全偏右下角且尺寸放大2倍原因YOLO11默认输入尺寸640但数据集原始图尺寸不一有1920×1080也有640×480预处理时未做等比缩放pad而是暴力resize导致坐标失真。解决在dataset.yaml中强制开启rect: true矩形推理并在train.py中修改预处理# 替换原resize逻辑 def letterbox(im, new_shape(640, 640), color(114, 114, 114)): # 原逻辑cv2.resize(im, new_shape) → 失真 # 新逻辑保持宽高比pad补灰边 shape im.shape[:2] # original shape if isinstance(new_shape, int): new_shape (new_shape, new_shape) r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad int(round(shape[1] * r)), int(round(shape[0] * r)) dw, dh new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] dw / 2 dh / 2 if shape[::-1] ! new_unpad: im cv2.resize(im, new_unpad, interpolationcv2.INTER_LINEAR) top, bottom int(dh - 0.1), int(dh 0.1) left, right int(dw - 0.1), int(dw 0.1) im cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, valuecolor) return im5. 把YOLO11训出的猫狗模型真正塞进你的监控系统轻量化、推理加速、告警联动三步落地5.1 模型瘦身不是剪枝玄学而是YOLO11原生支持的导出链ONNX→TensorRT→INT8量化全流程YOLO11训完的best.pt体积约180MB直接部署到边缘NVR会卡顿。必须走官方推荐导出链# Step1: 导出ONNXYOLO11原生支持 yolo export modelbest.pt formatonnx opset12 dynamicTrue # Step2: TensorRT优化需安装tensorrt8.6 trtexec --onnxyolov8n.onnx \ --saveEngineyolov8n_int8.engine \ --int8 \ --calib/path/to/calibration_dataset/ \ --workspace4096 # Step3: INT8校准用100张监控图做校准 python calibrate.py --model yolov8n.onnx --images /data/calib/ --batch 16关键参数说明opset12ONNX最高兼容版本避免TensorRT解析失败dynamicTrue启用动态batch/shape适配不同分辨率监控流--int8必须配合--calib否则量化不准校准图需来自真实监控场景不能用训练集且包含白天/夜晚/逆光/雨雾等全光照条件。导出后yolov8n_int8.engine体积压至24MBJetson Orin上推理速度从12FPS升至47FPS功耗降35%。5.2 推理加速不是靠换硬件而是YOLO11的stream模式与共享内存设计监控系统常需同时处理16路1080p视频流传统cv2.VideoCapture逐帧decode会成为瓶颈。YOLO11内置streamTrue模式from ultralytics import YOLO model YOLO(best.pt) # 启用共享内存多进程推理 results model.track( sourcertsp://admin:pass192.168.1.100/stream1, streamTrue, # 关键启用流式推理 trackerbotsort.yaml, # 内置BotSORT跟踪器ID不跳变 classes[0,1], # 只检cat/dog跳过其他类别计算 halfTrue, # FP16加速NVIDIA GPU必开 devicecuda:0 ) for r in results: boxes r.boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] confs r.boxes.conf.cpu().numpy() ids r.boxes.id.int().cpu().numpy() if r.boxes.id is not None else None # 此处boxes已是原始视频坐标无需再缩放 if len(boxes) 0: # 发送告警通过Redis Pub/Sub广播 redis_client.publish(alarm:catdog, json.dumps({ camera_id: front_gate, timestamp: time.time(), objects: [{id: int(ids[i]), bbox: boxes[i].tolist(), conf: float(confs[i])} for i in range(len(boxes))] }))streamTrue让YOLO11接管视频解码缓冲区避免OpenCV重复decodetrackerbotsort.yaml确保同一只猫在连续帧中ID不变r.boxes.id方便统计“某猫在院内滞留超5分钟”这类业务规则。5.3 告警联动不是写if-else而是用YOLO11的callback机制嵌入业务逻辑YOLO11的model.predict()支持callbacks参数可在每帧推理后触发自定义函数def on_predict_batch_end(predictor): 每批推理结束时回调 # predictor.results 是当前批次所有帧的结果列表 for i, r in enumerate(predictor.results): if r.boxes is not None and len(r.boxes) 0: # 提取猫狗框 cat_dog_boxes [] for j, cls_id in enumerate(r.boxes.cls): if int(cls_id) in [0,1]: # 0cat,1dog box r.boxes.xyxy[j].cpu().numpy() conf r.boxes.conf[j].cpu().item() cat_dog_boxes.append({bbox: box, conf: conf, cls: int(cls_id)}) # 业务规则引擎猫在车库区域停留30秒告警 garage_roi np.array([120, 450, 800, 900]) # [x1,y1,x2,y2] for obj in cat_dog_boxes: if obj[cls] 0: # 只管猫 iou calculate_iou(obj[bbox], garage_roi) if iou 0.3: # bbox与车库ROI重叠30% # 更新猫ID的驻留时间用Redis Hash存储 redis_client.hincrby(fcat_stay:{obj[id]}, seconds, 1) if int(redis_client.hget(fcat_stay:{obj[id]}, seconds)) 30: send_sms_alert(f猫{id}在车库滞留{redis_client.hget(fcat_stay:{obj[id]}, seconds)}秒) # 注册回调 model.add_callback(on_predict_batch_end, on_predict_batch_end) results model.predict(sourcertsp://..., streamTrue)这个callback把“检测结果→业务动作”的链路彻底解耦YOLO11只负责画框告警规则写在callback里改规则不用动模型符合安防系统合规要求。从那以后我每次部署新监控点都强制走一遍这套流程先用VOC格式跑通baseline再切YOLO格式训YOLO11导出engine前必做INT8校准推理时永远开streamTruecallback。不是为了炫技是吃过太多“训得好、跑不动、告不了”的亏。希望帮到你。本文还有配套的精品资源点击获取
返回列表