简介:本资源是一套基于YOLO框架拓展实现图像语义分割与实例分割的完整实践方案,面向计算机、电子信息工程及数学等专业的本科生,适用于课程设计、期末大作业或毕业设计参考。资源聚焦目标检测算法向像素级分割任务的延伸应用,提供可运行源码、标注清晰的图片数据集及详细说明文档,帮助学习者理解YOLO模型结构改造、后处理逻辑适配及分割结果可视化等关键技术环节。压缩包共2000个文件,含563张PNG格式样本图像、958个C/C++头文件(.h/.hpp/.inl)支撑底层网络构建、150余个CUDA相关文件(.cuh/.cu)实现GPU加速,以及少量Python脚本和配置文件,整体大小为63.55MB。已有1112人学习下载,内容覆盖darknet框架下的detector、layer、utils等核心模块,具备清晰的工程目录结构与典型分割流程实现,便于读者调试修改、功能扩展与原理验证。
1. 项目概述:从目标检测到像素级理解的跨越
拿到这个名为“基于YOLO目标检测算法实现图像语义分割实例分割”的资源包时,我第一反应是:这标题本身就蕴含了一个非常有意思的技术演进路径。YOLO(You Only Look Once)在计算机视觉领域几乎是目标检测的代名词,以其“单次前向传播”的极速特性闻名。但它的核心输出是边界框(Bounding Box)和类别标签,告诉你“图里有什么,大概在哪儿”。而语义分割和实例分割,则是更精细的像素级任务,要求模型不仅知道有什么,还要精确地勾勒出每一个物体的轮廓,甚至区分开同一类别的不同个体。用这个资源包,本质上是在探索如何让一个擅长“圈地”的模型,学会“描边”和“数数”。
这个项目的价值,远不止是拿到一套能跑的代码和数据集。它更像是一个绝佳的实践案例,让你亲身体验计算机视觉中两个核心任务(检测与分割)是如何联系与转化的。对于已经熟悉YOLO目标检测的开发者来说,这是向更高级视觉任务迈进的关键一步;对于刚入门的新手,它提供了一个从经典算法入手,理解分割任务完整流程的清晰路径。资源包里的“源码+图片数据集+说明文档”三件套,构成了一个可以立即上手、边做边学的完整实验环境。接下来,我会结合自己多次复现和改造类似项目的经验,为你深度拆解这里面的每一个环节,从核心思路到代码细节,再到训练中那些容易踩的坑。
2. 核心思路拆解:YOLO如何“兼职”做分割?
2.1 目标检测与分割的任务本质差异
首先要理清概念,否则很容易在后续实践中混淆。目标检测、语义分割、实例分割,虽然都关乎“识别物体”,但输出粒度完全不同。
- 目标检测 (Object Detection):输出的是一个个矩形框(Bounding Box)和类别标签。它的回答是:“有一只猫”,并用一个框大致框出猫的位置。YOLO系列的传统强项就在于此。它的损失函数、网络输出(如tx, ty, tw, th, confidence, class probabilities)都是为生成边界框服务的。
- 语义分割 (Semantic Segmentation):为图像中的每一个像素分配一个类别标签。它的回答是:“这个像素属于猫,那个像素属于背景”。它不区分个体,如果图中有两只猫,所有猫的像素都会被归为“猫”这一类。
- 实例分割 (Instance Segmentation):这是前两者的结合体,也是最复杂的。它不仅要进行像素级分类,还要区分开不同的个体实例。它的回答是:“这是猫A的像素集合,那是猫B的像素集合”。通常,实例分割的输出可以理解为“检测框 + 框内的精确掩码(Mask)”。
所以,让YOLO做分割,并不是让它突然学会一个全新的魔法,而是在它强大的特征提取和目标定位能力基础上,增加一个分支,来预测每个目标实例的精细掩码。这就是“YOLO + Segmentation Head”的基本思想。
2.2 YOLOv5/v7/v8 实例分割的实现路径
目前主流的方法,尤其是在这个资源包可能基于的YOLOv5/v7/v8框架中,实例分割的实现通常遵循以下两种路径之一:
- Mask R-CNN 思想的本土化:受经典实例分割网络Mask R-CNN启发,在YOLO检测头(预测框和类别)旁边,并行增加一个掩码头(Mask Head)。这个掩码头是一个小型全卷积网络(FCN),它以检测头提出的候选区域(在YOLO中,可以理解为网络深层特征图上对应目标位置的网格或锚点)对应的特征图为输入,输出一个固定分辨率(如28x28)的二进制掩码。训练时,需要像素级的掩码标签。
- SOLO 或 YOLACT 风格的思路:另一种思路是“原型掩码”法,以YOLACT为代表。网络会输出一组“原型掩码”(Prototype Masks)和每个检测框对应的“掩码系数”。最终的实例掩码由原型掩码线性组合而成。这种方法可以实现更快的推理速度。
根据项目标题和常见开源实践推断,这个资源包极有可能采用的是第一种路径,即在YOLO架构上集成一个掩码头。因为这种方法相对直观,与YOLO的检测流程结合紧密,也是官方仓库(如Ultralytics YOLOv5/v8)支持实例分割版本时所采用的方式。
注意:这里存在一个常见的理解误区。很多人以为“语义分割实例分割”是同时做两件事。在这个项目上下文中,更可能是指实现了实例分割功能。因为实例分割的结果已经包含了语义信息(每个像素的类别)和实例信息(个体的区分)。单独的语义分割模型(如UNet, DeepLab)通常不区分个体。
3. 环境准备与数据解析
3.1 开发环境搭建要点
拿到源码后,第一步就是配环境。根据“相关热搜词”里频繁出现的pytorch目标检测,可以判断该项目极大概率基于PyTorch框架。以下是搭建环境的可靠步骤和避坑指南:
- Python版本:推荐使用Python 3.8或3.9。这是PyTorch生态兼容性最好的版本,避免使用过新(如3.11+)可能遇到的包依赖问题。
- PyTorch与CUDA:这是核心。先去 PyTorch官网 根据你的CUDA版本(通过
nvidia-smi命令查看)选择安装命令。如果没有NVIDIA GPU,就安装CPU版本。实操心得:即使有GPU,也建议先使用CPU版本快速验证代码是否能跑通,排除CUDA版本不匹配这个最头疼的问题。 - 依赖包安装:通常项目会提供
requirements.txt文件。使用pip install -r requirements.txt安装。常见问题:如果遇到某个包版本冲突,可以尝试先注释掉该行,手动安装一个兼容版本。重点关注opencv-python,torchvision,matplotlib,seaborn,pandas等。 - 专属库:如果源码中引用了自研模块,可能需要以可编辑模式安装:
pip install -e .(在项目根目录执行)。
# 一个典型的环境检查与安装流程 conda create -n yolo_seg python=3.9 conda activate yolo_seg # 假设CUDA版本为11.3 pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113 pip install -r requirements.txt3.2 数据集结构与标签格式深度解析
“图片数据集”是这个项目的基石。分割任务的数据集比检测任务复杂得多,因为标签不再是简单的框坐标,而是像素级的掩码图。
常见结构:
dataset/ ├── images/ │ ├── train/ │ │ ├── image1.jpg │ │ └── ... │ └── val/ │ └── ... └── labels/ ├── train/ │ ├── image1.txt (或 image1.json, image1.png) │ └── ... └── val/ └── ...标签格式:这是关键,直接决定你的数据加载器(
dataset.py)怎么写。- YOLO格式的扩展:对于实例分割,YOLO格式的
.txt文件需要升级。每一行可能代表一个实例,其格式可能为:<class_id> <x_center> <y_center> <width> <height> <polygon_points>。其中polygon_points是一串归一化的多边形点坐标(x1, y1, x2, y2, ...),用于描述物体轮廓。这是Ultralytics YOLO实例分割数据集采用的格式。 - COCO格式:另一种可能是使用JSON文件,遵循COCO数据集格式。它包含
images,annotations,categories等字段,其中annotations里的segmentation字段存储的就是多边形点集或RLE编码的掩码。很多开源项目都支持COCO格式。 - 掩码图格式:最直观但存储效率低的方式,即每张图片对应一张同尺寸的PNG标签图,不同像素值代表不同实例ID。这种方式需要额外的映射文件来说明ID与类别的对应关系。
你必须仔细阅读“说明文档”和源码中的
data.yaml或类似配置文件,来确定本项目使用的具体格式。data.yaml文件通常会指明path,train,val的路径以及类别名称names。- YOLO格式的扩展:对于实例分割,YOLO格式的
数据检查脚本:在开始训练前,写一个简单的脚本可视化几张图片和对应的标签掩码,这是避免后续训练报错的最有效方法。检查标签是否与图像对齐,多边形点是否在图像范围内。
import cv2 import matplotlib.pyplot as plt import numpy as np # 假设标签是多边形格式 def plot_image_and_mask(img_path, label_path): img = cv2.imread(img_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) with open(label_path, 'r') as f: lines = f.readlines() mask = np.zeros(img.shape[:2], dtype=np.uint8) for line in lines: parts = list(map(float, line.strip().split())) class_id = int(parts[0]) polygon = np.array(parts[5:]).reshape(-1, 2) # 假设从第5位开始是多边形点 polygon = (polygon * [img.shape[1], img.shape[0]]).astype(np.int32) # 反归一化 cv2.fillPoly(mask, [polygon], color=class_id) # 用类别ID填充多边形区域 fig, ax = plt.subplots(1, 2, figsize=(12,6)) ax[0].imshow(img) ax[0].set_title('Image') ax[0].axis('off') ax[1].imshow(mask, cmap='jet') ax[1].set_title('Mask') ax[1].axis('off') plt.show() # 调用示例 plot_image_and_mask('dataset/images/train/image1.jpg', 'dataset/labels/train/image1.txt')4. 源码结构剖析与核心模块解读
一个完整的YOLO分割项目源码,其结构通常比单纯的目标检测项目更复杂。我们可以预期它包含以下核心模块:
4.1 模型定义 (models/目录)
这是项目的核心。你需要找到定义网络结构的文件,通常是models/yolo.py或models/segment.py。
- 主干网络 (Backbone):通常是CSPDarknet(YOLOv5/v7)或类似的CNN架构,负责从输入图像中提取多层次的特征图。
- 颈部网络 (Neck):如FPN (Feature Pyramid Network) 或 PANet,用于融合来自主干网络不同尺度的特征,增强模型对不同大小目标的检测和分割能力。
- 检测头 (Detection Head):输出边界框(bbox)、置信度(confidence)和类别概率(class probabilities)。这部分和标准YOLO一致。
- 分割头/掩码头 (Segmentation Head / Mask Head):这是新增的关键部分。它通常接在颈部网络输出的特征图之后。结构可能是一个轻量级的全卷积网络,包含若干层卷积、上采样和激活函数,最终输出一个通道数为
num_classes或num_masks的特征图。在推理时,这个分割头的输出会与检测头的输出结合,为每个检测到的目标生成掩码。
关键代码片段解读(以类YOLOv5分割头为例):
class Segment(nn.Module): def __init__(self, nc=80, nm=32, npr=256, ch=()): super().__init__() self.nc = nc # 类别数 self.nm = nm # 掩码原型数 (prototype masks) self.npr = npr # 掩码维度 # 一个小的解码器,用于生成掩码原型 self.proto = Proto(ch[0], self.npr, self.nm) # 输入通道,输出原型 # 检测头(与标准YOLO相同) self.detect = Detect.forward(...) def forward(self, x): # p 是检测头的输出 (bbox, conf, cls) p = self.detect(self.detect_forward(x)) # proto 是原型掩码特征图 proto = self.proto(x[0]) # 通常取最高分辨率的特征图 return p, proto这里proto输出的就是一组“原型掩码”,而检测头输出的每个边界框会对应一组“掩码系数”,通过矩阵乘法结合,得到每个实例的最终掩码。
4.2 数据加载与增强 (data/目录)
分割任务的数据增强需要特别小心,因为图像和掩码标签必须进行完全同步的变换。
dataset.py:继承自PyTorch的Dataset类。它的__getitem__方法需要返回:图像(Tensor)、归一化的边界框标签、实例的多边形标签(或掩码图)、图像路径、原始图像尺寸等。数据加载的复杂度主要在这里。augmentations.py:包含几何变换(如随机缩放、裁剪、翻转、旋转)和色彩变换(如亮度、对比度、饱和度调整)。核心原则:对图像进行任何几何变换,都必须以完全相同的方式应用于其对应的掩码标签。例如,随机水平翻转图像时,掩码多边形所有点的x坐标都要进行width - x的变换。- 马赛克增强 (Mosaic Augmentation):YOLO系列常用的强力增强技术,将四张图像拼成一张。对于分割任务,拼接时不仅要拼接图像,还要正确拼接和偏移四张图对应的所有多边形标签,确保每个实例的掩码仍然准确对应其所在的图像区域。这是数据加载部分最大的挑战之一。
4.3 损失函数设计 (loss.py)
分割任务的损失函数是检测损失和分割损失的总和。
- 检测损失:与标准YOLO相同,通常包含:
- 边界框损失 (Box Loss):如CIoU Loss,衡量预测框与真实框的重合度。
- 置信度损失 (Objectness Loss):二元交叉熵,判断网格内是否有物体。
- 分类损失 (Classification Loss):交叉熵或Focal Loss,判断物体类别。
- 分割损失 (Mask Loss):这是新增部分。通常使用二元交叉熵损失 (BCE Loss)或Dice Loss。计算的是预测的实例掩码与真实的二值掩码之间的差异。注意:损失计算时,通常只在与目标边界框对应的区域(或一个稍大的区域)内计算分割损失,以忽略无关背景的干扰。
总损失函数大致形式为:L_total = L_box + L_obj + L_cls + λ * L_mask,其中λ是一个平衡两项任务的权重系数。
4.4 训练与验证脚本 (train.py,val.py)
train.py:组织训练循环。在每个批次(batch)中,前向传播得到检测结果和分割原型/掩码,计算总损失,反向传播更新权重。需要重点关注学习率调度器(如Cosine Annealing)、优化器(如SGD with Momentum或AdamW)、梯度累积等超参数的设置。val.py:在验证集上评估模型性能。评估指标除了目标检测常用的mAP@0.5(平均精度)之外,必须包含分割任务的指标,主要是:- 掩码mAP (Mask mAP):类似于检测的mAP,但计算的是预测掩码与真实掩码的交并比(IoU)。
- 平均交并比 (Mask IoU):所有正样本预测掩码与真实掩码IoU的平均值。
5. 模型训练全流程实操与调优
5.1 训练启动与参数配置
假设项目结构清晰,你可以通过一个命令行启动训练。核心参数通常在train.py的parse_opt()函数中定义。
python train.py --img 640 --batch 16 --epochs 100 --data dataset/data.yaml --cfg models/yolov5s-seg.yaml --weights yolov5s.pt --name my_seg_exp--img 640: 输入图像尺寸。分割任务通常需要较高分辨率以保留细节,但会显著增加显存消耗和训练时间。可以从640开始尝试。--batch 16: 批次大小。取决于你的GPU显存。如果出现CUDA out of memory错误,首先降低batch,其次降低--img。--epochs 100: 训练轮数。对于中等规模数据集,100-300轮是常见的范围。--data: 指向你的data.yaml配置文件。--cfg: 模型结构配置文件。对于分割任务,必须选择带有-seg后缀的配置文件(如yolov5s-seg.yaml),它定义了分割头的结构。--weights: 预训练权重。强烈建议使用在COCO等大型数据集上预训练好的目标检测权重(如yolov5s.pt)进行初始化。这可以极大地加速收敛,提升最终性能。模型会利用预训练好的主干网络特征提取能力,只让新增的分割头从零开始学习。--name: 实验名称,用于保存结果到runs/train/目录下。
5.2 训练过程监控与指标解读
训练开始后,控制台会打印日志,并且TensorBoard或类似工具会记录指标曲线。你需要关注:
- 损失曲线:观察
train/loss和val/loss。理想情况是训练损失平稳下降,验证损失也同步下降并最终趋于平缓。如果验证损失很早就开始上升,可能是过拟合。 - 检测指标:
metrics/mAP_0.5和metrics/mAP_0.5:0.95。前者是IoU阈值为0.5时的mAP,后者是多个IoU阈值下的平均mAP。它们是模型检测能力的主要指标。 - 分割指标:
metrics/mask_mAP_0.5和metrics/mask_mAP_0.5:0.95。这是评估分割效果的核心。如果这个指标远低于检测mAP,说明分割头学习得不好,可能需要检查分割损失权重、数据标签质量或分割头结构。 - 学习率曲线:确保学习率按预定策略(如余弦退火)变化。
5.3 超参数调优实战心得
- 学习率 (lr0):这是最重要的超参数。对于使用预训练权重的微调,学习率通常设置得较小(如
0.01或0.001)。可以使用学习率查找器(如果代码支持)或进行小范围网格搜索。 - 权重衰减 (weight_decay):防止过拟合,常用值如
5e-4。 - 分割损失权重 (box, cls, obj, mask的权重):在
loss.py中定义。默认配置通常是一个不错的起点。如果你发现模型检测很好但分割很差,可以尝试适当提高mask损失的权重(如从1.0提高到3.0或5.0),反之亦然。 - 数据增强强度:分割任务对几何增强更敏感。过强的裁剪可能导致小目标实例被切掉,过强的旋转可能导致多边形标签变形。建议开始时使用中等强度的增强,根据验证集性能调整。
实操心得:训练初期,不要追求过高的
mask_mAP。分割头的学习需要时间。前几十个epoch,mask_mAP可能接近0,这是正常的。重点先看检测指标是否在稳步提升。只要检测框准了,分割头才有正确的“工作区域”去学习生成掩码。
6. 模型推理与结果可视化
训练完成后,在runs/train/my_seg_exp/weights/目录下会得到最好的模型权重(best.pt)和最后一个epoch的权重(last.pt)。使用detect.py或predict.py进行推理。
python detect.py --source test_images/ --weights runs/train/my_seg_exp/weights/best.pt --img 640 --conf 0.25 --save-txt --save-conf--source: 可以是单张图片、文件夹、视频流或摄像头索引。--conf: 置信度阈值,低于此值的检测结果将被过滤。--save-txt: 保存检测框的文本标签(YOLO格式)。--save-conf: 在标签中保存置信度。
对于分割任务,推理脚本会自动调用分割头,为每个检测到的目标生成掩码。可视化结果通常会以不同颜色叠加在原始图像上,并显示类别和置信度。
自定义可视化脚本:如果你想更精细地控制可视化效果,可以编写自己的脚本:
import cv2 import torch from models.experimental import attempt_load from utils.general import non_max_suppression, scale_coords from utils.segment.general import process_mask, scale_masks # 加载模型 device = torch.device('cuda:0') model = attempt_load('runs/train/my_seg_exp/weights/best.pt', device=device) model.eval() # 预处理图像 img = cv2.imread('test.jpg') img0 = img.copy() # 保留原始图像用于画图 img = preprocess(img) # 预处理函数:resize, normalize, to tensor... # 推理 with torch.no_grad(): pred, proto = model(img[None, ...])[0] # 获取检测结果和原型掩码 # 后处理:非极大值抑制 pred = non_max_suppression(pred, conf_thres=0.25, iou_thres=0.45) for det in pred: if len(det): det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round() # 缩放框坐标 masks = process_mask(proto, det[:, 6:], det[:, :4], img.shape[2:]) # 生成实例掩码 masks = scale_masks(masks, img0.shape) # 缩放掩码到原图尺寸 # 现在 det 是边界框信息,masks 是对应的二值掩码 # 可以遍历每个检测结果,将掩码画到 img0 上 for i, (*xyxy, conf, cls) in enumerate(det): mask = masks[i] color = colors[int(cls)] # 用半透明颜色填充掩码区域 img0[mask] = img0[mask] * 0.5 + np.array(color) * 0.5 # 画边界框和标签 cv2.rectangle(img0, (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])), color, 2) label = f'{model.names[int(cls)]} {conf:.2f}' cv2.putText(img0, label, (int(xyxy[0]), int(xyxy[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) cv2.imwrite('result.jpg', img0)7. 常见问题排查与性能优化指南
7.1 训练阶段问题
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| CUDA out of memory | 1. 批次大小(batch)过大。2. 输入图像尺寸( img)过大。3. 模型过大(如用了 yolov5x-seg)。 | 1. 首先降低batch(如16->8)。2. 其次降低 img(如640->512)。3. 使用更小的模型变体(如 s->n)。4. 使用梯度累积( --accumulate),模拟大批次。 |
| 损失不下降或为NaN | 1. 学习率过高。 2. 数据标签有误(如坐标超出范围)。 3. 损失函数计算出现数值不稳定。 | 1. 大幅降低学习率(如lr0=0.01->0.001)。2. 运行数据检查脚本,确保所有标签坐标在[0,1]范围内。 3. 检查损失函数中是否有除零或log(0)操作,加入微小epsilon。 |
| Mask mAP始终为0 | 1. 分割损失权重太低或梯度未回传。 2. 分割头结构有问题或初始化不当。 3. 掩码标签格式与代码读取方式不匹配。 | 1. 检查loss.py中loss_mask是否被正确计算并加到总损失中。2. 尝试使用预训练模型的分割头权重(如果有)。 3.重点检查:可视化几张训练样本的掩码,确认数据加载器读入的掩码标签是有效的。 |
| 过拟合(训练集指标好,验证集差) | 1. 训练数据量太少。 2. 模型复杂度太高。 3. 数据增强不够。 | 1. 增加数据增强的多样性(如Mosaic, MixUp)。 2. 加入更强的正则化,如增加 weight_decay,使用DropOut(如果模型支持)。3. 使用更小的模型。 4. 早停(Early Stopping)。 |
7.2 推理阶段问题
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 推理速度慢 | 1. 输入分辨率过高。 2. 未使用GPU或半精度推理。 3. 后处理(NMS)耗时。 | 1. 降低--img参数(需与训练时一致或按比例缩放)。2. 确保 torch.cuda.is_available()为True,并使用--half进行半精度推理(FP16)。3. 尝试调整NMS的 iou_thres,过小的阈值会增加计算量。 |
| 漏检或误检多 | 1. 置信度阈值(conf)设置不当。2. 训练数据未覆盖该场景。 3. 模型在复杂场景下泛化能力不足。 | 1. 调整--conf参数,降低会减少漏检但增加误检,提高则相反。2. 收集更多困难样本加入训练集。 3. 尝试使用集成测试或测试时增强(TTA),但会降低速度。 |
| 掩码边缘粗糙或不准确 | 1. 分割头输出分辨率低(如28x28)。 2. 训练时使用的 img尺寸较小,丢失细节。3. 目标本身边界模糊。 | 1. 这是模型结构限制。一些改进方案使用更高分辨率的掩码头或更精细的原型。 2. 尝试以更大尺寸(如1280)训练和推理,但代价是速度慢、显存高。 3. 后处理时可以对预测的掩码进行高斯平滑或形态学操作,但治标不治本。 |
7.3 性能优化进阶技巧
- 模型剪枝与量化:如果部署到边缘设备,可以考虑对训练好的模型进行剪枝(移除不重要的通道)和量化(将FP32权重转换为INT8),大幅减少模型体积和提升推理速度。可以使用PyTorch的TorchScript、ONNX转换以及TensorRT等工具链。
- 自定义数据增强:针对你的特定场景设计增强。例如,对于工业缺陷检测,可以增加模拟噪声、模糊的增强;对于医学图像,可以增加弹性形变。
- 多尺度训练与测试:在训练时随机选择多种输入尺寸,增强模型尺度不变性。在测试时,对同一图像进行多种尺寸的缩放并推理,然后融合结果,可以提升精度(但降低速度)。
- 利用预训练权重:永远从预训练权重开始。不仅是主干网络,如果能在类似任务(如COCO实例分割)上找到预训练的完整模型(包括分割头),进行微调,效果会比随机初始化好得多。
这个基于YOLO的实例分割项目,为你打通了从目标检测到像素级理解的实践通道。理解其“检测框+掩码头”的协同工作机理,是掌握现代实例分割模型的关键。在实际操作中,耐心和细致的调试比盲目尝试大量算法更重要。从确保数据标签百分百正确开始,逐步调整超参数,观察每一个指标的变化,你就能让这个模型在你的专属任务上发挥出强大的威力。
本文还有配套的精品资源,点击获取