
简介一套适用于YOLO系列算法的杂草与作物目标检测数据集面向计算机视觉初学者与农业智能化开发者可快速投入训练、验证与测试环节。压缩包共2000个文件以XML标注文件为主同时提供YOLO格式txt与VOC格式xml两套标签并附带数据集配置文件data.yaml可直接对接YOLOv5、YOLOv8、YOLOv9、YOLOv7、YOLOv10、YOLO11等主流版本。标签格式规范类别索引从0开始边界框坐标均为归一化比例值便于预处理与迁移学习。数据已做好训练集/验证集划分免去手动拆分工作包体大小约137.26MB已有104人学习使用。对于初学者可借助该数据集完整跑通YOLO目标检测流程理解标注格式与数据组织方式对于研究者也可基于此开展数据增强、模型调优等实验。整体特别适合农业除草、作物监测、田间智能识别等场景可帮助快速建立基线模型并横向对比不同YOLO版本的精度与推理速度。1. 杂草与作物目标检测2722张带标签数据集能直接省掉哪些事这份yolo算法-杂草和作物数据集-2722张图像带标签-杂草-作物.zip本质上是一套为 yolo系列算法目标检测数据集 定制的训练物资2722 张杂草与作物图像全部带标签训练集、验证集、测试集已经帮你划好data.yaml 也放进包里拿到手就能往 YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLO11 这些主流算法里喂。做农业检测的人最怕的不是训不好而是没数据、标签乱、格式不统一这套东西正好把这三件事一次性消掉。适合两类人刚入门目标检测、想省掉标注时间的初学者以及需要在杂草-作物场景做算法选型或快速验证的从业者。不过别高兴太早拿到压缩包直接开训还是会翻车问题大多出在格式细节上。2. 数据集资源拆解双标签格式与 data.yaml 的适配逻辑先不要急着点训练按钮花十分钟把资源包的结构和标签格式读明白能省掉后面好几个小时的排错时间。杂草和作物这类农业目标检测标签一旦错位模型训练得再久也学不到正确的东西。2.1 目录结构与命名规则文件里藏着什么信息这份数据集的目录组织方式是目标检测任务里最常见的一种解压后大概是这样的weeds_crops/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── annotations_voc/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamlimages 里放的是图像labels 里放的是 YOLO 格式的 txt 标注annotations_voc 里放的是 VOC 格式的 XML 标注。YOLO 系列算法读取 data.yaml 之后会根据 train 字段找到 images/train然后在它同级目录下找 labels/train所以这两个目录的层级结构必须保持一致。项目正文里出现的 XML 文件名很有意思比如 img_0887_506.xml、img_0887_1927.xml这种命名不是常见的“图像名.xml”更像“图像名_目标编号.xml”。我拿到这类资源的第一反应是先看 XML 内容确认文件里是单个 object 还是多个 objecthead -20 annotations_voc/train/img_0887_506.xml如果每个 XML 里只有一个 object说明导出工具按目标实例拆分了标注如果每个 XML 里有多个 object那就和标准 VOC 一致。无论哪种情况训练时都不用自己合并 XML直接用 labels/train 里现成的 txt 就好XML 作为格式备份和复核来源更合适。真正的坑在后续坐标转换和类别映射环节。2.2 YOLO 格式与 VOC 格式坐标换算与双份保留的价值YOLO 格式的 txt 每行对应一个目标框字段含义非常固定class x_center y_center width height其中 class 是类别索引从 0 开始x_center 和 y_center 是目标框中心点的归一化坐标width 和 height 是目标框的归一化尺寸。所有坐标值都是相对图像宽度和高度的比例范围在 0 到 1 之间。举个例子0 0.523437 0.482421 0.071875 0.134375表示类别为 0 的目标中心点在图像横向 52.34%、纵向 48.24% 的位置宽为图像宽度的 7.19%高为图像高度的 13.44%。VOC 格式的 XML 就不一样了它记录的是像素坐标通常长这样bndbox里直接给出 xmin、ymin、xmax、ymax。两者互换时需要做一次坐标换算我一般用这个脚本处理单行标注def yolo_to_xml_bbox(line, img_w, img_h): 将 YOLO 归一化坐标转换回 VOC 像素坐标 line: YOLO 格式的一行文本例如 0 0.5234 0.4824 0.0718 0.1343 img_w: 图像宽度 img_h: 图像高度 返回: (类别索引, (xmin, ymin, xmax, ymax)) parts line.split() cls_id int(parts[0]) x_c, y_c, w, h map(float, parts[1:]) # 归一化坐标乘回图像宽高得到像素尺寸 box_w w * img_w box_h h * img_h xmin x_c * img_w - box_w / 2 ymin y_c * img_h - box_h / 2 xmax x_c * img_w box_w / 2 ymax y_c * img_h box_h / 2 return cls_id, (int(xmin), int(ymin), int(xmax), int(ymax))这段代码的逻辑是先把中心点和宽高分别乘回图像尺寸再通过中心点加减半宽半高得到左上角和右下角坐标。参数上要注意如果图像不是 uint8 类型int() 转换前最好先做 round()否则像素坐标会偏一两个像素。这类微小误差在训练时影响不大但做标注审计时容易被当成异常框。数据集同时保留 txt 和 XML 两个版本的好处就在这里txt 直接喂给 YOLO 训练XML 可以导入 LabelImg 等工具做人工复核也可以作为转其他框架格式的中间产物。常见做法是训练只用 txt复核用 XML两边不一致时以 XML 为准重新生成 txt因为 XML 里保留了文件名、图像尺寸、类别名等更完整的上下文。2.3 data.yaml路径、nc、names 三者必须对齐data.yaml 是整个训练流程的入口这份数据集的摘要里明确写了包含它。一个典型的内容是path: /absolute/path/to/weeds_crops train: images/train val: images/val test: images/test nc: 2 names: 0: weed 1: croppath 指定数据集根目录train、val、test 是相对 path 的子目录分别指向三个图像目录nc 是类别数量这里就是 2杂草和作物names 是类别名列表它的索引顺序直接对应 txt 里每行开头的 class id。这三者必须完全对齐否则模型训练不报错但预测结果会张冠李戴。我拿到任意数据集都会先跑一个对齐检查读取所有 txt统计最大类别索引和 data.yaml 里的 nc 做比较。import yaml from pathlib import Path cfg yaml.safe_load(Path(data.yaml).read_text()) max_cls -1 for label_path in Path(labels/train).glob(*.txt): for line in label_path.read_text().splitlines(): parts line.split() if len(parts) 5: max_cls max(max_cls, int(parts[0])) print(fnc{cfg[nc]}, max_class_id{max_cls}) if max_cls cfg[nc]: print(class id out of range, data.yaml and labels not aligned) else: print(class index range OK)这段脚本的逻辑是遍历标签文件逐个对比类别索引的最大值。因为合法索引范围是 0 到 nc-1如果 max_cls 大于等于 nc说明标签里出现了 data.yaml 没声明的类别或者是转换脚本写死了索引。这个小脚本跑完基本就能排除一大半格式类问题。3. 训练前先做数据体检脚本挡掉大部分可复现问题很多人拿到数据集第一件事就是开训结果训练到一半 loss 异常或者验证集 mAP 一直很低最后排查才发现是标签文件缺失、坐标越界这类低级问题。与其事后定位不如训练前花十分钟跑一遍数据体检。3.1 图像与标签同名核对缺标签和孤儿标签一屏显示YOLO 训练时通过图像文件名去找同名 txt比如 img_0887.jpg 对应 img_0887.txt。如果某张图像没有对应 txt这张图会被直接跳过反之如果某个 txt 没有对应图像说明标签目录混入了无关文件。可以先跑一遍全量核对from pathlib import Path for split in (train, val, test): images set(p.stem for p in (Path(images) / split).glob(*.jpg)) labels set(p.stem for p in (Path(labels) / split).glob(*.txt)) missing images - labels # 有图但缺标签 orphan labels - images # 有标签但缺图 print(f[{split}] images{len(images)} labels{len(labels)} fmissing{len(missing)} orphan{len(orphan)}) if missing: print( missing example:, sorted(missing)[:5]) if orphan: print( orphan example:, sorted(orphan)[:5])这段脚本用 set 做差集逻辑很直接missing 是图像有但标签没有的样本orphan 是标签有但图像没有的样本。参数上要注意glob 只匹配了 jpg 后缀如果数据集里混有 png 或 jpeg需要把后缀列表扩一下。常见做法是先用 Path.suffix 看一下训练集里所有图像后缀的分布再决定怎么匹配。缺标签图超过 10%就要考虑是不是解压不全或文件复制中断了。3.2 标注内容体检类别编号、越界、零宽高全查出来同名核对只是第一步标签内容是否合法更关键。YOLO 格式对坐标有一套硬性要求class id 必须在 0 到 nc-1 之间width 和 height 必须大于 0中心点坐标必须在 0 到 1 之间目标框不能超出图像边界。逐个文件检查一遍from pathlib import Path nc 2 issues [] class_count {} for split in (train, val, test): for label_path in (Path(labels) / split).glob(*.txt): for line_number, raw in enumerate(label_path.read_text().splitlines(), 1): parts raw.split() # 字段数量不对直接记录 if len(parts) ! 5: issues.append((label_path.name, line_number, raw, field_count ! 5)) continue try: cls_id int(parts[0]) x_c, y_c, w, h map(float, parts[1:]) except ValueError: issues.append((label_path.name, line_number, raw, parse_error)) continue # 类别索引越界 if not (0 cls_id nc): issues.append((label_path.name, line_number, raw, class_out_of_range)) # 宽高必须为正 if w 0 or h 0: issues.append((label_path.name, line_number, raw, non_positive_size)) # 中心点必须在归一化范围内 if not (0 x_c 1 and 0 y_c 1): issues.append((label_path.name, line_number, raw, center_out_of_range)) # 目标框不能明显超出图像边界容差 1e-3 给浮点误差留空间 if x_c - w / 2 -1e-3 or x_c w / 2 1 1e-3 or y_c - h / 2 -1e-3 or y_c h / 2 1 1e-3: issues.append((label_path.name, line_number, raw, box_out_of_bound)) class_count[cls_id] class_count.get(cls_id, 0) 1 print(class_count:, class_count) print(total issues:, len(issues)) for item in issues[:10]: print(item)这个脚本里 nc 硬编码为 2对应杂草和作物两个类别运行前先确认 data.yaml 里的实际 nc。边界检查加了 1e-3 的容差是为了放过浮点数换算带来的微小误差但如果出现大量越界基本可以断定是 VOC 转 YOLO 时忘了除以图像宽高。class_count 的输出也很重要如果两类目标数量差距超过 5 倍训练时类别不均衡会导致小类别的召回率很低。其实还有一个和这份资源相关的隐藏问题像 img_0887_506.xml 这样按实例拆分的标注如果生成 txt 时聚合逻辑写错可能出现重复框或者漏框。重复框在这个体检脚本里表现为同一张图出现大量坐标几乎相同的框肉眼排查效率低建议结合下一步的可视化抽检。3.3 可视化抽检画框看标签贴不贴合目标脚本能查出格式问题却查不出语义问题比如框偏了半个身位、框住了背景、或者几个草挤在一起只标了一个。可视化抽检是唯一能确认标签语义是否正确的办法import cv2 from pathlib import Path image_path Path(images/train/img_0887.jpg) label_path Path(labels/train/img_0887.txt) img cv2.imread(str(image_path)) h, w img.shape[:2] for line in label_path.read_text().splitlines(): parts line.split() cls_id int(parts[0]) x_c, y_c, bw, bh map(float, parts[1:]) # 归一化坐标乘回原图尺寸转换为像素框 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) # 类别 0 用红色类别 1 用绿色方便区分 color (0, 0, 255) if cls_id 0 else (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, str(cls_id), (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1) cv2.imwrite(check_0887.jpg, img)这段代码 cv2.imread 读出来是 BGR 格式画框时颜色参数要注意通道顺序。坐标换算是把归一化中心点和宽高分别乘以原图宽高再计算左上角和右下角。类别 0 和 1 分别用红绿两色区分保存成新图后人工翻看重点看密集区域和遮挡场景。抽检思路是每个子集选 20 到 30 张不要只挑清晰的越模糊越要选。杂草和作物这类目标经常是丛生状态如果标注人员只框了大的、漏了小的可视化一看就知道。这也是数据集质量评估最省时间的办法。4. 用 YOLOv8 跑通完整训练配置、命令与超参数怎么调数据体检通过之后就可以正式进入训练流程。YOLOv8 是目前生态最成熟的版本命令统一、文档多、排查方案也多所以这一章先以 YOLOv8 作为基线把流程跑通。后面切换 YOLOv5、YOLOv10 时思路是通用的。4.1 环境搭建与项目路径规范训练前先装依赖。ultralytics 包已经整合了 YOLOv8 和更新版本的训练逻辑一条命令就能安装pip install ultralytics python -c import ultralytics; print(ultralytics.__version__)环境上注意 Python 版本建议 3.9 到 3.11 之间PyTorch 是否能用 GPU 由本机环境决定。2722 张图的数据量不算大CPU 也能训完 nano 模型只是速度慢。有 NVIDIA 显卡的同学先确认 CUDA 可用训练日志里会显示 device 信息。路径规范是个容易翻车的地方。把数据集放到一个独立目录路径里不要带中文、空格或括号然后打开 data.yaml 把 path 改成绝对路径。我见过太多因为工作目录不同导致相对路径指向错误位置的案例所以我的习惯是直接写绝对路径一劳永逸。4.2 把 data.yaml 改成适合自己机器的绝对路径修改后的 data.yaml 示例path: /home/you/datasets/weeds_crops train: images/train val: images/val test: images/test nc: 2 names: 0: weed 1: crop这里 train、val、test 都是相对 path 的目录YOLO 会自动处理 labels 路径。很多人在 train 字段里写完整的/home/you/datasets/weeds_crops/images/train结果 YOLO 把完整路径又拼到 path 后面直接报目录不存在。names 的索引顺序必须和 txt 第一列一致这个前面反复强调过这里不再展开。改完之后跑一个快速校验确认三个目录都能找到并且 names 解析正常python - EOF import yaml from pathlib import Path with open(data.yaml, encodingutf-8) as f: cfg yaml.safe_load(f) for split in (train, val, test): p Path(cfg[path]) / cfg[split] print(split, p, exists:, p.exists()) print(cfg[names]) EOF这个脚本的逻辑是把 data.yaml 里的相对路径拼接成绝对路径然后确认目录存在。如果某个子集路径报不存在优先检查是不是大小写写错或者 images 目录本身就没有对应的子集。4.3 训练命令与关键超参数训练命令本身不长但参数含义值得逐条说清楚yolo detect train datadata.yaml modelyolov8n.pt \ epochs100 imgsz640 batch16 patience10 \ workers4 seed42 projectweed_crops_exp namebaselineepochs 设为 100 个完整轮次但设置了早停因此实际训练一般会在 30 到 60 轮自动收敛imgsz640 是 YOLOv8 默认输入尺寸适合中等大小的目标。杂草和作物如果在小图中占比不大可以调到 960小目标的检出率通常会提升但显存占用和训练时间都会明显增加。batch16 是 8GB 显存下的常见选择显存 4GB 调到 8显存 12GB 调到 24batch 调大能加快训练但过大容易造成模型收敛不稳定。patience10 的意思是连续 10 轮验证集指标没有提升就停止训练实际使用中能省不少时间。workers4 是数据加载线程数CPU 较弱的时候可以降到 2否则数据读取会成为瓶颈。seed42 固定随机种子方便不同模型之间做对比实验。有一点要特别说明modelyolov8n.pt 指向的是官方预训练权重首次运行时会自动下载。如果网络下载失败训练会直接卡住解决方式改成modelyolov8n.yaml从随机权重开始训但 mAP 会明显低一些训练时长也要加长。有条件的话建议提前把权重文件下好放到配置目录里。4.4 训练日志判读哪些指标能信哪些是玄学训练输出目录里有一组关键文件weed_crops_exp/baseline/ ├── weights/ │ ├── best.pt │ └── last.pt ├── results.csv ├── args.yaml └── ...results.csv 记录了每个 epoch 的损失、精度P、召回率R、mAP50 和 mAP50-95。看这个 CSV 比看终端日志靠谱得多因为它保留了整个训练过程的数值变化。几个常见的判读经验loss 持续下降但 mAP 不涨大概率是数据里有噪声标签某个类别的标注框本身就不准P 高 R 低是漏检偏多R 高 P 低是误检偏多mAP50 和 mAP50-95 差距过大说明框定位不准这时候把 imgsz 调大通常比换模型更见效。mAP50-95 在杂草和作物这种语义边界模糊的任务里本身就是有点玄学的指标不要太纠结它小数点后两位的变化。训练过程中 graph 曲线有波动是正常的看趋势就行。我习惯每 20 轮看一眼 results.csv 里的 mAP50确认它在单调上升而不是反复震荡。如果震荡幅度超过 10%优先怀疑数据问题。4.5 用 best.pt 做推理验证训练结束后把 best.pt 对整个测试集做一次推理yolo detect predict modelweed_crops_exp/baseline/weights/best.pt \ sourceimages/test imgsz640 saveTrue输出结果默认保存在 runs/detect/predict 目录下。打开这些图重点看三件事杂草和作物是否互相误检、小目标有没有漏检、密集区域的框有没有错位。如果发现系统性错误比如所有 crop 都被标成 weed优先检查类别映射而不是重新调参。提示推理结果图和第 3 章的可视化脚本可以配合使用把模型预测的 txt 画到原图上和真实标注一对比能快速定位是标注问题还是模型能力问题。5. 避坑指南路径、格式与数据划分的几个高频问题这一章是真实踩坑记录汇总每一条都按现象、原因、解决三步写你遇到类似日志报错时可以直接对照排查。5.1 训练启动阶段路径和文件格式类的高频报错第一个坑是训练启动直接报AssertionError: train: No labels in ...。现象是训练命令刚跑起来就退出错误提示说 labels 目录里找不到标签。原因有几种可能data.yaml 的 train 路径写错YOLO 去 images 目录的同级目录找 labels 时落空相对路径依赖运行命令时的当前工作目录换了目录就失效或者解压 zip 时只解压了 imageslabels 目录整个丢了。解决方法是先用第 3 章的同名核对脚本确认 labels 和 images 文件数量对得上再把 data.yaml 的 path 改成绝对路径。这个报错 90% 是路径问题10% 是文件确实缺失。第二个坑是把 VOC 格式的 XML 文件直接当成训练标签。现象是训练能启动但日志里频繁出现 parse error验证集指标恒为 0。原因很直接YOLO 的标签加载器只认 txt 文本VOC 的 XML 结构完全不同放在 labels 目录里等于喂了无效数据。这份数据集把 txt 和 XML 分文件夹存放就是为了避免这种混用。解决方法是 labels 目录里只放 txtXML 统一保留在 annotations_voc 下如果只有 XML需要先完成格式转换再进训练。5.2 训练过程中类别错位与增强越界第三个坑是训练时 mAP 很高但推理结果类别张冠李戴最典型的就是把作物全部识别成杂草。现象是验证集指标看着不错可视化输出反而完全不对。原因基本可以锁定在类别映射上XML 转 txt 时 class id 写死了比如 XML 里正常的顺序是 weed 为 0、crop 为 1但转换脚本按字母表排序把 crop 排到了 0weed 排到了 1而 data.yaml 的 names 还是[weed, crop]两个文件分开看都没问题合在一起就全乱了。解决方法是把 data.yaml 的 names 当作唯一基准先打印一张图里的类别索引集合from pathlib import Path for p in Path(labels/train).glob(*.txt): class_ids sorted({line.split()[0] for line in p.read_text().splitlines()}) print(p.name, class_ids) break如果某个 txt 里同时出现 0 和 1说明两个类别都有样本如果所有 txt 只有 0那就看看这些 0 到底应该对应 weed 还是 crop。确认错位后重新写转换脚本固定映射表不要用排序后自动映射。第四个坑是训练到中途 loss 变成 NaN。现象是训练前期正常几十轮之后 loss 突然变成 nan或者验证集指标大跳水。常见原因有两类一是数据增强把标签框推到了图像边界外mosaic、随机旋转、透视变换都可能放大越界二是标签文件本身存在数值异常比如坐标字段里有 nan 或 inf。解决方法是先跑一遍第 3 章的越界检查把有问题的标签文件过滤掉如果越界标签很少直接删除或裁剪即可。然后检查增强强度的比例YOLOv8 默认增强参数比较激进可以适当调低yolo detect train datadata.yaml modelyolov8n.pt \ hsv_h0.015 hsv_s0.5 hsv_v0.4 mosaic0.8这几个参数控制了 HSV 颜色增强和马赛克增强的强度mosaic0.8 表示 80% 的批次会使用四图拼接。如果调低后仍然出现 NaN建议优先升级 ultralytics 版本因为旧版本在部分图像尺寸组合下确实存在标签越界的已知问题。5.3 评估阶段验证集 mAP 高、实测效果差第五个坑是验证集 mAP 接近 0.9但用自己的实拍图像测试效果远不如预期。现象是模型在 val 集上表现优秀泛化能力却很差。原因不一定是模型过拟合更常见的是数据划分本身存在信息泄漏。杂草和作物数据经常来自同一地块的连续拍摄相邻帧之间背景几乎一样如果划分时是纯随机洗牌train 和 val 里可能混入大量相似图片验证集指标被虚高推上去。解决方法是先检查三个子集之间有没有重复图像用 MD5 做精确去重是最快的方式import hashlib from pathlib import Path def file_md5(path): return hashlib.md5(path.read_bytes()).hexdigest() seen {} for split in (train, val, test): for img in (Path(images) / split).glob(*.jpg): h file_md5(img) if h in seen: print(duplicate:, img, -, seen[h]) else: seen[h] img这段脚本的逻辑是对每张图像计算 MD5在三个子集之间做交叉查重。精确重复能直接查出来近似重复需要感知哈希算法但先跑这个成本最低。如果发现大量重复需要重新划分数据如果没有重复但 val 指标仍然虚高就要考虑按采集时间或帧 ID 分桶而不是随机划分。这也是为什么数据集本身已经划好训练验证测试我仍然会先跑一遍查重脚本的原因。6. 用短周期交叉验证选模型同一份数据一次喂给多个 YOLO 版本数据集的 txt 格式是 YOLO 系列通用格式意味着你可以用同一份数据在 YOLOv5、YOLOv8、YOLOv10 等版本之间自由切换不需要重复转换。这里分享一个我常用的验证技巧不直接训练完整模型先让几个小模型各跑 30 个 epoch观察训练曲线谁更健康再决定哪个版本值得继续投入。for model in yolov8n.pt yolov10n.pt; do yolo detect train datadata.yaml model$model \ epochs30 imgsz640 batch16 workers4 \ projectfast_compare name${model%%.*} done这条命令的逻辑是循环用不同预训练权重训练同一个数据集${model%%.*}是 bash 参数扩展把后缀 .pt 去掉例如 yolov8n.pt 变成 yolov8n作为输出子目录名。30 个 epoch 不追求收敛到最优只为了看训练曲线的走势。两个模型都稳定上升说明数据和标签质量没问题可以大胆继续如果某个模型从头到尾乱跳优先怀疑环境兼容性而不是数据问题。训练完成后对同一批测试图分别推理对比输出差异yolo detect predict modelfast_compare/yolov8n/weights/best.pt sourceimages/test saveTrue yolo detect predict modelfast_compare/yolov10n/weights/best.pt sourceimages/test saveTrue对比时重点看同一张图上哪个模型把杂草和作物的边界分得更清哪个模型在密集区域漏检更少。短周期对比的核心观察点有三个训练损失的下降是不是平滑的、验证集 mAP50 是否在稳定增长、当前最优 epoch 出现在什么位置。如果最优 epoch 总是落在最后一轮且指标还在涨说明 30 轮不够需要延长如果前几轮就触顶说明模型容量对这个任务已经过剩。从那以后我每次拿到这类双格式标注的检测数据集都会强制先走一遍数据体检脚本再让两三个小模型各跑 30 个 epoch 做交叉验证确认数据和训练曲线都正常才会上大模型和长周期训练。这套流程帮我挡掉过很多低级翻车希望帮到你。本文还有配套的精品资源点击获取