简介:这是一份面向番茄目标检测任务的数据集,适用于YOLO系列、Faster R-CNN、SSD等主流目标检测模型的训练与验证。资源包含未熟番茄、成熟番茄和病害番茄三个类别,样本覆盖温室、背景复杂等多种场景,可帮助初学者或算法工程师快速开展农业生产场景下的检测实验。压缩包共2000个文件,以1999个txt格式标签文件为主,配合1个yaml类别配置文件,标签文件对应每张图像的检测框信息,包含边界框坐标与类别标签,yaml文件指定类别名称与索引,整体包大小约157.46MB,下载后可直接用于YOLO算法的训练流程,无需额外格式转换。数据集已按训练集、验证集和测试集划分,免去了手动拆分数据的步骤。目前已有281人学习下载,适合用于目标检测入门实践、模型对比评估或番茄成熟度与病害识别等研究场景。
1. 番茄识别数据集:目标检测里最容易被低估的差事
做目标检测的同行应该都有同感:番茄识别数据集这六个字,听着比行人检测、车辆识别简单太多,但真上手才发现,从采集、标注到训练、部署,每一步都比想象中折腾。番茄目标检测之所以难,不是难在模型结构,而是数据本身太“狡猾”——果实颜色随成熟度连续变化、叶片遮挡严重、大棚光照忽强忽弱,同一个番茄在不同角度下看起来像两个类别。
这个标题想解决的问题很具体:给采摘机器人、大棚估产、分拣线分级这类场景,准备一套能真正训练出可用模型的番茄目标检测数据集,并把它跑进 YOLO 系列框架。适合两类人:一类想把目标检测落地到农业场景的开发者,另一类是刚接触目标检测数据集构建、想避开“标注几个月却训不动”的初学者。我会从采集规范、标注选型、格式转换,一路讲到数据增强、YOLOv8 训练、排错和部署验证,每一步都附上可复现的命令和代码。
2. 攒数据集的第一课:从采集规范到 VOC 转 YOLO 的转换脚本
先立一个观点:目标检测模型的性能上限,是由数据分布决定的,模型只是一个拟合器。番茄识别数据集如果只从图库扒几百张干净背景的图片,训练出来的模型一到真实大棚就会误检百出。所以攒数据集的第一步不是打开标注工具,而是先定采集规范。
2.1 采集阶段先定三类场景:光照、遮挡、成熟度不能一把抓
常见的做法是先把采集场景拆成三个维度:场地类型、光照条件、成熟度状态。场地至少覆盖露地、温室大棚、分拣传送带三类,因为背景差异很大——露地有天空和泥土,大棚有立柱和薄膜反光,传送带有强光和运动模糊。光照要覆盖晴天直射、阴天散射、背光、人工补光四种,这样模型才不会只在某个固定色温下生效。
成熟度建议分成三档:青熟、转色、全红。做分拣线还想细分“软果”或“病斑”,但那已经超出检测任务本身,属于分类器的事。我一般建议在一开始只定这三档,类别越细,标注一致性越难保证。青果和叶片颜色接近,转色果和黄果形态相似,这三档边界已经足够让标注员头疼。
采集参数上,手机相机足够了,但分辨率至少 1080p,且要保证对焦准确。比连拍更推荐的是视频抽帧:固定机位拍一段,隔 N 帧抽一张。N 的判断标准是“相邻两帧里同一颗番茄的位移超过它直径的三分之一”,太密会产生大量相似帧,太疏会漏掉关键角度。另外,同一串番茄用 3 到 5 个不同角度各拍一遍,能显著提升遮挡样本的覆盖度。目标检测数据集的初始规模不需要贪多,800 到 1500 张标注图就可以训练第一版,后续根据坏例再补。
从公开数据集找补充样本也有用,但要注意比例控制。就像车辆检测数据集 BDD100K 强调天气多样性,鸟类目标检测数据集强调不同姿态一样,番茄数据集的核心是场景多样性和果实状态连续性。公开图和现场图混用建议控制在一比四以内,公开图只用来丰富背景,现场图才是模型真正要学的分布。
2.2 标注工具选型:LabelImg 管离线,Roboflow 管协作
单人标注阶段,我一般用 LabelImg,它是目标检测数据集构建里最常用的小工具。安装方式很简单:
pip install labelimg labelimg启动后打开图片目录和标注保存目录,快捷键w画框,d切换到下一张,Ctrl+S保存。标注输出是 Pascal VOC 格式的 XML 文件,每张图对应一个 XML,里面记录了图片宽高、通道数和每个目标的类别名与框坐标。
标注规范要在开工前写死,这是整个项目里最便宜的一剂后悔药。我常用的一套规则是:框四边紧贴果实可见轮廓,留 2 到 3 像素余量;两个果实挨在一起时,框允许重叠,但不要把两果之间的间隙包进同一个框;遮挡超过 50% 的果实不标,遮挡 20% 到 50% 的果实正常标,但框只画到可见边缘。这套规则能避免后面训练时出现大量“半果框”和“空背景框”。
多人协作时,LabelImg 的本地文件夹模式会很不方便。这时候我一般换 Roboflow,它支持在线分配标注任务、多人同步标注,还能一键把 VOC 转成 YOLO 格式并做在线增强。但 Roboflow 免费额度有限,团队协作频繁时值得付费;单人小项目留在 LabelImg 足够。工具对比大概是:LabelImg 免费、离线、上手快,适合个人冷启动;Roboflow 云端、协作好、格式转换方便,但数据要传服务器,对敏感项目不友好。
2.3 用 Python 把 VOC XML 批量转成 YOLO txt
LabelImg 导出的是 XML,而 YOLO 系列框架训练时需要的是 txt 标签文件。每一行代表一个目标,格式是:类别索引 中心点x 中心点y 框宽 框高,四个坐标值都是归一化到 0 到 1 之间的小数。转换脚本每个数据集项目都要写一遍,我直接给你一个可用的版本:
import xml.etree.ElementTree as ET from pathlib import Path # 类别顺序一定要和后续 data.yaml 里的 names 一致 CLASSES = ["tomato_green", "tomato_breaker", "tomato_red"] def voc_to_yolo(xml_path: Path, out_dir: Path): out_dir.mkdir(parents=True, exist_ok=True) tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") img_w = int(size.find("width").text) img_h = int(size.find("height").text) if img_w <= 0 or img_h <= 0: raise ValueError(f"{xml_path} size 缺失") lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in CLASSES: continue cls_id = CLASSES.index(name) b = obj.find("bndbox") x1 = float(b.find("xmin").text) y1 = float(b.find("ymin").text) x2 = float(b.find("xmax").text) y2 = float(b.find("ymax").text) # 坐标越界裁剪,防止训练时出现负数宽高 x1 = max(0.0, min(x1, img_w)) x2 = max(0.0, min(x2, img_w)) y1 = max(0.0, min(y1, img_h)) y2 = max(0.0, min(y2, img_h)) if x2 <= x1 or y2 <= y1: continue cx = (x1 + x2) / 2 / img_w cy = (y1 + y2) / 2 / img_h w = (x2 - x1) / img_w h = (y2 - y1) / img_h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") txt_path = out_dir / (xml_path.stem + ".txt") txt_path.write_text("\n".join(lines), encoding="utf-8") if __name__ == "__main__": # xml 目录和输出目录按实际路径改 xml_dir = Path("labels/voc") out_dir = Path("labels/yolo") for xml_file in xml_dir.glob("*.xml"): voc_to_yolo(xml_file, out_dir) print("done")这段脚本的逻辑很直接:从 XML 的<size>节点读取原始图片宽高,再把每个<object>节点里的<bndbox>四角坐标换算成 YOLO 的归一化中心坐标和宽高。CLASSES.index(name)把类别字符串映射成数字编号,这是 txt 文件里第一列的内容。
参数上需要特别注意两点:第一,CLASSES列表的排序一旦确定,后续所有版本的数据集都不能再改,否则旧标签全部作废;第二,越界裁剪不是可有可无,标注员手抖把框画到图片外是常有的事,不裁剪会出现负数宽高。转换完成后,挑一两张图把 txt 画回原图检查,这一步不要省。
提示:转换后的 txt 是 UTF-8 编码,别用 Excel 直接打开检查,容易乱码,用 VS Code 或文本编辑器看。
3. 数据增强与切分:让番茄小目标在训练前就站稳脚跟
标注完成并不代表数据集合格。番茄识别数据集最典型的毛病是干净过头:同一个大棚、同一时间段、同样的光照。直接把这种数据丢给目标检测模型,它会把“这个大棚的绿色背景”当成番茄的隐式特征。数据增强和数据切分就是为了打破这种虚假的干净。
3.1 针对番茄的增强策略:调色要克制,形状要保真
通用目标检测增强套路是色彩抖动、旋转、翻转、缩放,但番茄数据集有个特殊性:成熟度判断高度依赖颜色。你把色相偏移拉满,青色番茄变成紫色,红色番茄变成橙色,模型学到的就不是“成熟度”而是“某种色调”。所以我的经验是:色相偏移量控制在 ±5 度,饱和度和明度可以放宽到 ±20 左右。
形状类增强对番茄同样重要。番茄果实是近似圆形,叶片是细长条,适当的旋转和随机缩放能让模型学会“不管果实朝哪边都认识它”。我一般用 Albumentations 在训练时做在线增强,代码片段如下:
import albumentations as A train_transform = A.Compose([ A.RandomBrightnessContrast( brightness_limit=0.2, contrast_limit=0.2, p=0.8 ), A.HueSaturationValue( hue_shift_limit=5, sat_shift_limit=20, val_shift_limit=20, p=0.5 ), A.RandomScale(scale_limit=(-0.3, 0.3), p=0.5), A.Rotate(limit=30, p=0.4), A.RandomSizedBBoxSafeCrop( width=640, height=640, erosion_rate=0.1, p=1.0 ), ], bbox_params=A.BboxParams( format="yolo", min_visibility=0.4, label_fields=["class_labels"] ))逻辑上,这个管线把图先做亮度和颜色扰动,再做随机缩放和旋转,最后统一裁剪到 640×640。A.BboxParams里的min_visibility=0.4很关键:增强后如果某个框被裁掉超过 60%,这个目标就从标签里删掉,避免训练时看到一个“残缺标签”。
参数上,RandomSizedBBoxSafeCrop的erosion_rate=0.1表示允许裁剪时把目标边缘稍微切掉一点,模拟真实遮挡;scale_limit取 ±0.3 是为了让模型适应不同距离下的果实大小变化。注意 YOLO 训练时本身就带 Mosaic、翻转这类在线增强,如果再用 Albumentations 做同样的翻转,等于把数据重复增强,边际收益会明显下降。
3.2 目录划分与 data.yaml:路径写错是第一个坑
数据集切分不是随便按比例随机抽,而是要先定目录结构。我习惯建这样的布局:
dataset/tomato/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片,不到最后不碰 └── labels/ ├── train/ ├── val/ └── test/图片和标签的文件名必须一一对应,例如img_001.jpg对应img_001.txt。不要用子目录区分类别,目标检测数据集本来就是一张图里多类别共存。
训练前要写data.yaml,这是 YOLO 框架读数据集的入口:
path: /data/tomato train: images/train val: images/val test: images/test names: 0: tomato_green 1: tomato_breaker 2: tomato_redpath是这个 YAML 文件所在机器的绝对路径,train、val、test指定的目录会拼在path后面。注意train和val填的是目录名而不是图片文件的 txt 列表,这是新人和老手切换时最容易翻车的地方——老版本要求提供train.txt文件,现在用目录结构即可,两套写法都能跑通,但混用就会报“no labels found”。
还有个容易忽略的点:val必须独立提供。如果你不写val,Ultralytics 会默认从train里抽 20% 当验证集。新手会觉得“这挺好,自动切分”,但这样做的问题在于切分时机不可控,而且每次复现随机种子不同,验证结果不具备可比性。正确做法是自己先划分好目录,yaml里写死。
3.3 数据版本化的正向循环:一轮训练后回补坏例
第一版数据集训练结束后,不要急着调模型结构,先看失败样本。把验证集里预测错的图导出,按失败原因分类:是青果漏检,还是遮挡严重造成误检,或者是远处小目标完全没检出。然后针对每一类失败回补数据。
回补的意思是回到现场补拍新照片,重新标注,而不是把已有的图复制一份再调亮度。复制增强只能让模型重复看同一批目标,解决不了分布覆盖不足。我在项目里会给数据集打版本号,例如tomato_v1、tomato_v2,标注完成的图片和标签归档在一个目录,另外维护一个 “回补清单”,记录每个版本补了什么、因为什么失败补的。这个过程看起来琐碎,但它是目标检测数据集从“能跑”变成“能用”的核心环节。
4. YOLOv8 训练自己的番茄数据集:最小启动配置与三个必调参数
数据集准备好以后,训练环节反而是最省心的,因为框架已经把流程封装得很完整。这一章以 YOLOv8 为例,它是当前做自定义目标检测数据集训练比较稳妥的选择,社区资料多,出问题容易查到解决方案。
4.1 环境准备和预训练权重:先跑通单卡训练再说调优
环境配置遵循最小可用原则,先不要折腾 Docker 和分布式训练,单卡跑通再谈别的。创建 Python 环境后安装 Ultralytics 包:
pip install -U ultralytics yolo detect predict model=yolov8n.pt source=https://ultralytics.com/images/bus.jpg第一条命令装的是整个 YOLO 训练预测工具链,第二条命令下载官方预训练权重并跑一次推理,输出一张带检测框的图片就算环境正常。这里用yolov8n.pt是因为它最小最快,跑通验证环境足够。ultralytics包会自动拉起 PyTorch,如果你用的是 NVIDIA 显卡,先确认nvidia-smi能看到显卡,再执行一次第二行命令,看终端里是否出现device: CUDA,如果是 CPU 就要查一下 PyTorch 的 CUDA 版本装没装对。
为什么要选 YOLOv8 而不是从零写检测头?因为番茄识别数据集的重点在数据,不在模型。YOLOv8 在公开检测任务上的先验知识可以通过预训练权重迁移过来,尤其是果实轮廓、叶片纹理这些低层特征,迁移学习能省大量训练时间。等你的数据集足够大、任务足够特殊时,再来考虑从yolov8s.pt还是yolov8m.pt起步的问题。
4.2 训练命令与参数表:imgsz、patience、batch 缺一不可
训练命令比我见过的绝大多数博客写的都短:
yolo detect train \ data=config/data.yaml \ model=yolov8s.pt \ epochs=200 \ patience=30 \ imgsz=640 \ batch=16 \ device=0 \ workers=4 \ cache=True这段命令的逻辑是:从官方预训练权重yolov8s.pt出发,用指定的数据集配置开始训练;epochs是最大训练轮数,patience是早停耐心值,连续 30 轮验证集指标不提升就自动停止;imgsz决定输入图片的缩放尺寸;batch是每轮喂进显卡的图片张数;cache=True会在第一次 epoch 前把图片缓存到内存,第二次启动训练会快很多。
参数说明这块是重点。三个必须理解透的参数是imgsz、patience、batch:
| 参数 | 番茄项目的建议值 | 调参说明 |
|---|---|---|
imgsz | 640 起步,小目标多改 960 | 必须是 32 的倍数;增大输入等于给小目标更多像素,但显存占用按平方增长 |
batch | 16(16GB 显存) | 太小 BN 统计不稳定,太大要同步调低学习率 |
patience | 30 | 验证指标连续 30 个 epoch 不涨就停,避免无效等待 |
epochs | 200 到 300 | 有早停时设大一点没坏处 |
batch和学习率是联动的:如果你因为显存不足把batch从 16 降到 8,理想情况下学习率也应该减半,否则梯度噪声变大,损失曲线会异常抖动。Ultralytics 默认会自动调度学习率,但遇到 loss 炸到 NaN,先查学习率和标签里有没有 NaN 坐标。还有一点,imgsz=640时,一张 1080p 的原图会被缩小到 640×640,原图中较小的番茄在缩放后可能只剩十几像素,这种目标在这个尺寸下基本学不到特征。所以番茄这类小目标偏多的数据集,我会优先把imgsz调到 960 再试。
4.3 训练过程的黑匣子:三条 loss 曲线怎么读
训练开始后,项目目录下会出现runs/tomato/exp/,里面包含一堆曲线图。很多人把损失曲线当玄学看,其实它是有规律可循的。重点关注三条:box_loss、cls_loss、dfl_loss。box_loss下降说明模型预测的框位置在逼近真实框;cls_loss下降说明类别判断在变准;dfl_loss负责框的边界质量,它收敛慢一点是正常的。
读曲线时最容易误解的一个点是:val曲线比train曲线高,并不一定代表过拟合。可能是验证集分布确实比训练集难,也可能是验证集里混入了和训练集相似的帧导致评估失真。真正的过拟合信号是train_loss持续下降、val_loss在某个点反弹并持续上升。遇到这种情况,先别急着加正则化,回头检查数据集切分是不是有问题,第 5 章的相似帧坑就在这里。
番茄遮挡严重的数据集还有一个特点:box_loss不会像公开数据集那样收敛到特别低。因为大量果实边缘被叶片遮挡,标注框本身就有不确定性,模型再强也无法精确到像素级。看到 loss 停在某个平台期下不去,先问数据噪声有多大,再问模型容量够不够。
5. 番茄训练翻车日志:目标检测数据集的 5 个典型踩坑现场
这一章全是踩坑记录。每个坑我都按“现象 → 原因 → 解决”讲透,都是我实际做过番茄项目时遇到的。
5.1 框松框紧不一致,AP@0.75 直接拉胯
现象:训练结束看验证结果,mAP@0.5不低,但mAP@0.75明显偏低,画出来的 PR 曲线在 0.75 附近快速跌落。
原因:标注员 A 喜欢把框画得很宽,把果蒂和一点叶子都包进去;标注员 B 喜欢贴果肉边缘,框小而紧。模型在训练时看到的 IoU 标准不一,预测框只能“平均”这些标注习惯,导致它永远无法和任何一套标准对齐。IoU 阈值取 0.75 时,框位置差几个像素就判定为失败,问题立刻暴露。
解决:开工前写死标注规范,明确“框四边贴住果实可见轮廓,最多留 3 像素余量”。做完一批标注后抽 20% 检查框的紧实度,发现松框直接打回重标。如果是多人协作,同一批图片最好由同一个人标完,不要在训练集里混合两套标注风格。
5.2 验证集混入相似帧,val_loss 后期越洗越虚
现象:训练到第 80 轮时train_loss还在降,但val_loss开始上涨,看起来像过拟合。可模型在测试现场的漏检率并不高。
原因:数据切分用了随机打散,而没有按“视频片段”维度切。同一个视频抽出来的相邻帧,一张在训练集、一张在验证集,视觉内容几乎一样。验证集里塞满了训练集的“亲戚帧”,评估分数被大幅高估,而 val_loss 曲线则因为验证集内部统计不独立而出现虚假上涨。
解决:视频抽帧后,先按视频文件分组,再把整个分组划分到训练集或验证集。比如 10 段视频,8 段进训练,2 段进验证,保证没有任何一帧来自同一个视频片段。更进一步,可以用感知哈希去重,把肉眼几乎相同的帧删掉。
5.3 青色番茄完全漏检,类别不平衡被低估
现象:红色番茄的召回率 90%,青色番茄的召回率连 40% 都不到,而且模型把不少叶片当成青番茄。
原因:数据集中青色番茄只占 15%,红色番茄占 60%,转色期占 25%。类别不平衡让模型在训练中把“红色圆轮廓”当作主导特征,青番茄与叶片形状和颜色都接近,样本少学不到判别力,误检自然高。
解决:先统计每个类别的标注框数量,低于总数 20% 的类要回补。回补时优先去现场采集青熟期果实,或者换个角度重新拍;如果实在补不到,可以把已有青番茄样本离线复制 2 到 3 倍,配合轻微的颜色扰动。对损失函数层面,也可以给类别权重,但这是第二选择,第一选择永远是数据本身。
5.4 远处小目标全灭,imgsz 和切片谁说了算
现象:画面近处的大番茄框得很准,远处果园深处的番茄漏检一片,如果把验证按尺寸分桶看,小目标的 AP 接近零。
原因:原图 1080p 缩到 640×640 后,远处番茄在图上可能只有 10×10 像素,特征图下采样后只剩一两个特征点,检测头根本分不清那是果实还是叶子。
解决:先尝试把imgsz提到 960,显存不够就减batch。如果提到 960 仍然漏检,就得切图推理,把一张 1080p 的原图切成四张 640×640 的重叠块,分别推理再把结果按坐标拼回去。注意切图时要留 10% 左右的重叠区域,否则果实刚好在切缝处会被截成两半。不要一上来就上 MMROTATE 那套旋转框方案,水平框在番茄场景下够用,旋转框是遥感 DOTA 数据集的高价需求,这里不需要。
5.5 训练集 mAP 很高,现场演示却翻车
现象:验证集 mAP@0.5 达到 0.95,拿到温棚现场跑,误检和漏检却比测试时严重得多。
原因:数据分布偏移。训练集和验证集都来自同一天下午,阳光充足,模型学会了“顺光下红绿分明的番茄长什么样”。现场是阴天加人工补光,叶片反射偏黄,模型把反射高光误判为番茄果面。
解决:建立一套“现场验证集”,专门从部署场地录 200 张照片,标好框,但永远不参与训练。任何模型版本上线前,必须在这套现场集上评估,指标过线才允许部署。如果现场集表现差,最有效的办法是拿现场图做小样本微调,而不是重新训练全院模型。微调用 50 到 100 张现场图,跑 30 个 epoch 就够,多了会破坏原有的泛化能力。
6. 验证与落地之间的最后一公里:从测试集拆分到 ONNX 导出
6.1 测试集按场景分组,避免数据集“掏洞”
很多项目在切分时只做了 train/val,test 直接从剩余数据里随机抽。正确的做法是测试集完全不参与训练和验证,并且在物理维度上隔离。对番茄数据集来说,隔离单位是“大棚编号”或“植株行号”——同一行、同一株的果实,不管怎么随机划分,它的背景和光照条件都是高度近似的。按场景分组后,训练集、验证集、测试集的分布才真正独立。
如果你的数据来源比较多,还要注意测试集的难度不要低于验证集。我吃过亏:测试集选了大棚入口处光线最好的几排,验证集反而更难,结果模型“看起来测试不错”,一到生产环境就露馅。
6.2 用 val 和 predict 做落地的双保险
训练完成后,用两段代码完成最终验收:
from ultralytics import YOLO model = YOLO("runs/tomato/exp/weights/best.pt") # 在测试集上做正式评估 metrics = model.val( data="config/data.yaml", split="test", plots=True, ) print(metrics.box.map50, metrics.box.map) # 在现场新图片上做推理,并保存可视化图 results = model.predict( source="data/field_day1", conf=0.25, iou=0.45, save=True, project="runs/verify", name="field_day1", )这段代码的逻辑是先用val拿一批量化指标,再用predict做实际效果的可视化检查。metrics.box.map50是 IoU 阈值 0.5 的 mAP,metrics.box.map是 0.5 到 0.95 的平均 mAP,后者更严格,对框的精确度更敏感。番茄这类小目标多的数据集,我会重点看map而不是map50。
predict时的conf和iou也需要调:conf=0.25是置信度阈值,太高会漏掉遮挡严重的果实,太低会有一堆叶片误检;iou=0.45是 NMS 阈值,果实密集时建议降到 0.4,让互相重叠的果实更容易被分开。
6.3 从 s 到 n:一张表把模型裁剪给现场
训练时用的是yolov8s,部署在 Jetson 或 arm 盒子上时,如果帧率不够,可以先蒸馏或者直接换成yolov8n再微调几轮。一个实用的做法是:保留s模型训练结果作为教师模型,用n模型在同一个训练集上继续训练,学习率调低到原来的十分之一。这样裁剪后的模型能继承大部分精度,又能在边缘设备上跑起来。
如果要用 TensorRT 或 ONNX Runtime,导出命令如下:
yolo export \ model=runs/tomato/exp/weights/best.pt \ format=onnx \ imgsz=640 \ opset=12导出后一定要做一次精度复核,ONNX 和 PyTorch 推理结果在数值上通常会有微小差异,如果差异超过 0.5% 的 mAP,优先检查输入归一化逻辑是否一致。
养成习惯之后,我现在新开任何数据集项目,一定会先花两天时间把采集规范、标注规范、验证集隔离规则全部写进项目文档,再让模型进场。这些“看不见的数据集工程”,决定了模型在现场是表现好,还是只是演示好。希望帮到你。
本文还有配套的精品资源,点击获取