简介:面向电力巡检与计算机视觉学习者的YOLO输电线路数据集,聚焦绝缘子、铁塔、导线等关键部件检测,可用于训练实时目标检测模型,辅助线路异常监测与故障预警。压缩包共2000个XML标注文件,整体约366.78MB,每个XML文件记录目标的边界框坐标与类别信息,可直接转换为YOLO格式使用,省去人工标注环节。已有511人加入学习下载,适合电力行业算法研发人员、科研学生及目标检测爱好者作为训练与验证数据。该数据集在YOLO框架下能帮助快速构建输电线路巡检模型,提升对设备老化、部件损坏等场景的识别能力,同时也可用于不同光照与复杂背景下的算法效果对比,为实际部署提供可靠支撑。
1. 输电线路数据集到手别急着训:3334张标注图离“能训练YOLO”还差四步
这份“yolo算法-输电线路数据集-3334张图像带标签-.zip”,文件名写得像开箱即用:解压、喂给YOLO、跑训练,一条龙。但真落到输电线路巡检这个场景里,3334张标注图只是个起点。这种包大多是无人机巡检拍回来的绝缘子、防震锤、线夹和导线,标注格式可能是VOC的xml、COCO的json或YOLO的txt,包内还可能暗藏文件名错位、空标签、坏图。拿到手直接训练,十有八九在DataLoader阶段就翻车。适合谁?做电力巡检视觉检测的算法工程师、做目标检测课题的研究生,以及想拿公开数据集评测YOLO版本的开发者。这篇按我平时处理同类数据集的路径,从拆包、验标签、转格式到跑通第一条val命令,一步步说清楚。
2. 拆包看结构:三条命令判断标签格式,VOC、COCO还是YOLO一眼分清
2.1 解压前的完整性检查:先看列表、再测损坏、最后对账文件数
很多人拿到zip第一件事就是双击解压,我建议先执行两条命令,避免解压到一半报“CRC错误”或者解出来缺文件。zip这层协议本身不难,难的是包内文件一致性:图片和标签的文件名能否对上、两个目录数量是否匹配。
# 只列压缩包内容,不实际解压,前30行足够看出目录结构 unzip -l 输电线路数据集.zip | head -30 # 逐个文件做CRC校验,损坏文件会在这里暴露 unzip -T 输电线路数据集.zip # 解压到独立目录,避免和现有工程文件混在一起 unzip -q 输电线路数据集.zip -d transmission_line_dataunzip -l输出里的文件路径能直接告诉你目录层级:是images/和labels/平级,还是所有图片和标注混在一起。-T比-t更严格,逐文件做checksum测试,源文件在打包前如果已经损坏,这一步会明确报错。解压后立刻做一次对账:
cd transmission_line_data echo "图片数量: $(find . -name '*.jpg' | wc -l)" echo "xml数量: $(find . -name '*.xml' | wc -l)" echo "txt数量: $(find . -name '*.txt' | wc -l)" echo "json数量: $(find . -name '*.json' | wc -l)"标题说3334张图带标签,如果图片数和xml/txt数对不上,先别怀疑数据集质量,先查是不是标签文件用了*.JPG大写后缀或者标签被放在子目录里。注意macOS压缩的zip经常带__MACOSX目录和._开头的元数据文件,这些文件不影响校验,但会干扰后面find的统计,建议解压后直接删掉。
2.2 标签格式三选一:按后缀和首行内容快速定性
输电线路数据集在市面上流通,标注格式基本逃不出三种:VOC的xml、COCO的json、YOLO的txt。判断方法很简单,不用写代码,看后缀和文件头就行。
# 看标签目录下都有什么后缀 ls -la labels/ | head -10 # 如果是txt,看第一个文件的前3行 head -3 labels/$(ls labels/ | head -1)VOC格式:每个图片对应一个xml,关键字段是<filename>、<size>里的width/height,以及<bndbox>里的xmin/ymin/xmax/ymax,是绝对像素坐标。COCO格式:整个数据集只有一两个json文件,annotations数组里每条记录包含image_id、category_id和bbox(四个值是x、y、width、height)。YOLO格式:每个图片对应一个txt,每行5个数字:类别id cx cy w h,其中cx、cy是中心点坐标,w、h是宽高,全部归一化到0到1。
这三种格式对应完全不同的处理路径。如果是YOLO的txt,打开一个文件看看坐标是否在0到1之间、类别id是否连续从0开始,通常能直接用。如果是xml或json,就得走第三章的转换脚本。还有一种少见情况:txt里第一行是filename,xmin,ymin,xmax,ymax这种带表头的CSV,那是某些标注平台导出格式,需要单独解析。
2.3 类别分布粗统计:先看类别不平衡再决定训练策略
输电线路目标检测的典型类别包括绝缘子、防震锤、线夹、导线、塔基,缺陷类还分破损、缺失、闪络等。这类数据集有个通病:正常部件样本占比极高,缺陷样本可能只有几十张。不做统计直接开训,模型会对少样本类别完全无视——loss被大类淹没,val的mAP看起来还行,实际部署时缺陷一个都检不出来。
# 对所有YOLO格式txt做类别统计,第一列就是类别id awk '{print $1}' labels/*.txt | sort | uniq -c | sort -rn # 如果是VOC格式,统计xml里的object name grep -h "<name>" labels/*.xml | sort | uniq -c | sort -rn在输电线路场景里,类别不平衡不只是“少”,而是“极度少”。3334张图里绝缘子标注可能上万,而“绝缘子破损”这个缺陷类别可能只有一两百个实例。统计结果出来后,如果少数类实例数小于500,后面训练必须配cls_loss权重或者做过采样,否则这个类基本等于废的。这一步的结论会直接影响第四章的data.yaml配置,别跳过。
3. 统一成YOLO格式:VOC/COCO转换脚本与三个必查项
3.1 VOC转YOLO脚本框架:xml解析、坐标归一化、类别映射顺序
多数输电线路数据集的原始标注来自LabelImg或某平台导出,格式是VOC xml。YOLO训练器不认识xml,必须先转成txt。下面是我常用的转换脚本,按实际使用场景简化过,核心就三步:读xml里的size拿图像宽高、读bndbox拿绝对坐标、换算成中心点加宽高的归一化值。
import xml.etree.ElementTree as ET from pathlib import Path # 类别映射表,顺序就是YOLO的class id,一个字都不能乱 classes = ['insulator', 'damper', 'clamp', 'wire', 'tower'] def voc2yolo(xml_path: Path, out_dir: Path): tree = ET.parse(xml_path) root = tree.getroot() # 图片原始宽高来自xml的size字段 img_w = int(root.find('size/width').text) img_h = int(root.find('size/height').text) lines = [] for obj in root.iter('object'): cls_name = obj.find('name').text if cls_name not in classes: print(f"{xml_path.name}: 跳过未定义类别 {cls_name}") continue box = obj.find('bndbox') xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.find('ymax').text) # 中心点坐标 + 宽高,全部除以原图宽高做归一化 cx = (xmin + xmax) / 2.0 / img_w cy = (ymin + ymax) / 2.0 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h # 越界检查:VOC里偶尔出现xmax比原图宽还大的脏标注 if cx > 1.0 or cy > 1.0 or w > 1.0 or h > 1.0: print(f"{xml_path.name}: 坐标越界 {cls_name} {cx:.3f} {cy:.3f} {w:.3f} {h:.3f}") continue cls_id = classes.index(cls_name) lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") if lines: out_path = out_dir / (xml_path.stem + '.txt') out_path.write_text('\n'.join(lines) + '\n') print(f"{xml_path.name}: 转换出 {len(lines)} 个目标")这段脚本有两个关键点。第一,classes列表的顺序就是YOLO的类别编号,必须和后面data.yaml里的names完全一致。常见翻车是把类别按字母序排,结果xml里的name顺序和列表对不上,虽然转换没报错,但训练出来的模型所有框的类别都是错的。第二,脚本末尾的越界检查不是多余的。无人机航拍输电线路时,绝缘子经常贴着图像边缘,标注人员稍微多点一下,xmax就超出宽度了。这类脏数据直接转进YOLO,轻则训练警告,重则loss变成nan。
3.2 COCO转YOLO脚本框架:按image_id聚合annotation再做换算
有些平台导出的是COCO json。COCO的核心结构是三个数组:images、annotations、categories。转换思路和VOC不同,因为json是一个大文件,得先按image_id把所有标注聚合到对应图片下,再从categories里拿类别名。
import json from pathlib import Path def coco2yolo(ann_file: Path, img_dir: Path, out_dir: Path): with open(ann_file, 'r', encoding='utf-8') as f: coco = json.load(f) # COCO的category_id不一定是连续的,先把id映射成连续编号 cat_id_map = {} for idx, cat in enumerate(coco['categories']): cat_id_map[cat['id']] = idx # 注意:这里idx的顺序取决于json里categories数组的顺序 # 如果想自定义顺序,按名字排序后再建映射 # image_id -> 文件名索引 img_id_to_name = {img['id']: img['file_name'] for img in coco['images']} # 按image_id聚合所有annotations anns_by_img = {} for ann in coco['annotations']: img_id = ann['image_id'] anns_by_img.setdefault(img_id, []).append(ann) for img_id, anns in anns_by_img.items(): file_name = img_id_to_name[img_id] img_path = img_dir / file_name if not img_path.exists(): print(f"警告: 图片不存在 {img_path}") continue # 读取真实宽高,避免拿json里的宽高代替 lines = [] for ann in anns: cls_id = cat_id_map[ann['category_id']] x, y, w, h = ann['bbox'] # COCO的bbox是[x, y, width, height] # COCO的坐标是绝对像素值,转归一化时要用真实图片宽高 cx = (x + w / 2.0) / img_w cy = (y + h / 2.0) / img_h nw = w / img_w nh = h / img_h if cx > 1.0 or cy > 1.0 or nw > 1.0 or nh > 1.0: print(f"{file_name}: 越界bbox {ann['bbox']}") continue lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}") if lines: out_path = out_dir / (Path(file_name).stem + '.txt') out_path.write_text('\n'.join(lines) + '\n')COCO转YOLO最容易踩的坑是直接用json里images字段的width/height做归一化,不重新读图片。某些标注工具在json里写的尺寸和实际图片不一致,一旦不一致,整个数据集的所有框都偏。我在脚本里坚持读取实际图片尺寸。另一个坑是COCO的category_id是从1开始的,而YOLO从0开始,上面代码用enumerate重新编号就是为了处理这个错位。如果你发现转换后的txt第一列有数字大于nc-1,说明映射写错了。
3.3 转换后三查:文件名对得上、txt非空、坐标不出界
转换脚本跑完不等于数据就能用。我见过太多人跑完脚本直接开训,然后浪费一下午排查“为什么类别对不上”。转换后必须做三项校验,都是命令行就能解决的。
# 第一查:每张jpg必须有同名txt,反向也要对得上 for img in images/*.jpg; do base=$(basename "$img" .jpg) if [ ! -f "labels/$base.txt" ]; then echo "缺标签: $img" fi done # 第二查:空标签文件必须处理掉或回补 find labels -name '*.txt' -size 0 | head -20 echo "空txt数量: $(find labels -name '*.txt' -size 0 | wc -l)" # 第三查:坐标越界,任何w或h大于1都说明归一化漏了 awk '{if($3>1 || $4>1 || $5>1 || $6>1) print FILENAME": "$0}' labels/*.txt | head -20第三查的awk条件里,$3是cx、$4是cy、$5是w、$6是h。实际项目里我发现坐标越界最常见的原因不是转换脚本写错,而是源xml里本身就存在xmax大于图片宽度的坏标注。这种情况在输电线路数据集中特别多,因为绝缘子串经常延伸到图像边缘,标注员画框时手一抖就出去了。处理方式不是删除,而是裁剪到边界值再归一化,毕竟一个框越界1%还是能用的,删掉反而亏样本。
提示:以上三条命令全部通过后再进入数据划分。这一步数据是脏的,后面每一步都会放大问题。
4. 划分训练集并配置data.yaml:同塔图片泄漏是val虚高的头号原因
4.1 按塔位批次划分:random.shuffle的指标好看但上线就崩
输电线路数据集有一个和通用目标检测数据集截然不同的特性:同一基塔的航拍图背景高度重复。无人机围绕一基塔拍摄,可能连续拍下几十张不同角度的照片,这些照片共享同一套背景、同一个绝缘子。如果直接用random.shuffle划分train和val,同一基塔的图片会被拆散放进两边,模型在val上看到的“新图片”其实和训练数据高度重合,mAP会虚高到不真实。
更稳妥的做法是按文件名里的塔位编号分组。输电线路巡检图片的命名通常带塔位信息,比如T123_001.jpg、T123_002.jpg代表同一基塔的不同角度。划分时以塔位为单位,整个塔位的图片只能进train或val,不能拆散。这里给出一个按前缀分组的划分思路:
import random from pathlib import Path import shutil img_dir = Path('images') train_dir = Path('split/train/images') val_dir = Path('split/val/images') train_dir.mkdir(parents=True, exist_ok=True) val_dir.mkdir(parents=True, exist_ok=True) # 提取每个文件名的塔位前缀,比如 T123_001.jpg -> T123 img_paths = list(img_dir.glob('*.jpg')) groups = {} for p in img_paths: prefix = p.stem.split('_')[0] # 按实际命名规则调整 groups.setdefault(prefix, []).append(p) all_prefixes = list(groups.keys()) random.seed(42) random.shuffle(all_prefixes) # 按前缀分组数量切分,而不是按图片数量切分 split_idx = int(len(all_prefixes) * 0.8) train_prefixes = set(all_prefixes[:split_idx]) val_prefixes = set(all_prefixes[split_idx:]) for prefix in train_prefixes: for p in groups[prefix]: shutil.copy2(p, train_dir / p.name) label = img_dir.parent / 'labels' / (p.stem + '.txt') if label.exists(): shutil.copy2(label, train_dir.parent / 'labels' / label.name)划分比例建议:3334张图,按塔位分组后如果是8:2,val大约有六七百张,够用了。关键指标是塔位不重叠,而不是图片数恰好八二分。如果文件名里没有塔位编号,退一步按拍摄时间间隔划分也行,同一天的巡检任务划进同一集合,效果接近。这一步直接决定你后面提交的模型指标是否可信,值得认真对待。
4.2 data.yaml配置:path、train、val、nc、names五个字段别写错
划分完目录后,写data.yaml是训练前最后一道配置。YOLO的data.yaml结构很简单,但五个字段里每个都有坑。
# 这个yaml放在数据集根目录下 path: . # 相对路径基准,写"."代表yaml所在目录 train: split/train/images val: split/val/images nc: 5 # 类别数量,必须和names列表长度一致 names: 0: insulator 1: damper 2: clamp 3: wire 4: towerpath字段的坑在于它决定了后面train和val是相对谁解析的。如果yaml放在项目工程目录,而数据集在别的路径,path要写成数据集根目录的绝对路径。nc必须和names列表长度一致,多一个少一个都会在训练启动时直接报错或产生诡异的类别映射。names的索引顺序必须和第三章转换脚本里的classes顺序完全一致,这一点怎么强调都不为过。
很多新手会问要不要写test字段。3334张图的数据集本来就不大,我建议在划分时直接切成train/val/test三份,哪怕test只有100张,也值得留出来。这样做的好处是最后模型训练完有一个完全没碰过的集合做最终验证,避免在val上调参调太久导致过拟合val。
4.3 训练参数初设:imgsz 640起步、anchor交给自适应机制
data.yaml写好后,训练命令本身也要设置参数。输电线路目标检测有个显著特点:小目标占比极高。绝缘子在4K航拍图里可能只有几十个像素宽,防震锤更小。但这不意味着你应该直接把imgsz拉到1280,显存和训练时间会成倍增加,而且小目标也不是单纯靠增大输入分辨率就能解决的。
yolo train model=yolov8s.pt data=data.yaml epochs=100 imgsz=640 batch=16imgsz=640是起步值,先跑通流程,确认loss正常下降、val的mAP不是0,再回头试imgsz=960或1280。batch取决于显卡显存,16G显存跑yolov8s用16没问题,8G显存降到8。网上关于yolo算法讲解ppt的教程一大把,但真正到这个落地的环节,最关键的不是anchor尺寸或者backbone结构,而是数据质量。YOLOv8以后anchor已经改成自适应,训练时会自动从数据里统计框的尺寸分布,不需要手工kmeans聚类。别把时间浪费在调anchor上,先把数据划分和标注质量搞定,收益高得多。
如果类别不平衡严重,比如缺陷类只有几百个实例,训练命令里要加类别权重:
yolo train model=yolov8s.pt data=data.yaml epochs=100 imgsz=640 batch=16 \ cls=0.7 # 默认0.5,提高对少样本类别的惩罚权重cls参数的原理是对分类loss加权,类别越少权重越大。但这只是缓解手段,不是根治方案。真正有效的是后续对少样本类别做数据增强或采集补样本,会把精确率和召回率拉上一个台阶。
5. 训练前避坑清单:五个翻车点从现象到解法
5.1 文件名大小写不一致导致标签匹配率为零
现象:训练启动时YOLO打印“WARNING: labels not found in image”或训练正常但val的mAP全是0。原因:xml里的<filename>字段写的是IMG_20210305.JPG,而实际图片文件叫img_20210305.jpg。Linux文件系统区分大小写,Windows上解压出来的数据还好,一旦放到Linux服务器训练,全部标签匹配失败。解决:建立索引时不要读xml或json里的filename字段,直接用文件系统的实际文件名作为基准。如果已经转换完,执行一个统一的改名脚本,把所有图片和标签文件名都转成小写。
for f in images/*.JPG; do mv "$f" "${f%.JPG}.jpg" base=$(basename "$f" .JPG) if [ -f "labels/$base.txt" ]; then mv "labels/$base.txt" "labels/$(basename $base).txt" fi done5.2 空标签文件导致训练直接崩溃
现象:训练几分钟后报错AssertionError: labels not in dataset,或者某个epoch直接中断。原因:转换脚本遇到源xml里没有<object>的图片,生成了0字节txt。YOLO训练器读到空标签文件会认为数据异常。解决:先统计空文件数量,再决定是删除对应图片还是回补标注。对于输电线路数据集,纯背景图(没有绝缘子、没有塔材)其实是有价值的负样本,但YOLO的标签格式不支持空txt和图片共存。我的做法是:空标签对应的图片单独放一个no_objects目录,用它们做训练时的负样本增强,而不是直接混进数据集。
5.3 类别映射顺序错位,模型把所有绝缘子都识别成防震锤
现象:训练loss正常下降,val的mAP整体看也还行,但单独看每个类别的mAP发现全乱了。原因:第三章转换脚本里的classes列表顺序和data.yaml里的names顺序不一致。VOC xml里的name是'insulator',转换时classes.index('insulator')得到0,但data.yaml里0对应的却是damper,模型学到的类别编号就全歪了。这类错误最难排查,因为训练过程完全不报错。解决:转换脚本的classes列表和data.yaml的names必须从同一个配置源生成,不要各写一份。最稳的做法是转换脚本从data.yaml里读names,保证单一真源,顺序永远一致。
5.4 压缩包里的坏图和隐藏文件让cv2读取崩溃
现象:训练跑到一半报cv2.error: can not open or read file,或者某个epoch的loss突然变成nan。原因:解压后的目录里混入了macOS的._开头元数据文件、缩略图目录Thumbs.db,甚至有几张jpg后缀但实际是损坏文件。这类文件占位不多,但YOLO遍历目录时会把它们当成有效图片读入。解决:训练前用脚本全量检查图片可读性,顺便把隐藏目录清掉。
# 删除macOS和Windows的隐藏目录 rm -rf __MACOSX find . -name '._*' -delete find . -name 'Thumbs.db' -delete再用Python做一次图片完整性检查:
from pathlib import Path from PIL import Image bad_images = [] for p in Path('images').glob('*.jpg'): try: img = Image.open(p) img.load() except Exception: bad_images.append(p) print(f"坏图数量: {len(bad_images)}") for p in bad_images: print(p)坏图直接删除或移出数据集目录,因为后续任何一步都可能因为这张图导致训练中断。
5.5 归一化坐标和绝对坐标混用,一个txt里w大于1
现象:训练不报错,但val的mAP在某一类上异常低,打开标签可视化时框全画偏了。原因:数据集不是单一来源,部分图片的标签是VOC转过来的(归一化坐标),另一部分是有人手工用标注工具导出时勾了“绝对坐标”选项(像素值直接写入txt)。两类数据合并时没有统一。典型特征是一个txt文件里出现w=1.2或者cx=0.8这种明显越界的值。解决:第三章的awk校验命令在合并前跑一遍,把所有异常文件找出来单独重新归一化。处理完再进入训练流程,这是唯一靠谱的解法,没有捷径。
6. 先用一条yolo val命令验证数据集,再考虑要不要动模型结构
6.1 用yolo val看per-class的mAP50:数据质量的第一份体检报告
很多人拿到数据集,第一步直接train,这是成本最高的做法。我的习惯是先用预训练模型在数据集上做一次val,不训练,只看推理结果。这一步只需要一条命令:
yolo val model=yolov8s.pt data=data.yaml imgsz=640这条命令会用yolov8s在COCO上的预训练权重跑一遍你的数据集,输出每类目标的mAP50和mAP50-95。这一步的价值在于:预训练模型没在你的数据上训练过,它的表现完全取决于你的标签质量和目标可辨识度。如果某一类的mAP50只有个位数,先别怀疑模型,回查那一类的标签——大概率是框没贴住目标、类别标错或者坐标越界。如果所有类都是0,那几乎可以断定是类别映射错位或者标签路径没接对。
第一次val建议加plots=True参数,让YOLO输出混淆矩阵和预测样例图,用眼睛直接看哪个类被认成了哪个类。比看数字直观得多。
6.2 可视化bbox回查标注质量:画完框一眼看出脏数据
数值校验能查出物理层面的问题(空文件、越界),但查不出标注质量问题(框偏了、框太大、目标漏标)。这一步我会写一个极简的可视化脚本,把标签框画在原图上,抽几十张图肉眼扫一遍。
import cv2 from pathlib import Path images_dir = Path('split/train/images') labels_dir = Path('split/train/labels') out_dir = Path('check_vis') out_dir.mkdir(exist_ok=True) # 颜色表按类别id对应 colors = [(0, 255, 0), (0, 0, 255), (255, 0, 0), (0, 255, 255), (255, 255, 0)] for txt_path in list(labels_dir.glob('*.txt'))[:50]: # 先抽50张看 img_path = images_dir / (txt_path.stem + '.jpg') if not img_path.exists(): continue img = cv2.imread(str(img_path)) h, w = img.shape[:2] for line in txt_path.read_text().strip().splitlines(): parts = line.split() cls_id = int(parts[0]) cx, cy, bw, bh = map(float, parts[1:]) # 还原成像素坐标 x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[cls_id], 2) cv2.putText(img, str(cls_id), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[cls_id], 1) cv2.imwrite(str(out_dir / txt_path.name), img)画完图你会立刻看到哪些框的边框离目标边缘有几十像素的空白。输电线路数据集的绝缘子标注,最常见的质量问题是框过大——标注员把绝缘子串两端的金具也框了进来。这种框不算错,但会让模型学到的目标范围偏大,部署时对遮挡场景的检测能力明显下降。如果抽检50张里超过10张有明显标注问题,我的建议是暂时放弃直接训练,先花时间修正标签。脏标签训练出来的模型,指标再好看也是空中楼阁。
6.3 一个延续到现在的习惯:先验数据、再训模型、最后调参
做这个方案我踩过最大的一次坑,是把一个“看着没问题”的输电线路数据集直接训了一版yolov8m,训练三天,val的mAP50报0.72,当时觉得不错。结果拿到现场测试,检测结果一塌糊涂,查了两天才发现数据划分时没有按塔位分组,val里全是训练时见过的同塔背景。从那以后,我拿到任何标注数据集,第一件事永远是先花两小时把标签和图片对一遍,而不是着急写训练代码。后来所有项目都沿用了这个习惯,教训就是:数据集的坑,越早发现,修复成本越低。真正上线回查的时候,省下来的时间一定是当初那两小时的十倍以上。希望帮到你。
本文还有配套的精品资源,点击获取