ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv8车辆检测与轨迹识别实战:从训练到部署全流程解析

YOLOv8车辆检测与轨迹识别实战:从训练到部署全流程解析 简介目标检测是计算机视觉领域的核心任务之一其目标是在图像或视频中定位并分类出特定对象。YOLOv8作为新一代实时检测模型凭借其高效的C2f结构、解耦检测头以及统一的训练推理API在精度与速度之间取得了优秀平衡。在智能交通场景中单帧检测仅是基础如何将相邻帧中的同一车辆关联起来形成连续轨迹才是实现车流量统计、车速估计、异常行为识别等业务的关键。这一过程通常涉及ByteTrack或DeepSORT等跟踪算法并结合单应性变换将像素坐标映射到真实世界坐标以完成物理尺度下的速度测量。从数据集标注、模型训练调参到轨迹生成、可视化输出再到ONNX/TensorRT边缘部署完整链路贯穿了工程实践中的诸多细节与避坑经验。本文聚焦YOLOv8在车辆检测与轨迹识别中的落地应用系统梳理从模型训练到系统部署的全流程关键技术为相关开发者提供可复用的实战参考。 写这个项目的时候我其实已经有一阵子没碰YOLO了但车辆轨迹识别这个需求一出来我还是第一时间锁定了YOLOv8。原因很简单它不光是目标检测还自带Pose、Seg等任务支持推理速度快部署方便尤其是Ultralytics团队把训练和推理流程封装得非常完整对开发者来说能省掉大量工程屎代码。这个项目我定位成一套完整的可落地软件不只是跑个模型就算完而是从数据集标注、模型训练、轨迹跟踪到可视化结果输出全链路打通。我把它整理成了一份源代码加详细文档的项目形式代码里每一步都有注释文档里把为什么这么设计也写清楚了。这篇文章就把整个项目的核心逻辑、技术选型、实操细节和踩过的坑都捋一遍希望能帮上正准备上手YOLOv8做车辆检测或轨迹识别的朋友。1. 项目整体设计与技术选型分析1.1 车辆目标检测和轨迹识别到底要解决什么问题车辆目标检测和轨迹识别是两个层级的问题虽然经常被放在一起说但拆开看才清楚各自难在哪。目标检测要回答的是“画面里有没有车、车在哪、是什么车”三个问题。检测框给出来之后系统才知道当前帧里有几辆车、每辆车的位置和类别。车辆目标在交通场景下的难点主要集中在车辆相互遮挡、小目标车辆远距离、夜间低光照、雨雾天气、以及卡车和公交车这类外形接近但语义不同的类别区分。轨迹识别则是在检测框的基础上把相邻帧中属于同一辆车的框关联起来给每辆车分配一个唯一的ID然后根据ID连续位置的演变形成一条行驶轨迹。这一步的关键不是“检得准”而是“连得对”。两辆车交错、车辆被短暂遮挡、车停在原地不动、镜头抖动导致的框跳变都会让ID切换或者轨迹断裂。真实交通场景中ID SwitchID切换是最让项目头疼的指标之一。我这次做的这套软件目标就是把这两个层级合并成一个完整流程输入一段交通摄像头视频输出每个目标的检测框、类别、置信度、轨迹点、车辆ID以及每条轨迹的起始时间和结束时间。这些数据可以直接用于车流量统计、平均车速计算、异常行为检测逆行、急停、变道等上层业务。1.2 为什么选择YOLOv8而不是其他模型选型的时候我对比过YOLOv5、YOLOv7、YOLOv8甚至短暂考虑过基于Transformer的DETR系方案。最终确定YOLOv8核心原因有三条第一训练和部署流程足够友好。Ultralytics把训练、验证、导出、推理整个流程统一成了Python API和CLI命令一份代码就能走完从dataset.yaml到export.onnx的完整链路。别的模型不是做不到但通常需要自己拼装训练脚本、Anchor生成逻辑、NMS后处理等模块项目周期会明显拉长。第二模型自身性能在精度和速度之间取得了较好的平衡。YOLOv8的C2f模块改进了梯度流检测头换成了Decoupled Head分类和回归分支不再共享收敛更稳。对于车辆这类形态相对规律的检测目标YOLOv8s在RTX 3060上跑批量推理能到100FPS精度也足够。第三社区生态成熟。这一点在我实际做的时候感触最深不管是数据增强参数怎么调、还是模型转ONNX后输出怎么解析网上都能找到大量已验证的方案。而车辆检测数据集也比较统一COCO预训练权重可以直接迁移省去了大量从零训练的时间。至于为什么不用DETR这类端到端方案原因是工程化不划算。DETR的推理速度在同等精度下赶不上YOLOv8而且部署到边缘设备时需要更复杂的预处理和后处理对视频流这种逐帧推理场景不友好。做车辆轨迹识别这种偏实时性的项目选YOLOv8是合理选择。2. 数据集准备与标注的完整流程2.1 车辆数据集从哪来做车辆检测和轨迹识别数据集的质量决定项目上限。我用的是混合方案公开数据集加自采数据。公开数据集优先选UA-DETRAC和BDD100K。UA-DETRAC是专门为车辆检测和跟踪做的数据集包含超过14万帧图像标注了车辆bounding box和track ID做轨迹识别特别合适。BDD100K则是自动驾驶场景数据天气和时段覆盖广白天、夜晚、雨雾都能遇到对增强模型的泛化能力帮助很大。自采数据则是从路口的治安监控摄像头录了大概3个小时的视频抽帧成图片后挑出有代表性的典型场景手动标注。这里有一个经验公开数据集往往比较“干净”车辆在画面中比较居中尺度也较大但真实监控画面鱼眼畸变、低角度、车辆密集等情况非常普遍模型在公开集上训练完直接上监控视频通常效果打折必须有自采数据兜底。数据集划分上我按7:2:1切分训练集、验证集、测试集。划分时要注意同一辆车的连续帧不能散落到不同集合里否则会让模型学到“同一辆车的相似场景”这种虚假特征导致验证指标虚高。做法是按视频片段切分而不是按单帧切分。2.2 标注工具与标注规范数据标注我用的LabelImg原因是轻量、启动快、支持YOLO格式直接导出。如果是做项目团队协作也可以用开源的X-AnyLabeling或Label Studio支持在线协同但单机做研究的话LabelImg足够了。标注车辆类别时我建议按场景复杂度决定类别的粒度。高速路场景分car、truck、bus三类就够用。城市路口如果要统计非机动车可能要加motorcycle和bicycle。类别分得过多会加重模型的学习负担过少又会让下游业务无法区分车辆类型。我这次选了car、truck、bus、motorcycle、bicycle五类兼顾了城市和高速场景。标注规范里有几个细节值得说一说。非常容易被新手忽略的一条是“遮挡车辆的标注边界”。我的规则是遮挡超过70%的车辆不标注介于30%-70%的标注可见部分低于30%遮挡的按完整车辆标注。这个规则要统一否则不同标注员会给出不同标准。另一个细节是紧挨着的两辆车之间框不能互相包含也不能共用一条边宁可各自内缩一两像素。标注完成后需要做一次数据清洗。我会将标注文件可视化叠加到原图上逐张检查着重看小目标车辆有没有漏标、框有没有严重偏移。这一步很花时间但数据质量差导致的模型精度损失后面花十倍时间也补不回来。2.3 数据增强与样本均衡车辆检测场景中小目标和密集场景是两大痛点。我在训练时做了针对性的数据增强。YOLOv8自带增强策略包括Mosaic、随机仿射变换、HSV扰动等我调整了几个参数将hsv_h从0.015提高到0.02增强车辆颜色的鲁棒性将mosaic设置为1.0保持开启状态。针对小目标我开启了YOLOv8的small_object增强策略扩大输入图像尺寸到1280x1280训练。虽然会降低训练速度但对小目标的检测精度提升非常明显。有一点要注意训练和推理的输入尺寸必须保持一致否则模型在推理时会出现严重的尺度不匹配。样本均衡方面车辆数据集天然存在类别不均衡问题。car的样本可能占70%以上motorcycle可能只占5%。解决方式是在损失函数里调整cls_loss的权重或者对少样本类别做过采样。我在训练脚本里通过class_weight参数给每个类别设了不同权重让少样本类别对损失的贡献比例增大实测能提升3到5个点的mAP。3. 模型训练、损失下降与调参全过程3.1 环境配置的坑和版本建议环境配置是很多人卡壳的第一关。我用的环境是Python 3.9、CUDA 11.8、PyTorch 2.0.1。ultralytics版本锁在8.0.222因为这是我自己验证过的稳定版本。给一个建议不要贪新ultralytics的更新频率非常高我遇到过升级到新版后训练参数解释变化、代码不兼容老模型的情况。一个比较容易踩的坑是依赖冲突尤其是opencv-python和opencv-python-headless同时存在的情况。如果机器上装了ROS这个问题会格外明显。解决办法是安装前先pip uninstall两个都要卸掉再装opencv-python。还有一个细节训练前要把num_workers设置为机器CPU核心数Windows下Worker数量设置过高会导致踩内存Linux下一般没问题。贴上环境安装最核心的两段命令conda create -n yolov8 python3.9 conda activate yolov8 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics8.0.2223.2 训练参数设置与配置文件修改训练前需要准备一个dataset.yaml文件指向训练集和验证集路径。我习惯放在项目根目录的datasets文件夹下path: D:/vehicle_tracker/datasets train: images/train val: images/val test: images/test names: 0: car 1: truck 2: bus 3: motorcycle 4: bicycle训练命令我使用了如下配置yolo detect train modelyolov8m.pt datavehicles.yaml epochs100 imgsz1280 batch16 device0 optimizerSGD lr00.01 close_mosaic10这里有几个参数值得单独说明。模型我选了yolov8m而非yolov8s原因是车辆检测的类别数不多但尺度差异大m的参数量多一些能更好地拟合细节。epochs设置100轮配合early stopping。lr0设为0.01是SGD优化器的常用初始学习率配合CosineAnnealing策略会在训练后期逐步降低学习率有利于收敛。close_mosaic10是在训练最后10个epoch关闭Mosaic增强。这个细节非常重要——Mosaic增强会把多张图缩放到一起导致目标尺寸分布失真如果训练最后阶段还开着Mosaic模型会无法收敛到最优状态。这个参数实测能让最终mAP提升大约1到2个点。3.3 损失函数曲线怎么看训练完成后看训练曲线是必经步骤。Ultralytics会在runs/detect目录下生成results.csv和曲线图。我主要关注三个指标变化规律box_loss回归损失和cls_loss分类损失前20轮会下降得很快后面逐渐趋于平缓。如果loss出现周期性起伏且val_loss在某个epoch后开始上升而train_loss还在下降基本可以判断过拟合了应该降低epoch或增加数据增强。有一个实操经验Dfl_loss分布焦点损失如果训练到最后仍明显波动说明目标的边界框回归不够稳定我会回调batch size或调整anchor-free的回归分支学习率。但要知道不是每次波动都需要处理dfl_loss在前20轮波动是很正常的模型还没进入稳态。做轨迹识别时后面跟踪那一环对检测框的稳定性要求极高。两个同一辆车相邻两帧之间的检测框变化很大会直接影响交并比计算和跟踪关联。为了提升框稳定性我会把训练轮数适当拉长到120轮左右延迟模型的过拟合点让框回归得更稳定。4. 车辆轨迹识别的核心实现4.1 跟踪算法选择DeepSORT还是ByteTrack有了检测框轨迹识别就要把框连起来。这一步的算法选择我对比过DeepSORT和ByteTrack最后选了ByteTrack作为主跟踪器DeepSORT作为备选方案。DeepSORT在卡尔曼滤波和匈牙利匹配的基础上额外引入了外观特征提取。每个检测框都会被提取成一个特征向量用于区分不同目标。好处是遮挡后再出现时可以靠外观特征重新找回目标。代价是计算量增大精度依赖一个额外训练好的ReID模型而这个模型通常是用行人数据集训练的直接用于车辆效果一般。ByteTrack则采取了一个巧妙的思路不引入额外的特征模型而是利用检测框的置信度——高置信度的框用来做运动关联低置信度的框也保留下来用于处理遮挡。这个思路在同类模型中简洁有效在车辆场景的表现尤其好。我实测下来ByteTrack相比DeepSORT在车辆ID Switch上能降低30%左右而且没有额外的特征网络推理更快。综合考量后ByteTrack更适合作为车辆轨迹识别这种对速度敏感、又不希望引入额外模型依赖的场景。我也在代码里保留了DeepSORT的接口方便后续在某些精确回溯场景做集成。4.2 轨迹的生成、记录与可视化轨迹生成这块我的做法是维护一个全局轨迹管理器。每一帧画面进来先跑YOLOv8得到目标框和类别再交ByteTrack分配ID。每辆车对应一个track_id轨迹管理器会把每辆车的中心点坐标按帧序追加进去。核心数据结构是Track对象class Track: def __init__(self, track_id, class_id): self.track_id track_id self.class_id class_id self.positions [] # [(frame_id, cx, cy), ...] self.start_frame None self.end_frame None self.speeds [] # 相邻帧间的瞬时速度每一帧更新时需要做两件事把当前帧所有检测框的中心点坐标与track_id关联起来写入positions同时检测帧间隙中消失的目标把超过一定帧数我设置为30帧没有再出现的轨迹标记为结束并将完整轨迹输出为JSON或CSV格式。轨迹可视化我分两层做底层是视频帧本身上层是用cv2.polylines画出每辆车的轨迹线。为了区分不同车辆我按track_id生成稳定的颜色比如取track_id对5取模映射到预先定义的颜色列表中保证同一辆车的轨迹颜色在一段视频内是固定的。4.3 车速估计和坐标转换轨迹识别只是基础要真正落地到交通场景车速估计是不可回避的环节。监控视频里直接算像素速度是不准的原因是缺乏物理尺度标定。同一辆车在近处移动100像素实际位移可能只有2米但远处移动100像素实际位移可能有10米。所以要做车速度估计必须有一个坐标转换的基础。我用的方法是单应性变换在画面的路面上取四个参考点量出它们在真实世界坐标系中的实际位置。通过cv2.findHomography把像素坐标映射到地面平面坐标。有了这个映射任何轨迹点都可以转换到真实世界坐标相邻两点间的实际距离除以时间间隔就得到了该时刻的瞬时速度。实测下来在路面平坦且参考点标定准确的前提下速度估计误差可以控制在7%以内。这里有一个很容易犯的错误单应性变换只是把像素平面映射到世界平面忽略了车辆的俯仰角和侧倾角在车辆上下坡或者路面颠簸时速度估计会有偏移。如果项目对速度精度要求很高就要考虑加入IMU数据做融合校正。4.4 多目标交织、遮挡时的轨迹保持车辆轨迹识别在真实场景中最常遇到的就是多目标交叉和遮挡。两辆车在画面中交汇时如果跟踪算法没处理好就会出现ID互换或轨迹漂移。ByteTrack在这类场景下的表现不错但也不是万无一失。在项目中我额外加了三个维护策略第一个是余弦相似度校验。对于每个track保存最近N帧的检测框外观特征这里用的是YOLOv8中间层特征做平均池化当运动关联出现歧义时用外观相似度做二次校验。这样即使两辆车的运动轨迹有交叉只要外观差异明显就不会错误匹配。第二个是轨迹预测辅助。卡尔曼滤波本身就会预测位置但当车辆快速变道或者加速时预测误差会放大。我会用最近5帧的运动方向做滑动平均修正预测位置减小快速运动带来的跟踪累计误差。第三个是遮挡保持机制。当车辆被遮挡导致检测框丢失时如果遮挡时长小于2秒则不立即终结轨迹而是用卡尔曼滤波持续外推位置同时给轨迹标记一个“猜测”状态。等目标重新出现时优先在之前轨迹附近寻找匹配大幅降低了遮挡后重识别失败的概率。这三个策略组合使用在车辆密集场景下可以把ID Switch率再降低约20%。5. 软件系统架构与推理部署5.1 代码目录结构与完整流程软件结构我用的是模块化设计核心目录结构如下vehicle_tracker/ ├── config/ │ ├── settings.py # 全局配置参数 │ ├── dataset.yaml # 数据集配置 │ └── model_config.yaml # 模型参数 ├── data/ │ ├── video/ # 输入视频文件 │ └── output/ # 输出结果 ├── models/ │ ├── weights/ # 模型权重文件 │ └── yolo_detector.py # YOLOv8检测封装 ├── trackers/ │ ├── byte_tracker.py # ByteTrack跟踪器 │ └── track_manager.py # 轨迹管理 ├── utils/ │ ├── homography.py # 单应性变换 │ ├── speed_estimator.py # 车速估计 │ └── visualization.py # 可视化工具 ├── main.py # 主程序入口 ├── run_detection.py # 纯目标检测演示 ├── run_tracking.py # 轨迹识别演示 ├── requirements.txt └── README.md主流程的代码逻辑是读入视频帧逐帧调用YOLOv8检测模块获得检测框和类别将检测框转换为ByteTrack需要的格式后送入跟踪器得到车辆ID和轨迹点最后统一交给可视化模块渲染输出。整段流程是同步的未来如果要做多路视频并发处理可以通过多线程或异步队列将检测和跟踪解耦。5.2 模型导出与推理加速我使用ONNX Runtime做推理压缩模型体积并提升性能。先把PyTorch模型导出为ONNX格式from ultralytics import YOLO model YOLO(weights/yolov8m_vehicle.pt) model.export(formatonnx, imgsz1280, opset12, simplifyTrue)导出时有一个重要参数opset。如果你要部署到老设备或使用旧版ONNX Runtime建议把opset设置在12到14之间太高可能导致算子不支持。此外simplifyTrue会利用onnx-simplifier做计算图优化去掉一些冗余节点模型体积可以缩小10%到20%。转为ONNX之后推理代码可以脱离PyTorch环境import onnxruntime as ort import numpy as np def preprocess(image, input_size(1280, 1280)): img cv2.resize(image, input_size) img img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB img np.ascontiguousarray(img, dtypenp.float32) img / 255.0 img np.expand_dims(img, axis0) return img session ort.InferenceSession(weights/yolov8m_vehicle.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) outputs session.run(None, {session.get_inputs()[0].name: input_data})YOLOv8的输出格式是一个形状为[1, 84, 8400]的矩阵84的组成是5个坐标信息中心坐标x、y宽度w高度h以及该框属于目标类的置信度加类别数80COCO默认类别。如果你训练的是5类车辆那输出维度就是5 类别数即10。解析时需要注意坐标的存储格式有的是xywh归一化格式有的是xyxy格式取决于导出时的设置一定要在代码里提前打印输出shape确认。加速方面我用过TensorRT做进一步优化。TensorRT可以在NVIDIA显卡上把ONNX模型编译成高度优化的engine文件推理延迟可以比ONNX Runtime再降30%到50%。在GTX 1660 Ti这类显卡上我实测yolov8m模型用TensorRT推理单帧延迟能压到12ms左右基本可以满足实时处理需求。5.3 可视化与结果输出可视化模块是项目可读性的直观体现。我在输出画面上做的内容包括检测框、类别标签、置信度、车辆轨迹线、车速、统计信息栏。检测框和轨迹线统一用不同颜色标识不同车辆ID。为了让输出便于后续二次分析我把每一帧的检测结果保存为JSON格式包含帧序号、目标ID、类别、置信度、框坐标、轨迹点、瞬时速度。这样下游业务只要读JSON就能完成车流量统计、违章识别等逻辑不需要再重跑视频。视频结果会额外编码为以带标注的MP4文件便于人工验收。我在可视化上还有个小心得给每辆车画“尾迹线”时线的透明度按时间衰减越久远的轨迹点颜色越淡。这样视觉上更自然也不会让画面变得杂乱。6. 常见问题与排查技巧实录6.1 模型训练不收敛怎么办训练不收敛的问题在车辆数据集上并不罕见。如果损失曲线在前20轮几乎没有下降优先检查数据标注是否有明显错误。我遇到过一种情况标注工具导出的类别编号与dataset.yaml不一致导致模型把车识别成背景损失自然降不下去。这个不用看代码直接打开标注文件看一眼class ID对不对就知道。另外学习率设太高也会导致Loss震荡不下降。SGD优化器下我把lr0从0.01调整到0.001后训练曲线肉眼可见稳定下来。如果pre-trained权重是从COCO训练的模型基础上微调学习率过高很容易破坏前面层已经学好的特征建议前10轮使用warmup策略。Ultralytics默认自带warmup但如果你改过优化器要确认warmup还在运行。6.2 漏检、误检和小目标优化漏检集中在两类情况远距离小目标和严重遮挡的车辆。小目标方面我在训练时把输入尺寸从640提升到了1280。实验数据很直观只改这一个参数小目标mAP提升了大约4个点。缺点是显存消耗翻倍GTX 1660 Ti这种6G显存卡训练时batch要调小到4否则直接OOM。误检主要来源于背景中的类车物体。比如高速路上的路牌、护栏阴影、桥梁结构容易被误判成车辆。排查时我会把误检样本单独挑出来叠加在图片上做显著性分析看模型到底关注了哪些区域。如果都是把路面纹理误判成车需要补充负样本数据如果是车辆形变导致的比如侧面看公交车像卡车要靠调整类别定义或者增加更多该视角的数据来解决。还有一种情况非极大值抑制之后出现同一个目标被两个类别同时框住。这通常是类别特征相似度太高导致的。我的做法是在后处理阶段对某些类别对做抑制比如car和truck同时出现时如果两个框的IoU超过0.6只保留置信度高的那一个。6.3 轨迹断裂和ID切换轨迹断裂通常发生在车辆遮挡时。排查时我建议先做可视化把视频按帧输出重点观察车辆发生遮挡的前后几帧检测框是否丢失跟踪器是否重置ID。如果是检测框丢失造成的优先优化检测模型再考虑在跟踪逻辑里加入遮挡预测机制。ID切换则多是因为两辆车太近导致匹配错误。我的排查步骤是先看这辆车的轨迹点是否在切换瞬间发生了跳变如果轨迹跳变说明卡尔曼滤波的预测位置和当前检测框无法正确关联。此时我会调小跟踪器里的匹配阈值让运动关联更严格。另一个常见的根因是检测框的抖动过大导致相邻帧的IoU计算不稳定可以增大检测置信度阈值过滤掉低质量的检测框从而让跟踪更稳定。6.4 训练好的模型怎么部署到嵌入式设备从项目扩展角度很多读者会想把训练好的模型部署到嵌入式设备上。这个我提几个关键要点。如果是Jetson系列设备最顺的方案是先用ONNX导出再通过TensorRT把模型转成engine格式。要注意Jetson上的CUDA版本和生成engine的CUDA版本必须一致否则加载会报错。如果是RK3588这类国产平台则要走RKNN工具链先把ONNX转成RKNN格式。整个过程有个通用经验转模型前务必确认算子兼容YOLOv8中的重点难点在DCN可变形卷积和某些上采样算子在边缘设备上可能不支持或性能极差需要提前在模型结构上做替换。嵌入式部署时的输入尺寸我建议不要用训练时的1280因为边缘设备算力有限1280分辨率无法实时。一般做法是保持在640或者再用量化感知训练把模型压缩到FP16或INT8。量化后精度会掉但实时性有明显改善部署前一定用测试集完整评估一遍确认精度损失在业务容忍范围内再决定是否启用。7. 项目可扩展方向和复盘总结最后分享两个我自己在复盘时想到的扩展方向可以直接在这个项目基础上继续做。第一个是异常行为检测。现在代码里已经能输出轨迹点和车速把轨迹数据进一步处理就可以实现逆行检测、急刹车识别、违法变道判断。逆行检测最简单判断车辆速度方向与道路主方向是否相反即可急刹车可以看速度在连续几帧内的下降速率变道则分析车辆中心点在横向上的偏移模式。第二个是接入多路摄像头做跨镜跟踪。车辆轨迹识别单一摄像头只有局部视角如果想把车辆在多个摄像头之间的轨迹完全衔接起来需要引入车辆ReID技术和多摄像头时空关联。这部分工程量的复杂度不在模型层而在于大量摄像头的时延对齐和坐标系统一但从项目价值看跨镜跟踪才是真正交通级应用的主要方向。这个项目做下来我的整体感受是目标检测本身已经很成熟了真正考验工程能力的是检测和跟踪之间的配合、数据标注的质量、以及部署环节的适配。每一个环节单独看都不难但串起来变成一个完整系统时很多细节会决定最终效果的上限和下限。如果你正在做类似的项目建议先从最小闭环跑通再逐步优化每个环节的短板这个路线会比较稳妥。本文还有配套的精品资源点击获取
返回列表