简介:本资源是面向计算机视觉初学者与深度学习实践者的水果目标检测专用VOC格式数据集,聚焦目标检测任务中的类别识别与定位能力训练,适用于智能农业、食品质检等实际场景的算法验证与模型微调。压缩包共400个文件,含200张PNG格式水果图像(JPEGImages目录)与200份对应XML标注文件(Annotations目录),完整提供苹果、香蕉等常见水果类别的边界框坐标及类别标签,结构严格遵循PASCAL VOC规范,便于直接接入Faster R-CNN、YOLO等主流检测框架。资源大小为51.3MB,轻量易下载,目录层级清晰、命名规范,附带典型样本(如fruit163.png、fruit209.png等)确保图像质量与标注一致性。目前已有951人学习下载,配套博文深入解析数据集组织逻辑、标注字段含义及常见预处理转换方法,助力读者快速完成数据加载、格式适配与端到端训练流程。
1. 拿到数据集先别急着训练:先搞懂VOC格式到底存了什么
最近我在捣鼓一个水果分类目标检测项目,手头这份“水果分类目标检测VOC数据集.zip”挺有意思。先说结论:这个压缩包本质上是一套已经标注好的、按Pascal VOC标准组织的水果检测数据集,里面包含苹果、香蕉、橙子这类常见水果的图片,以及每张图片对应的目标边界框(Bounding Box)和类别标签。你可以直接拿它来训练YOLO系列、SSD、Faster R-CNN这类主流目标检测模型。
很多初学者拿到数据集的第一反应就是解压、扔进训练脚本、开跑,结果跑出来的mAP惨不忍睹,然后开始怀疑模型有问题。其实问题往往出在你根本不了解自己的数据长什么样。VOC格式数据集有一套固定的目录规范,搞懂它再动手,比盲目调参重要得多。
1.1 解压之后,你会看到的目录结构长这样
一个标准的VOC格式数据集,解压后通常包含以下核心目录:
VOCdevkit/ └── VOC2007/ (或者 VOC2012 / 自定义名称) ├── JPEGImages/ # 存放所有原始图片 ├── Annotations/ # 存放所有XML标注文件 ├── ImageSets/ │ └── Main/ # 存放训练集、验证集、测试集的划分文件 ├── SegmentationClass/ # 语义分割标签,检测任务用不到 └── SegmentationObject/ # 实例分割标签,检测任务用不到JPEGImages目录下是所有的原始图片,一般统一命名为“000001.jpg”“000002.jpg”这样六位数字递增的格式。Annotations目录下是配套的XML文件,一个XML对应一张图片,文件名和图片名完全一致。ImageSets/Main目录下是几个txt文件,比如train.txt、val.txt、trainval.txt,里面记录的是图片文件名(不带扩展名),用来告诉训练脚本哪些图片用于训练,哪些用于验证。
这里有个细节很多人会忽略:图片文件和标注文件的名称必须一一对应,否则训练时会报“找不到标注文件”或者“图片与标注不匹配”的错误。我见过有人从网上下载数据集后,自己重新整理文件名,结果编号错位,训练出来的模型完全乱套,检测框全偏到背景上。
1.2 打开一个XML标注文件,里面到底写了什么
XML标注文件是VOC格式的核心,它详细记录了图片里每个目标的信息。用文本编辑器打开一个标注文件,你会看到类似这样的结构:
<annotation> <folder>JPEGImages</folder> <filename>000001.jpg</filename> <path>/home/user/VOCdevkit/VOC2007/JPEGImages/000001.jpg</path> <source> <database>Unknown</database> </source> <size> <width>500</width> <height>375</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>apple</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>100</xmin> <ymin>150</ymin> <xmax>200</xmax> <ymax>250</ymax> </bndbox> </object> </annotation>各字段的含义:
<filename>:当前标注对应的图片文件名。<size>:图片的宽度、高度和通道数(深度)。这个信息很重要,因为很多模型在预处理时需要根据原始尺寸归一化边界框坐标。<object>:一个目标物体,一张图片里有多少个物体,就有多少个<object>节点。<name>:类别名称,比如apple、banana、orange。<truncated>:目标是否被截断(0表示完整,1表示超出图片边缘),一般简单数据集里都是0。<difficult>:目标是否难以识别,1表示困难样本,训练时通常会被忽略。<bndbox>:边界框坐标,xmin/ymin是左上角坐标,xmax/ymax是右下角坐标,单位是像素。
你拿到的这份水果数据集,里面的标签大概率就是apple、banana、orange这三类,也可能有葡萄、草莓之类。不管类别是什么,结构基本一致。搞清楚这些字段,后续做数据清洗、格式转换、数据增强时才能游刃有余。
提示:目标检测模型接收的标签格式五花八门。VOC是XML框坐标,YOLO系列常用的是txt格式的归一化中心点坐标和宽高,COCO是JSON格式。所以用这份数据集去训练YOLOv8之前,通常需要做一步格式转换,这个后面会详细讲。
2. 数据质量决定模型上限:水果数据集的关键细节
很多人以为目标检测的难点在于模型结构、训练技巧,但以我自己的实操经验,数据集的干净程度和质量,往往比模型本身更能决定最终效果。一个水果分类检测模型,如果数据里充斥着模糊图片、错误标注、类别严重不均衡,哪怕你用YOLOv8这种SOTA模型也救不回来。
2.1 先做一次全面的数据体检
拿到数据集别急着训练,先花一两个小时做体检。这是我在多个项目里踩坑后养成的习惯,非常值得。
第一步,统计图片数量和各类别目标数量。可以直接写个简单的Python脚本,遍历所有XML标注文件,统计每个类别的目标个数:
import os import xml.etree.ElementTree as ET annotations_dir = "VOC2007/Annotations" class_count = {} for xml_file in os.listdir(annotations_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(annotations_dir, xml_file)) root = tree.getroot() for obj in root.findall("object"): name = obj.find("name").text class_count[name] = class_count.get(name, 0) + 1 print(class_count)如果发现苹果有5000个标注框,而香蕉只有200个,这就是典型的类别不平衡问题。训练出来的模型会对苹果格外敏感,对香蕉的漏检率会明显偏高。解决思路有三个:一是补充香蕉类别的图片数据,二是对香蕉图片做数据增强(旋转、缩放、加噪等),三是给香蕉类别分配更高的损失权重。
第二步,检查图片是否都能正常打开、格式是否统一。有些数据集里混入了损坏的图片,或者有些图片是灰度图、有些是RGB图。模型输入通常要求统一尺寸和通道数,混入异常图片会导致训练过程中突然报错或者loss异常。
from PIL import Image import os images_dir = "VOC2007/JPEGImages" count = 0 for img_file in os.listdir(images_dir): img_path = os.path.join(images_dir, img_file) try: img = Image.open(img_path) img.verify() except Exception as e: print(f"损坏图片: {img_file}, 错误: {e}") count += 1 print(f"共发现 {count} 张损坏图片")第三步,随机抽几十张图片,把标注框画上去,肉眼检查标注是否准确。这一步特别重要,因为有些标注框要么框得太大——把背景也框进去了,要么太小——只框住了水果的一半,要么干脆标错了类别。用OpenCV或者matplotlib可以把边界框画出来看:
import cv2 import xml.etree.ElementTree as ET def draw_boxes(img_path, xml_path): img = cv2.imread(img_path) tree = ET.parse(xml_path) root = tree.getroot() for obj in root.findall("object"): name = obj.find("name").text bbox = obj.find("bndbox") xmin = int(bbox.find("xmin").text) ymin = int(bbox.find("ymin").text) xmax = int(bbox.find("xmax").text) ymax = int(bbox.find("ymax").text) cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2) cv2.putText(img, name, (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img # 随机抽一张图检查 img_path = "VOC2007/JPEGImages/000001.jpg" xml_path = "VOC2007/Annotations/000001.xml" result = draw_boxes(img_path, xml_path) cv2.imwrite("check.jpg", result)这个操作虽然简单,但能帮你快速发现大量问题。我拿到这份水果数据集检查时就发现,有一部分图片里的苹果和番茄长得特别像,而且标注框甚至有标错的。这种问题不提前发现,模型学到的东西就是错的。
2.2 小目标问题:水果检测绕不开的坎
很多水果图片里,果实特别小,尤其那种挂在树上的远景照片。比如一棵苹果树,整张图1000像素宽,一个苹果可能只有二三十个像素大小。这种就是典型的小目标检测难题,也是目标检测领域公认的难点。
小目标之所以难,是因为在卷积神经网络的层层下采样过程中,小目标的特征信息很容易丢失。比如YOLOv8的Backbone里有5次下采样,最终特征图只有输入尺寸的1/32。一个32×32像素的苹果,经过下采样后就变成1×1的特征点,模型根本没法从中提取有效的语义信息。
应对小目标问题,常用手段包括:
- 高分辨率输入:增大输入图像尺寸,比如从640×640提升到1280×1280,小目标的像素占比会明显增加。
- 多尺度训练:训练时随机缩放输入尺寸(比如在640到1280之间随机取值),让模型适应不同尺度的目标。
- 使用FPN等特征金字塔结构:YOLOv8本身就带FPN,能把浅层的高分辨率特征和深层的语义特征融合,对小目标更友好。
- 切图推理:对超大图片切成多个小图块(有重叠),分别送入模型检测,再把结果合并。
拿这份水果数据集训练时,建议先统计一下所有标注框的面积分布,看小目标占比多少。如果小目标占比高,那么训练时就要有意识地把输入分辨率调高。
实操心得:很多开源数据集里的标注框其实包含了大量“不算错但不算准”的框。做目标检测项目,最怕的就是这种“差不多”的数据。宁可少要几个标注框,也不要让错误的框混进去。我一般会先跑一轮快速训练,然后把验证集上的预测结果画出来,人工看一遍错检和漏检,再回头修正错误标注,这样比纯手工翻图检查高效得多。
3. 从零训练YOLOv8水果检测模型:完整实操流程
这份VOC格式的水果数据集,最常见的用法就是转换成YOLO格式,然后用YOLOv8训练。说实话,现在用YOLOv8训练一个自定义检测模型,已经比前几年简单太多了,但整个流程里还是有不少细节值得抠一抠。下面我按自己实际操作的顺序逐步过一遍。
3.1 环境准备与依赖安装
我的环境是Ubuntu 20.04 + Python 3.9 + CUDA 11.8 + PyTorch 2.0。如果你用Windows,在能正常安装PyTorch GPU版的前提下,后续操作也完全一样。先把基础库装齐:
pip install ultralytics opencv-python matplotlib numpyultralytics这个包自带YOLOv8的完整实现,不需要额外clone仓库。装好之后,命令行输入yolo就能看到相关的命令帮助。
另外建议安装一个GPU版本的PyTorch,如果你有NVIDIA显卡的话。检查方式:
python -c "import torch; print(torch.cuda.is_available())"输出True说明CUDA可用,训练速度会快非常多。如果没GPU,CPU也能训练水果数据集这种小规模数据集,只是慢很多。我试过用纯CPU训练几千张图片,一个epoch可能要十来分钟,而用一张中端显卡(比如RTX 3060)同样的数据,一个epoch大概不到一分钟。
3.2 关键一步:VOC格式转YOLO格式
YOLOv8训练时用的标签格式是txt文件,每行表示一个目标,格式为:
类别id x_center y_center width height注意这里的x_center、y_center、width、height都是相对于图片宽度和高度的归一化值(0到1之间的小数),不是像素坐标。类别id从0开始依次对应类别名列表中的顺序,比如apple→0,banana→1,orange→2。
所以你需要先确定自己的类别列表,然后写脚本把VOC的XML格式转成YOLO的txt格式。最简单的保留类别顺序的方式是生成一个data.yaml文件,内容类似:
train: VOC2007/ImageSets/Main/train.txt val: VOC2007/ImageSets/Main/val.txt nc: 3 names: ['apple', 'banana', 'orange']然后写转换脚本,Python代码如下:
import os import xml.etree.ElementTree as ET from PIL import Image def convert_voc_to_yolo(xml_path, img_path, output_label_path, class_names): tree = ET.parse(xml_path) root = tree.getroot() img = Image.open(img_path) w, h = img.size lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in class_names: continue class_id = class_names.index(name) bbox = obj.find("bndbox") xmin = float(bbox.find("xmin").text) ymin = float(bbox.find("ymin").text) xmax = float(bbox.find("xmax").text) ymax = float(bbox.find("ymax").text) x_center = (xmin + xmax) / 2.0 / w y_center = (ymin + ymax) / 2.0 / h box_w = (xmax - xmin) / w box_h = (ymax - ymin) / h # 过滤掉异常框:宽高为负或中心点超出图片范围 if box_w <= 0 or box_h <= 0 or x_center < 0 or x_center > 1 or y_center < 0 or y_center > 1: continue lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}") with open(output_label_path, "w") as f: f.write("\n".join(lines))转换完以后,图片文件和对应的txt标签文件放在同一个目录下,或者放在平行的两个目录中(YOLOv8支持在data.yaml里分别指定images和labels的路径)。推荐把数据组织成这个结构:
dataset/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练标签 │ └── val/ # 验证标签 └── data.yaml3.3 划分训练集和验证集
很多VOC数据集自带ImageSets/Main下的train.txt和val.txt,可以直接借用。如果没有,就自己划分。划分的原则是同源的图片不要同时出现在训练集和验证集里,比如同一颗果树连续拍摄的几十张照片,应该全部归入训练集,否则验证集就失去了意义——模型相当于开卷考试,成绩虚高。
我自己常用的划分脚本很简单:
import os import random from shutil import copy2 random.seed(42) images_dir = "VOC2007/JPEGImages" train_ratio = 0.8 all_images = [f for f in os.listdir(images_dir) if f.endswith(".jpg")] random.shuffle(all_images) split_idx = int(len(all_images) * train_ratio) train_images = all_images[:split_idx] val_images = all_images[split_idx:] # 创建目录结构(略) # 复制图片和对应的txt标签到指定目录(略)注意随机种子要固定,保证每次跑出来的划分结果一致,方便复现实验。
3.4 训练参数怎么调才能又快又稳
数据准备好了,data.yaml写好了,就可以开始训练了。YOLOv8提供了非常简单的命令行接口:
yolo train data=data.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16这里的几个参数要解释一下:
model=yolov8n.pt:模型权重。有yolov8n(nano)、yolov8s(small)、yolov8m(medium)等。水果检测任务属于简单任务,用yolov8n或yolov8s就足够了,没必要上yolov8x(extra large),训练慢而且提升有限。imgsz=640:输入图片尺寸。如果小目标多,可以试试imgsz=1024或imgsz=1280。epochs=100:训练轮数。水果数据集规模不大,100轮足够收敛。batch=16:批大小,根据显存大小调整。如果爆显存就调小到8或4,同时可以配合--cache参数把数据缓存到内存里加速。
训练过程中YOLOv8会在终端打印每轮的训练损失和验证mAP。正常情况下,train_loss会逐渐下降,mAP50(IOU阈值0.5时的平均精度)会逐步上升。如果mAP50涨到某个值后不再变化,就可以考虑提前终止训练。用patience=20参数可以开启早停机制,连续20轮mAP不提升就自动停止。
3.5 评估结果怎么知道模型好坏
训练结束后,YOLOv8会在runs/detect/train目录下生成结果文件,其中最重要的是results.png,它画出了损失曲线和mAP曲线。除此之外还有confusion_matrix.png,展示混淆矩阵,可以直观看到哪些类别容易互相混淆。
对于水果分类检测,我更关注的是漏检率。一个模型漏检一个苹果的后果,比误检一个苹果要严重得多——实际应用里,客户想看的是“我在筐里放了多少个苹果”,漏检会少计数,误检会多计数。所以配置评估时,可以把置信度阈值调低一些(比如0.25),看看不同置信度下的precision和recall曲线。
yolo val model=runs/detect/train/weights/best.pt data=data.yaml命令会输出每个类别的精确率、召回率和mAP值。如果某个类别的recall明显偏低,说明这个类别的目标经常被漏掉,需要针对性地做数据增强或补充样本。
3.6 用训练好的模型做推理
训练完成之后,用模型跑一张新图片,命令非常简单:
yolo predict model=runs/detect/train/weights/best.pt source=test.jpg模型会输出检测结果图片和txt格式的预测标签,包含检测框坐标、类别和置信度。如果想批量处理图片文件夹,把source改成文件夹路径即可。
实际部署的时候,也可以把模型导出成其他格式:
yolo export model=runs/detect/train/weights/best.pt format=onnx导出成ONNX后,就能在手机端、Web端或者其他推理框架里跑起来了。
注意:使用这份VOC数据集训练之前,务必确认类别名和你的业务场景对齐。如果原始数据里叫“apple”,你的业务代码里叫“红富士”,需要在转换时做映射。不要因为嫌麻烦而跳过这一步,后续排查错误时会让你怀疑人生。
4. 常见问题与排查技巧实录
训练目标检测模型的过程永远不可能一帆风顺。我把自己在VOC格式数据集上经常遇到的问题整理成了一份速查表,每一条背后都有真实的踩坑经历。
4.1 问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方法 |
|---|---|---|---|
| 训练报错“Can't find label file” | 标签文件和图片文件路径不匹配 | 检查data.yaml中的路径配置 | 重新组织目录结构,确保labels和images目录一一对应 |
| 训练损失下降缓慢或震荡 | 学习率过高 | 查看训练曲线,loss在较大范围波动 | 降低lr,设置lr0=0.001或更低 |
| mAP50一直为0 | 标签类别索引与data.yaml不一致 | 检查转换脚本里的class_names顺序 | 在data.yaml里核对names顺序和类别id |
| 检测框全部偏大或偏小 | 边界框坐标归一化错误 | 把转换后的txt标签画到原图上检查 | 检查VOC转YOLO时的坐标计算是否除以图片宽高 |
| 模型不收敛,loss是NaN | 图片或标签里有异常值 | 检查是否有损坏图片或标签坐标越界 | 用脚本清洗异常图片和标签 |
| 某些类别完全检测不到 | 训练集和验证集分布不一致 | 统计各类别在train和val中的数量 | 做分层采样,确保每个类别在训练集和验证集中都按比例分布 |
4.2 踩坑实录:标签索引错位
我第一次用VOC数据集训YOLOv5时,犯过一个特别愚蠢的错误。我当时自定义的类别顺序是['apple', 'banana', 'orange'],但data.yaml里写的names是['apple', 'banana', 'grape'],因为我顺手从网上抄了一段配置没改干净。结果模型训练了50多轮,mAP50始终是0。
排查过程是这样的:我先打印了几条转换后的标签,发现第三类(原来数据里的grape)被映射成了id=2,而data.yaml里id=2对应的是orange。模型收到一个“类别id=2”的标签,读出来是orange,但图片里实际标的是grape,模型当然学不会。这类问题在训练时不会报错,只会让你在mAP曲线低谷里挣扎很久。
所以我现在每次转换完格式,都会写一个“反向检查”的小脚本:把YOLO格式的txt标签画回原图,用肉眼对比原始VOC标注,确认类别和位置都没问题。
4.3 踩坑实录:图片尺寸不一致导致的目标变形
很多开源数据集的图片尺寸不统一,有的1920×1080,有的480×640。YOLOv8在训练时会做letterbox缩放,也就是保持宽高比、填充灰色边条,这本身没问题。但问题出在——如果一张图缩得太小,标注框的坐标归一化后可能非常小,接近0甚至变成负值,导致训练时出问题。
我处理过一份水果数据集,里面有几张特别小(比如100×80)的图片,转换后标签里有sx和sy出现负数的情况。原因是一些标注框超出了图片边缘。这个问题在VOC数据里不算少见,因为标注工具允许你在图片外面画框(有的工具会自动这么做)。
解决方法是写一个过滤脚本,统一把这类异常框剔除掉:
with open(label_file, "r") as f: lines = f.readlines() valid_lines = [] for line in lines: parts = line.strip().split() x_center, y_center, w, h = map(float, parts[1:]) # 剔除中心点越界或宽高小于等于0的框 if 0 < x_center < 1 and 0 < y_center < 1 and w > 0 and h > 0: valid_lines.append(line)4.4 避坑心得:训练前一定要做一次“闪电战”验证
所谓“闪电战”,就是先只拿一小部分数据(比如200张图)跑10个epoch,确认整个流程能跑通,loss有下降趋势,再启动完整训练。这样做有三大好处:
第一,及时发现数据格式问题和路径问题,不用白等几个小时的完整训练。第二,快速验证模型结构和小批量数据上能否过拟合——如果200张图跑10轮loss都降不下去,说明模型的容量或学习率设置有问题,此时调参成本极低。第三,你能提前估算完整训练需要的时间,方便安排实验计划。
这个习惯帮我在多个项目里省下了大量时间。说实话,比起模型网络结构怎么选,这些工程层面的细节往往才是决定一个目标检测项目能不能顺利落地的关键。
5. 训练完以后还能怎么玩:从数据到应用的延伸
模型训练完了,这份VOC数据集的工作才刚刚开始。目标检测项目的终极目标是落地应用,这里分享几个基于水果检测的扩展方向。
5.1 做实时视频检测
有了训练好的模型,你可以接入摄像头做实时水果检测,比如超市里自动识别水果种类的自助结账系统。用OpenCV读取视频流,把每一帧送入模型:
import cv2 from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") cap = cv2.VideoCapture(0) while cap.isOpened(): ret, frame = cap.read() if not ret: break results = model(frame) annotated_frame = results[0].plot() cv2.imshow("Fruit Detection", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows()这个扩展很简单,但马上就能看到模型在真实场景下的表现。你会发现之前训练集里没有的画面——比如反光严重的桌面、灯光偏暗的货架、水果叠在一起——模型的表现可能会有较大抖动,这也是检验数据集多样性的好机会。
5.2 做水果计数和质量分级
结合检测框的位置信息,你还能在应用层做更复杂的逻辑。比如水果叠放场景下,通过检测框的重叠程度判断是否被遮挡;通过检测框面积估算水果大小,做大小分级;通过颜色统计判断成熟度。这些都不是模型本身的功能,但检测框给你提供了基础数据。
我在自己的一次实践里,把目标检测和简单的面积统计结合起来,做了一个水果大小分拣的原型:检测每个苹果的边界框,按像素面积把苹果分成大、中、小三个等级。实测下来,在光照稳定的环境下准确率可以达到90%以上。
5.3 迁移学习:从水果到其他品类
这份数据集还有一个隐藏价值——微调底座。YOLOv8在COCO数据集上预训练的权重已经学到了一般性的物体表示能力,用水果数据微调以后,模型对“小体积、圆形、表面纹理差异明显”的物体变得比较敏感。这种特性可以迁移到其他类似的任务上,比如番茄分级、百香果检测、甚至坚果炒货的检测。
迁移学习的操作很简单:用你训练好的best.pt作为预训练权重,再换一个新的自定义数据集继续训练:
yolo train data=new_data.yaml model=runs/detect/train/weights/best.pt epochs=50这样训练通常比从COCO预训练权重开始收敛更快,因为模型已经“知道”物体长什么样了。但要注意,如果新任务的数据分布和水果差异很大(比如换成检测汽车),这种迁移的意义就不大,直接从头训练反而更可控。
根据我个人的经验,验证集mAP并不是判断模型是否可用的唯一标准。真正投入实际场景之前,一定要亲自拿手机拍几张不同光线、不同角度的水果照片去测,看看边界框是不是稳定、置信度是不是合理、漏检和重复检测的情况多不多。很多时候,跑通流程比追求更高的精度更让人踏实——精度可以后面慢慢刷,但你得先有一套能用的检测系统。
这份“水果分类目标检测VOC数据集”虽然不大,但作为入门目标检测、熟悉数据处理和模型训练流程的练手项目,已经非常够了。把它吃透,比下载一堆自己完全看不明白的大数据集有用得多。用这个压缩包去做第一个属于自己的检测模型,路就在脚下。
本文还有配套的精品资源,点击获取