简介面向目标检测入门与YOLO模型训练者的菠萝检测数据集按YOLOv5目录结构整理可直接当作现成训练集使用无需额外清洗或格式转换图像统一为640×640 RGB大图来自真实生活场景每张至少包含一个完整标注的菠萝目标。压缩包共1567个文件以783个TXT标注文件和782张JPG图片为主体另含1个类别文本文件及1个可视化Python脚本整体约52.49MB数据已划分训练集和验证集训练集693张图片与693个标签一一对应验证集89张图片与89个标签对应。标注采用YOLO相对坐标格式即classes、x_centre、y_centre、w、h仅含菠萝一个类别可视化脚本支持随机传入一张图片即可绘制边界框并保存到当前目录无需修改即可运行便于快速检查标注质量。已有156人学习适合目标检测实操、YOLO模型调优、数据标注格式学习等场景。1. 搜到「YOLO 数据集 菠萝检测」只是开始划分、class 文件、可视化脚本才是能直接训练的关键搜「YOLO 数据集 菠萝检测」的人多半不是想读论文而是手里有张推理卡或一台训练机想把菠萝成熟度识别、果品分拣、果园巡检这类任务跑起来。可现实里数据集资源大多只给一堆图片加一个压缩包划分、类别清单、标注可视化全要自己补补的过程中最容易翻车。标题里这份数据集把「划分好的数据集、类别 class 文件、数据可视化脚本」打包在一起正好覆盖了从拿到图到按下训练键的三件套。下面按这三件事拆开讲清楚YOLO 格式到底怎么组织、划分脚本怎么抄、可视化脚本查什么以及常见的坑在哪里。适合刚接触 YOLO 训练的入门者也适合想快速验收一份公开数据集的老手。2. 把菠萝检测数据集拆开看YOLO 目录结构与标注文件怎么组织更稳2.1 一个能直接喂给 YOLO 的数据集目录必须是这个骨架YOLO 系列从 v5 到 v8训练入口都是先读一个 data.yaml再按里面的路径去加载图片和标签。约定俗成的目录结构是 images 和 labels 两个大目录各自再按 train、val、test 细分。图片是 jpg/png标签是同名 txt。注意「同名」这两个字000001.jpg 对应 000001.txt一个字母都不能差。很多数据集只给图片不给标签或者标签是 VOC 的 xml到手必须先转格式标题里这份数据直接配好了省掉最麻烦的一步。在拿到任何数据集后我第一件事不是打开文件夹看图片而是先看目录骨架和文件命名是否规矩# 在数据集根目录执行确认 images/labels 双目录结构 find . -maxdepth 2 -type d | sort # 抽查命名是否一一对应应输出两个文件 ls images/train/000001.jpg labels/train/000001.txt如果环境里有 tree用tree -d -L 2更直观。这一步能过滤掉一大半「假数据集」图片和标签文件名对不上、train 和 val 里缺 labels、目录层级多套了一层都会在训练时以「Cant find dataset」或「No labels found」的形式爆出来。检查通过之后再看数据入口文件 data.yaml# data.yamlYOLO 训练入口路径要写对names 顺序不能换 path: ./pineapple_dataset # 数据集根目录 train: images/train # 相对 path 的路径 val: images/val test: images/test # 可留空验证用不到 nc: 3 # 类别数量 names: # 类别清单顺序就是模型输出顺序 0: ripe_pineapple 1: unripe_pineapple 2: pineapple_leaf这个文件里最容易被忽略的是 path 字段。我见过有人把 path 写成相对路径又把 train 写成绝对路径跑起来目录直接翻车。最稳的写法是 path 用数据集根目录train/val/test 都用相对路径后面带不带斜杠都行但保持一致。nc 必须与 names 的长度一致names 的索引必须从 0 开始连续编号中间不能跳。这些细节后面第 5 章的避坑部分还会再展开。2.2 txt 标注与 class 文件四个数字为什么够用YOLO 的 txt 标注每行只有五个字段类别 id 和四个归一化浮点数分别是目标中心点的 x、y 坐标和框的宽、高。归一化指的是除以图片的宽和高所以所有坐标都在 0 到 1 之间。这样做的好处是模型训练和图片分辨率解耦640 和 1280 的输入都能用同一套标注坏处是坐标一旦越界训练时框回归就会出现诡异行为所以拿到标签文件先做一次全量合法性检查比直接开训省心得多。下面这段脚本的功能是读取一个标签文件逐行解析并检查坐标是否越界# parse_label.py读取一个 YOLO 标签文件并检查坐标合法性 import sys def check_label(txt_path: str) - None: with open(txt_path, r, encodingutf-8) as f: lines [line.strip() for line in f if line.strip()] if not lines: print(f[警告] 空标注文件: {txt_path}) return for line_no, line in enumerate(lines, start1): parts line.split() if len(parts) ! 5: print(f[错误] 第 {line_no} 行字段数不是 5: {line}) continue cls_id, x_c, y_c, w, h map(float, parts) # 归一化坐标合法区间中心点 0~1宽高 0~1且大于 0 if not (0 x_c 1 and 0 y_c 1): print(f[错误] 中心点越界: {txt_path}:{line_no}) if not (0 w 1 and 0 h 1): print(f[错误] 宽高越界: {txt_path}:{line_no}) print(f类别 {int(cls_id)}: 中心({x_c:.3f}, {y_c:.3f}), 尺寸({w:.3f} x {h:.3f})) if __name__ __main__: check_label(sys.argv[1])用法是命令行传一个标签文件路径python parse_label.py labels/train/000001.txt。脚本里用 map(float, parts) 统一把字符串转成浮点数遇到非数字字段会直接抛异常这反而是好事说明文件被改坏过。字段数不等于 5 的要单独报错因为多一个空格或复制时串行解析出来就是脏数据。中心点和宽高的判定分开写是为了快速区分「坐标算错了」还是「文件损坏」。说到 class 文件这里要澄清一个搜索误区标题里的「class 文件」在 YOLO 生态里有两个意思一个是 data.yaml 里的 names 列表另一个是标注工具或某些脚本要求的 classes.txt。它们不是编程语言里的类关键字很多入门者搜「python 中 class 函数的用法」是搜错方向了。classes.txt 的写法是每行一个类别名顺序必须和标注 txt 里的数字一一对应# classes.txt每行一个类顺序不能乱 ripe_pineapple unripe_pineapple pineapple_leaf如果在训练脚本里用工具导出的数据集还会看到 data.yaml 由程序自动生成但手工整理的公开数据集这两份文件往往都要自己维护。我的习惯是 classes.txt 只作为标注阶段的参考训练一律以 data.yaml 为准因为 YOLO 训练时根本不读 classes.txt只有 data.yaml 是入口。两者顺序不一致最常见的后果是可视化时框和名字对不上模型本身没大问题但评估报告没法看。2.3 图片分辨率与标签的对应关系可视化脚本的前提图片尺寸在 YOLO 数据集里是一个隐性但关键的因素。txt 里的坐标是归一化的画框时必须有图片的宽和高才能恢复成像素坐标。数据集里常见的图片尺寸是 640x640、1280x720、1920x1080 混着来如果假设所有图都是 640 去画框框的位置会整体偏移看起来像标错了实际上是坐标系没对齐。这也是可视化脚本必须逐张读图片的原因。还有一个容易踩的细节是图片 EXIF 方向。手机或无人机拍的菠萝照片可能带旋转信息cv2.imread 读取时不会自动应用 EXIF 方向画框看起来就是转的。遇到这种情况先批量转正图片再入库否则框和目标在图上的相对位置是错的。这个检查和图片分辨率检查应该放在同一步因为两者都会让可视化脚本输出「假错」的结果。3. 自己也能划分出的 YOLO 数据集训练集、验证集、测试集的比例与脚本3.1 8:1:1 还是 9:0.5:0.5划分之前先看样本量划分比例没有标准答案取决于图片总数。菠萝检测如果只有两三百张按 8:1:1 分成 train 160 / val 20 / test 20验证集会少到评估结果方差很大一个 batch 的随机性就能让 mAP 上下浮动好几个点。图片数超过 1000 时我会把验证集调到 5% 左右测试集留在 5%训练集拿 90%。数据越少验证集越不能省因为你要靠它判断什么时候停训。图片总数训练集验证集测试集备注300 以下80%10%10%验证集保住 30 张以上300100085%10%5%测试集可以只评估一次1000 以上90%5%5%验证集 50 张起步即可除了总量还要看类别分布是否均衡。菠萝成熟度检测里「成熟」「未熟」两类往往比例悬殊如果直接全局随机划分验证集里可能出现某类只有一两张。处理这类不均衡我会按类别分层先把图片按标注里出现的主类别分桶再在每个桶内做随机划分保证验证集和训练集的类别比例大致一致。这个操作不复杂但能避免「验证集 mAP 高、落地就崩」的假象。还有一个被忽略的问题是数据来源的时序泄露。图片如果是视频按帧抽出来的相邻两帧几乎一样全局随机划分会把同一段视频的帧同时分进训练集和验证集。菠萝果园巡检视频一秒 30 帧抽帧通常隔几秒取一帧但连续两段视频的末尾和开头仍然高度相似。正确的做法是先按视频片段分组把整个片段分配到某一边再在片段内部划分。这个问题第 5 章避坑部分专门展开。3.2 一个可复用的划分脚本按文件移动图片与标签并生成 data.yaml直接抄下面这段脚本。它能完成三件事把 images 目录里的图片按比例拆成 train/val/test同步移动同名标签最后生成 data.yaml 和 classes.txt。运行一次就够了不用手动拖文件。# split_dataset.py按比例划分 YOLO 数据集并生成 class 文件 import random import shutil from pathlib import Path # 参数区按实际目录修改 dataset_root Path(pineapple_dataset) images_dir dataset_root / images_all # 未划分的图片集合 labels_dir dataset_root / labels_all # 未划分的标签集合 train_ratio, val_ratio, test_ratio 0.8, 0.1, 0.1 random.seed(42) # 固定种子保证可复现 # 目标目录结构 for split in [train, val, test]: (dataset_root / images / split).mkdir(parentsTrue, exist_okTrue) (dataset_root / labels / split).mkdir(parentsTrue, exist_okTrue) # 收集图片jpg/png 都算 img_paths sorted(images_dir.glob(*.jpg)) sorted(images_dir.glob(*.png)) random.shuffle(img_paths) # 计算切分下标 n len(img_paths) n_train int(n * train_ratio) n_val int(n * val_ratio) print(f总图片数 {n}: train {n_train}, val {n_val}, test {n - n_train - n_val}) for i, img_path in enumerate(img_paths): if i n_train: split train elif i n_train n_val: split val else: split test label_path labels_dir / (img_path.stem .txt) if not label_path.exists(): print(f[跳过] 找不到标签: {img_path.name}) continue # 把图片和同名标签移动到对应 split 目录 shutil.move(str(img_path), str(dataset_root / images / split / img_path.name)) shutil.move(str(label_path), str(dataset_root / labels / split / label_path.name))脚本里最关键的一行是random.seed(42)。没有它每次运行划分结果都不同第一次跑出 0.82 的验证集精度第二次可能就变 0.79你会以为模型不稳定其实是数据划分变了。种子固定成 42 之后任何人用这个脚本跑同一份数据划分结果完全一致这也是公开数据集「可复现」的前提。脚本里遇到缺失标签的图片直接跳过而不是报错终止因为一张漏标注的图不值得让整个划分流程停下来。划分完还要写 class 文件。下面这个脚本读取训练集里所有标签统计类别数量并按顺序生成 data.yaml 和 classes.txt# gen_yaml.py从标签统计类别生成 data.yaml 和 classes.txt from pathlib import Path label_root Path(pineapple_dataset/labels/train) class_names [ripe_pineapple, unripe_pineapple, pineapple_leaf] # 统计每个类别出现的图片数确认没有空类 counts {i: 0 for i in range(len(class_names))} for txt in label_root.glob(*.txt): with open(txt, r, encodingutf-8) as f: for line in f: if line.strip(): counts[int(line.split()[0])] 1 print(类别统计:, counts) # 生成 classes.txt with open(classes.txt, w, encodingutf-8) as f: f.write(\n.join(class_names) \n) # 生成 data.yaml yaml_text fpath: pineapple_dataset train: images/train val: images/val test: images/test nc: {len(class_names)} names: for i, name in enumerate(class_names): yaml_text f {i}: {name}\n with open(data.yaml, w, encodingutf-8) as f: f.write(yaml_text)运行完这两段目录结构就变成了标准形态images/train、images/val、images/test 和 labels 下的对应目录外加一个 data.yaml。此时可以先跑一次第 4 章的可视化脚本抽查几组图再决定要不要进入训练。如果中途发现划分比例不对还没开始训练前有后悔药把 images 和 labels 下面三个子目录里的文件重新归拢回 images_all/labels_all改掉比例重新跑一次即可。3.3 没有现成划分时先看文件的命名规则再决定脚本怎么写补充一个经验公开数据集的图片命名千奇百怪有的带日期前缀有的按视频帧编号有的名字里还有空格。写划分脚本前先ls | head看几条真实文件名确认扩展名大小写.JPG 和 .jpg 是两种文件、有没有隐藏后缀.jpg.png 这种双重扩展名、有没有中文或空格。文件名里有空格时shutil.move 没问题但 YOLO 训练加载时可能解析异常稳妥做法是先批量重命名成纯数字编号。这个步骤不写进脚本里是因为每个数据集的脏数据都不一样只能按实际情况处理。4. 数据可视化脚本标注框看过一遍训练才敢按下启动键4.1 OpenCV 把标注框画回原图验证 txt 与图片对得上可视化脚本是数据集验收的最后一关也是最容易跳过的一关。很多翻车现场都是这样发生的data.yaml 写对了、目录也对了训练也启动了跑到一半发现 loss 不降把训练日志翻出来看才发现某张图的标注框画在了图片外面或者框的宽高是 0。与其等训练跑几个小时再排查不如先花五分钟把所有标注框画回原图人眼扫一遍。下面这段脚本把指定目录里的图片和对应的 YOLO 标注画框并保存到 vis 目录# vis_boxes.py把 YOLO 标注框画回原图 import cv2 from pathlib import Path def visualize_split(split_dir: Path, class_names: list, output_dir: Path): img_dir split_dir / images label_dir split_dir / labels output_dir.mkdir(exist_okTrue) for img_path in sorted(img_dir.iterdir()): label_path label_dir / (img_path.stem .txt) if not label_path.exists(): continue img cv2.imread(str(img_path)) if img is None: print(f[警告] 图片读取出错: {img_path.name}) continue h, w img.shape[:2] with open(label_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, x_c, y_c, bw, bh map(float, parts) # 归一化坐标转像素坐标注意全部取整 x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) # 画框和类别名颜色用 BGR 绿色 color (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) label class_names[int(cls_id)] cv2.putText(img, label, (x1, max(y1 - 5, 15)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) out_path output_dir / img_path.name cv2.imwrite(str(out_path), img) print(f[完成] {img_path.name}) # 用法示例默认可视化 val 集 visualize_split(Path(pineapple_dataset/val), [ripe_pineapple, unripe_pineapple, pineapple_leaf], Path(vis_val))脚本里最容易被忽略的细节是坐标换算时的减半操作txt 存的是中心点坐标和宽高画到图片上要先把中心点换算成左上角和右下角。x1 int((x_c - bw / 2) * w)这一步错一个括号框就会整体偏移半个身位。cv2.rectangle 的坐标必须是整数浮点数直接传进去在部分版本里会报类型错误所以统一用 int 包一层。类别名的位置做了个max(y1 - 5, 15)保护防止框贴在图片顶部时文本写到画面外面去。画完图之后人眼扫一遍 vis 目录里的图。重点看三件事框是否紧贴目标松垮的框说明标注质量差、类别标签和框内物体是否一致说明 class 文件顺序可能配错了、有没有框明显超出图片边界说明归一化坐标是拿另一张图的尺寸算的。这三类问题在数据量大的时候很难靠统计脚本发现但人眼扫图几乎一下就能看出来。批量抽样的数量不用太多1000 张的数据集抽 50 张看就够。重点是覆盖不同光照、不同距离的场景而不是随机点开前几张。我习惯固定随机种子抽图这样每次验收看到的都是同一组方便对比前后改动。4.2 类别分布与框尺寸统计可视化不止画框还能发现样本不均衡画框只是把「单张图的问题」暴露出来样本级别的偏斜要靠统计脚本来查。菠萝检测的场景里成熟菠萝的框通常小而密集叶片和远景的框大而稀少两类目标在训练时对 yolo 损失函数的贡献完全不同。统计脚本输出每个类别的目标数量、图片数量、框面积分布能直接指导后续要不要做重采样或改增强策略。# stat_labels.py统计类别数量与标注框尺寸分布 from pathlib import Path from collections import Counter label_dir Path(pineapple_dataset/labels/train) cls_counter Counter() # 每个类别出现的目标总数 img_counter Counter() # 有标注的图片数 area_list [] # 所有目标的归一化框面积 for txt_path in label_dir.glob(*.txt): with open(txt_path, r, encodingutf-8) as f: lines [line for line in f if line.strip()] if lines: img_counter[with_label] 1 for line in lines: parts line.split() if len(parts) ! 5: continue cls_id int(parts[0]) w, h float(parts[3]), float(parts[4]) cls_counter[cls_id] 1 area_list.append(w * h) # 归一化面积用于框尺寸分布判断 print(各类别目标总数:, dict(cls_counter)) print(有标注的图片数:, img_counter[with_label]) # 框面积排序后看中位数和极端值 area_list.sort() if area_list: print(f框面积 最小{area_list[0]:.4f}, f中位{area_list[len(area_list)//2]:.4f}, f最大{area_list[-1]:.4f})这段统计的价值在于给训练参数提供依据。如果中位框面积只有 0.01 左右说明菠萝目标在图中占比很小训练时默认的 anchor 尺寸大概率不匹配要么把 imgsz 调大要么考虑 anchor 聚类重算如果「成熟」和「未熟」两个类别的目标数量差了十倍只靠随机采样训练模型会对少数类严重欠拟合这时可以在训练配置里给少数类加样本权重或者在预处理里对少数类做过采样。很多人一上来就研究 nwd 改进 yolo、调 yolo 损失函数其实先看看自己数据的框尺寸分布和类别比例往往更能解释为什么模型不收敛。可视化脚本的价值不只是「看一眼」而是把数据里的偏斜量化出来让后续每个训练决策都有依据这是把数据集价值吃透的第一步。5. 避坑与排查菠萝检测数据集里最常翻车的四个细节5.1 边界框坐标越界和空标注文件为什么训练一半 Loss 变成 nan现象训练进行到某个 epoch 后 loss 突然变成 nan或者一开始就是 nan。重启训练、换学习率都没用。原因标注 txt 里坐标越界或宽高为 0。YOLO 的框回归损失里含有坐标的变换计算当 x_center 和 y_center 出现在 0~1 之外或者宽高算出来是负值梯度就会变成无穷大带动整个网络参数一起爆掉。空标注文件不会直接导致 nan但会造成训练时该图没有正样本损失曲线出现异常抖动。解决训练前用第 2 章的 parse_label.py 批量跑一遍全部标签目录把越界、字段数不对、空文件全列出来。越界的坐标做一个裁剪中心点 clamp 到 0~1宽高 clamp 到 0~1 但保留最小阈值。空文件直接删除同时删掉对应的图片避免训练时图片有、标签缺失导致的警告刷屏。这个检查过程应该写进数据验收流程而不是等训练出问题再回头查。5.2 类别编号对不上class 文件的顺序就是模型顺序现象训练完成后验证把预测结果可视化出来发现模型把成熟菠萝标成了未熟菠萝或者评估报告里某个类别的 AP 始终是 0。原因data.yaml 里的 names 顺序和标注 txt 里 class_id 的编码不一致。比如标注时 classes.txt 的顺序是 ripe、unripe、leaf训练时 data.yaml 写成了 leaf、ripe、unripe模型学到的类别编号全部错位。训练本身不会报错因为类别数量没变损失还能正常下降但模型的输出语义已经错乱了。解决写一个对照脚本把 data.yaml 里的 names 和训练集标签里出现的 class_id 最大值、最小值和计数全部打印出来。重点确认两件事class_id 是不是从 0 开始连续编号names 列表里第 N 个名字是不是真的对应 N 号目标。改 data.yaml 的顺序比改几百个 txt 文件简单得多所以发现错位时优先修正 yaml除非你有把握做一次标签批量替换。类别少的时候人眼还能看类别超过 10 个以后这个检查必须机器来做。5.3 训练集和验证集出现重复图片视频抽帧的时序泄露现象训练 loss 和验证 mAP 都很漂亮模型一到真实果园现场就完全失真误检漏检一大堆。原因图片是从视频里按帧抽出来的同一段连续画面的相邻帧几乎一样。全局随机划分时同一段视频的帧被同时分进训练集和验证集模型在训练阶段就已经「见过」验证集的内容评估结果虚高。菠萝园巡检视频里相机固定不动拍一整片树相隔几秒的两帧画面差异极小这种泄露比想象中严重得多。解决划分前先确认数据来源。如果是视频抽帧按视频片段分组把属于同一段视频的所有帧放在一个桶里划分时以桶为单位而不是以帧为单位。具体做法是给每张图片的文件名加上视频片段 ID 前缀然后按前缀分组再抽若干个完整组进验证集。这样验证集和训练集之间没有相邻帧评估结果才真实。判断标准很简单在验证集里随机挑几张图和训练集里最相似的那张比一下如果肉眼几乎分不出差别就是泄露了。5.4 在 Windows 上改过配置文件后训练报错换行符与编码问题现象YOLO 训练读 data.yaml 时直接报解析错误或者路径里多出一个奇怪的\r字符模型加载权重时报错。原因data.yaml 在 Windows 记事本或某些编辑器默认设置下被改成 CRLF 换行而 YOLO 的 YAML 解析器在部分版本里对 CRLF 处理比较敏感更常见的是编码问题Windows 下新建的文件默认可能是 GBK而 YOLO 按 UTF-8 读取中文注释或包含中文的路径直接乱码。解决统一用 UTF-8 无 BOM 编码写 data.yaml换行符用 LF。最省事的办法是不用手工编辑直接跑一遍第 3 章的 gen_yaml.py 重新生成文件。如果文件已经存在用下面这条命令做转码和换行符统一# 把 data.yaml 转为 UTF-8无 BOM并统一 LF 换行 sed -i s/\r$// data.yaml # 去掉 CR 回车符 file data.yaml # 确认编码是 UTF-8路径里的反斜杠也要小心。Windows 里写目录习惯用\YAML 里反斜杠是转义字符labels\train会被解析成labels加一个制表符再加train。统一把 data.yaml 里的路径写成正斜杠/Python 和 YOLO 都能正常识别这是跨平台最稳的写法。6. 让这份数据集发挥出全部价值先从 mAP 验证与增强参数开始数据集验收通过之后第一轮训练建议用官方预训练权重起步不要从零训练。以 yolov8 为例最小训练命令是这样yolo detect train datadata.yaml modelyolov8n.pt epochs50 imgsz640 batch16data.yaml 已经在第 3 章生成model 用 yolov8n.pt 预训练权重epochs 先定 50batch 按显存调整8G 显存跑 16 会爆就降到 8。训练结束后用yolo detect val看 mAP50 和 mAP50-95前者判断框有没有检测到后者判断框贴不贴目标。菠萝这类目标不算小mAP50 到 0.85 以上算及格如果只有 0.6 左右先回头检查类别统计里是不是有极端不均衡再考虑增强参数。小数据集的增强别一上来拉满。mosaic 确实能提升小目标检测效果但菠萝数据集只有几百张时mosaic 会强行拼出大量不自然的组合模型的收敛反而变慢。我的习惯是 epoch 数翻倍不如把 hsv_h、hsv_s 各开 0.015加一点平移和缩放让模型对光照变化更鲁棒。这些参数在 data.yaml 里不配要写进训练配置文件的 augmentation 部分。最后说一个我的教训有次拿到一份葡萄检测数据集目录、yaml 都对得上我跳过可视化直接开训两天后才发现某个类别 ID 的框全部画在图片角落数据分布统计根本没人做过。自此之后任何数据集到手先跑可视化脚本画 50 张图再跑统计脚本看类别比例和框尺寸两步加起来不到十分钟却省掉了后面无数次无效训练。这份菠萝检测数据集本身已经把三件套配齐了但每个使用它的人都值得把这十分钟验收流程保留下来。希望帮到你。本文还有配套的精品资源点击获取