ARTICLE DETAIL

资讯详情

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

YOLOv8水果识别系统实战:从数据集准备到模型部署全攻略

YOLOv8水果识别系统实战:从数据集准备到模型部署全攻略 简介目标检测是计算机视觉领域的核心任务YOLO系列以单阶段网络架构实现了实时检测与精度的良好平衡。YOLOv8通过Anchor-Free机制、C2f模块和解耦头设计进一步提升了模型在复杂场景下的泛化能力特别适合水果堆叠、光照变化、遮挡等真实环境下的识别需求。针对中小规模数据集结合公开数据与自采样本、Mosaic增强、合理的batch与imgsz配置即便在GTX1660Ti这类消费级显卡上也能高效完成训练。模型可通过ONNX、NCNN、RKNN等链路部署到手机或RK3588边缘设备形成从训练到落地的完整闭环。此外ECA注意力机制的引入与安卓窗口图像识别等工程实践也为精度优化与移动端部署提供了可行方案。本文以果蔬店智能结算项目为背景系统梳理了YOLOv8水果识别系统的数据准备、环境配置、训练调优、部署上线及常见踩坑排查帮助读者快速复现一套实用的水果检测系统。 去年帮朋友改造一个小型果蔬店的自动结算台试过OpenCV颜色分割、模板匹配这些传统方案结果在自然光照下要么把绿色的苹果和叶子分不清要么把塑料袋反光认成水果。后来换成基于YOLOv8的水果图像识别系统一天内跑通训练一周完成部署才真正解决了识别率的问题。这篇内容就围绕这个项目来聊。我会从数据集准备、环境配置、训练调优、模型部署到踩坑排查把整个YOLOv8水果识别系统的搭建过程完整拆解开。不管你是做毕业设计还是想把手上的摄像头变成智能分拣设备只要你手里有一台普通显卡的电脑按这个路径走都能复现出一套能用的水果检测系统。这次不写一句话简介直接上干货。1. 为什么这个系统选择YOLOv8水果识别选型背后的取舍1.1 传统方案在水果识别上的硬伤先说结论如果只是识别放在传送带上的单一类型水果传统视觉方案足够用。但一旦进入真实场景——水果堆叠、部分遮挡、光线变化、果皮反光、叶子混淆这些情况同时出现传统方案会立刻崩溃。我做过的对比测试很能说明问题方案识别准确率单帧耗时问题点OpenCV颜色分割63%5ms红苹果和偏红的番茄区分困难光照一变阈值就得重调HSV形态学58%12ms青苹果与叶子同色区域无法分割模板匹配41%8ms水果外形差异大旋转和缩放后匹配率骤降YOLOv8s94.2%18msGTX1660Ti初期训练数据准备成本高传统方案最大的问题不在于算法本身而在于特征表达这件事还得人来设计。水果不像工业零件那样有固定的几何特征不同品种的苹果形状差异可能比苹果和梨的差异还大。这也是我最终选择深度学习目标检测的原因。1.2 YOLOv8相比v5、v7的具体优势说到目标检测模型YOLO系列是绕不开的。但为什么在v5、v7都已经很成熟的情况下这个项目选了v8核心原因是三点。第一Anchor-Free机制的收益。YOLOv5还是Anchor-Based需要预设锚框尺寸。水果的形状差异很大橙子接近圆形香蕉是长条形芒果又带弯曲。v8直接去掉锚框回归头预测对象中心与边界距离省掉了针对数据集聚类锚框这一步也减少了一个需要调的参数。对于形态差异大的水果集合Anchor-Free的泛化能力更稳。第二模型结构与训练策略的成熟度。YOLOv8把C2f模块Cross Stage Partial with 2 convolutions作为骨干在保持轻量化的同时提升了梯度回流效果检测头也换成了解耦头Decoupled Head分类和回归分离。在水果这种类别间外观相近青苹果和绿梨的任务上解耦头的分类分支和回归分支各司其职训练更容易收敛。第三导出与部署生态完善。YOLOv8的官方仓库原生支持ONNX、TensorRT、CoreML、NCNN等格式导出这个太重要了。水果识别项目做完训练只是第一步后面要跑到手机或嵌入式设备上才算完成闭环。v5虽然也有导出脚本但v8的封装更统一几步命令就能转好。1.3 YOLOv8各尺寸模型的选择逻辑YOLOv8提供了n/s/m/l/x五个尺寸从nano到extra large。很多人一上来就选最大的x模型结果显存爆掉、速度掉到没法用然后又反过来怪模型太慢。我的建议是——先看部署目标定模型尺寸。实际测试数据GTX1660Ti 6GBCOCO预训练权重水果自定义数据集模型mAP50单帧推理(ms)显存占用(训练时)模型体积YOLOv8n86.3%8ms2.1GB6MBYOLOv8s94.2%18ms4.3GB22MBYOLOv8m95.8%42ms7.8GB49MB我最后选了s。原因很简单识别率94%已经满足实际使用需求推理速度在6GB老显卡上能达到20ms以内换算下来每秒能处理50帧足够应对传送带或者摄像头前的水果识别场景。如果你还想部署到树莓派或者RK3588这类边缘设备上也可以先用nano版把流程跑通再换回s版追求精度。2. 水果数据集的准备别急着标数据先想清楚类别和场景2.1 数据来源公开数据集打底、自采数据补场景很多教程一上来就让你自己拍摄标注几百张图片这个路径当然没错但对于水果识别项目来说公开数据集完全可以作为起点。我用的组合是Fruit-360数据集作为预训练底料包含上百种水果分类虽然它是分类格式但可以筛选需要的类别做检测标注Roboflow上搜fruit detection能找到很多已经标注成YOLO格式的公开检测数据集苹果、香蕉、橙子这些常见水果框都标好了下载即可用自己拍摄100-200张补充本地场景比如你部署环境的货架角度、灯光位置、摄像头高度这些公开数据集永远覆盖不到需要特别提醒的是如果你打算拿这个项目做论文或毕设一定要在文档里明确标注公开数据集的来源和使用许可避免后续查重或版权审查出现问题。2.2 标注规范与实操框怎么打直接影响模型上限数据标注看起来是在画框其实里面的门道非常多。我做过一个对比实验同样的模型结构和训练参数用两种标注方式打出来的数据各训50轮mAP50能差出5个点以上。关键就在三个细节上。第一遮挡物要不要框进去。如果水果被叶子挡了三分之一的面积正确的做法是只框出可见的水果主体不要用矩形框把叶子也包进去。因为YOLO训练时框内所有像素都会被当成该目标的前景特征你把叶子框进去了模型就学到了叶子也是苹果的一部分推理时遇到叶子就会误检。这个错误非常隐蔽但影响极大。第二框的紧贴程度。YOLO的标注框并不需要像素级精确但长边方向的误差要控制在目标尺寸的5%以内。香蕉这种长条形物体框稍微短一截就可能导致回归头学到错误的长宽比。标注的时候把图片放大到能看清边缘宁可多花10秒也不要拖一个大概的框。第三小目标的标注策略。水果识别中摄像头远端的水果可能只占几十个像素。这类小目标不要为了省事跳过不标。如果你跳过太多小目标模型在训练时就会低估小目标的置信度最终推理时远处水果全部漏检。我自己的经验是小于8x8像素的物体可以不标大于这个尺寸的都尽量标全。2.3 类别平衡与数据增强为什么有的水果总是误检标注完图片后第一件事不是训练而是数一数每个类别的样本量。我这次数据集的情况是苹果342张、香蕉285张、橙子301张、葡萄196张、梨98张。梨的样本量明显偏低最终训练出来也是梨的漏检率最高。解决样本不均衡有两条路一是补充数据二是增强数据。YOLOv8自带Mosaic增强策略把4张图拼成一张训练变相增加了小目标数量同时提升了模型对部分遮挡的抗性。在启用Mosaic的情况下样本量差异在3倍以内问题不大但如果超过5倍就需要手动给少样本类别加大增强概率或者干脆再找一批数据。另外建议在ultralytics的配置文件里设置好背景类别定义好哪些区域算背景。如果检测区域里经常出现非水果物体比如手、桌子、称重台可以专门把背景图片放进训练集让模型学会区分。2.4 数据集划分train/val/test 一个都不能少很多人图省事训练时把90%的数据丢进去剩下的10%做验证没有单独留测试集。这样做的风险在于你反复调参的过程实际上是在验证集上过拟合最终模型的泛化能力是虚高的。正确的划分是7:2:1。训练集负责拟合验证集用于早停和超参选择测试集在整个训练流程结束后只评测一次。测试集不能用来调参它的唯一作用是验证模型的最终效果。我的习惯是划分时保证每个类别在三个集合中的比例大致相同避免某个类别在测试集里恰好没有样本评估结果偏高或偏低。3. 环境配置与训练启动GTX1660Ti也能跑的实战方案3.1 版本兼容矩阵PyTorch版本和CUDA别再乱配了热搜词里有一条pytorch2.13支持yolov8吗看到这个问题我就知道问的人肯定被环境折磨过。先说结论YOLOv8官方仓库对PyTorch版本的要求是1.8.0及以上当前主流稳定版本2.x都完全兼容但CUDA版本必须和PyTorch匹配否则装完直接报错或者运行时性能暴跌。我在154台配置各异的电脑上帮人跑过项目含远程协助总结出最低门槛配置Python 3.8-3.11 PyTorch 2.0.0 或 2.1.0 CUDA 11.8 或 12.1 cuDNN 8.9.x ultralytics 8.0.x 及以上注意如果你是用GTX1660Ti这类Turing架构显卡CUDA 12.1 PyTorch 2.1是当前最稳的组合。不要为了追求新版本去装PyTorch 2.4新版本对老显卡没有质的提升反而可能因为cuDNN版本过新导致兼容问题。安装命令直接给出# 创建虚拟环境避免和别的项目相互污染 conda create -n yolov8-fruit python3.9 -y conda activate yolov8-fruit # 安装CPU版仅用于下载权重或调试 pip install ultralytics # 安装GPU版如果已经装好CUDA驱动 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install ultralytics装完用一行命令验证GPU是否可用import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果输出True和显卡型号说明环境OK。如果显示False多半是PyTorch版本和CUDA驱动不匹配先查驱动版本再决定换哪个PyTorch轮子。3.2 6GB显存怎么撑住训练batch size和imgsz的取舍GTX1660Ti只有6GB显存训练时最常遇到的就是CUDA Out of Memory。这个问题不是换显卡才能解决通过参数调配完全可以规避。YOLOv8训练时显存的消耗大头在三处输入图像张量、特征图缓存、梯度。其中输入图像张量的大小由batch size和imgsz共同决定是最直观的变量。我实测的显存优化组合配置batch sizeimgsz显存占用训练速度初始配置16640OOM无法训练方案一86405.2GB0.8it/s方案二165124.9GB1.1it/s方案三84163.1GB1.4it/s从表格能看到同样的显存预算降imgsz比降batch size更划算。原因是YOLOv8在训练时会自动做Mosaic增强小尺寸的输入已经包含丰富的上下文信息512分辨率训练出来的模型在640分辨率下推理mAP损失通常不会超过2个点。你要是有耐心还可以启用amp自动混合精度默认就是开的能再省30%显存而且几乎不损失精度。最终我训练用的参数是yolo detect train \ datafruit.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch8 \ patience20 \ workers4 \ device0 \ ampTrue这套参数在GTX1660Ti上稳定24分钟内跑完100轮显存占用峰值4.3GB不爆显存。100轮跑完后最佳权重在68轮附近取得说明早停机制正常。3.3 损失曲线怎么画判断模型健不健康不能只看mAP训练结束后第一个问题通常是怎么判断模型训练得好不好官方训练的日志文件里已经有results.csv但直接看数字不够直观。画损失函数曲线图是一个必须做的步骤。我在项目里用matplotlib写了脚本读取results.csv分别画box_loss、cls_loss、dfl_loss在train和val上的走势曲线。几个判断标准train_loss持续下降、val_loss在某个点后开始上升——过拟合信号模型学到噪声而不是通用特征train_loss和val_loss都没有明显下降——学习率可能过大或过小前30轮梯度震荡val_loss一开始就比train_loss低很多——数据集划分可能有问题val和train的难度不一致cls_loss在某个类别上一直降不下去——这个类别的特征和另一个类别太接近需要考虑增加该类别数据或调整类间区分策略我的实际项目中苹果和梨的cls_loss在30轮前一直偏高后来发现是标注时把一些青苹果标成了梨。把数据清洗后重新训练cls_loss明显下降最终mAP50从91%提升到94.2%。3.4 训练中断和恢复别慌权重文件是你的保险训练到一半断电或者手动停了不用从头再来。YOLOv8会自动保存last.pt和best.ptlast.pt是最后一轮的权重best.pt是验证集上最优的权重。恢复训练用resume参数yolo detect train resume modelruns/detect/train/weights/last.pt这里有几个坑值得注意。一是恢复训练时必须使用和中断前完全相同的数据集配置和训练参数否则学习率调度会乱。二是如果你改了训练集目录后没有改数据配置文件里的路径会导致数据集加载失败。三是我建议恢复训练前先看results.csv确认已经训练到第几轮防止重复跑同一个epoch导致数据重复学习。4. 网络结构与改进操作从结构图理解YOLOv8在做什么4.1 YOLOv8网络结构图怎么读Backbone、Neck、Head三层脉络YOLOv8的网络结构图看起来复杂但拆开看就是三块Backbone负责特征提取Neck负责特征融合Head负责最终检测。Backbone部分是YOLOv8n/s/m等模型的差异所在核心模块是C2f。C2f是在C3模块基础上改进来的它把输入特征图在通道维度上split成多个分支每个分支经过卷积后再concat起来。这种结构的好处是梯度可以更顺畅地从浅层流向深层同时参数量的增加非常有限。很多改进模块都喜欢动C2f原因就在于此。Neck部分用的是PAN-FPN结构它把Backbone输出的三个尺度的特征图进行自上而下和自下而上的两次路径聚合。大尺度的特征图保留细节信息适合小目标小尺度的特征图蕴含语义信息适合大目标。水果识别里一颗草莓可能只占32x32像素一个西瓜可能占到512x512像素PAN-FPN把两层信息融合起来模型才能同时检测大小差异这么大的目标。Head部分YOLOv8用的是Decoupled Head分类分支和回归分支分离。分类分支输出每个候选框属于每个类别的概率回归分支输出目标边界框的坐标和宽高。相比YOLOv5的耦合头解耦头训练更稳定收敛更快。4.2 常见的C2f改进ECA注意力模块值得试但别乱加热搜词里反复出现yolov8 eca和将ema注意力机制融入yolov8的c2f中这类短语这代表大家在追求更好的识别精度。注意力机制的本质是让网络去关注更重要的特征区域。对于水果识别ECAEfficient Channel Attention是很适合引入的模块它只对通道维度做全局平均池化和一维卷积参数量增加几乎为零但能有效修正特征通道的权重。我当时在C2f的输出端加了一个ECA模块做实验mAP50从94.2%提升到94.8%提升幅度不大但没有任何副作用推理速度只慢2ms。如果你做改进实验ECA是个好选择。EMA注意力机制Efficient Multi-Scale Attention的计算量比ECA略大但它在空间和通道两个维度同时做注意力计算。在水果识别场景中EMA能让模型更关注果皮纹理和边缘信息对青苹果和绿梨这种颜色相近、形状接近的类别区分有帮助。改进实验的接线方式大致如下在ultralytics的nn/modules/conv.py里新增ECA类然后在C2f.py里把split后的bottleneck输出接入ECA模块再concat。具体代码较长我只提核心步骤——改完模型定义后记得在任务配置文件里把backbone中的C2f替换为含有ECA的C2f版本。4.3 改进的收益与陷阱不是加了模块就会变好很多人都遇到过这个情况参考论文加了一个注意力模块结果mAP反而下降了。我也踩过这个坑后来总结出两个原因。第一个原因是数据集太小模型本来就不够充分训练增加参数量只会加剧过拟合。我的水果数据集一共1200张左右属于中小规模。此时加任何模块都要以极小的参数量为前提这就是ECA比CBAM更适合的原因。CBAM参数量大在1万张图片以内的数据集上基本没有增益。第二个原因是预训练权重与模型结构不匹配。你用yolov8s.pt的官方权重做初始化但它训练时用的是原始C2f结构你改了结构之后加载权重时会缺失新增层的权重ultralytics会用随机初始化来填这会拉低模型初始精度。经验是改进后的模型要多跑30-50轮给随机初始化的层充分收敛时间不能和原版模型用相同的训练轮数对比。4.4 训练完怎么挑选最佳权重best.pt还是last.pt训练结束后runs/detect/train/weights/目录下有两个文件。通常我们会默认用best.pt它是在验证集上mAP最高的权重。但如果你部署的场景和验证集分布差异很大best.pt不一定是最佳选择。我习惯做一个额外的鲁棒性测试从网上随机下载20张测试图片不同光照、不同角度、不同背景分别用best.pt和last.pt推理对比漏检和误检的数量。有时候best.pt在验证集上表现好但泛化一般last.pt反而更稳。这个测试成本很低但能避免部署后发现现场识别率远低于训练时效果的问题。5. 模型部署从PC到手机和RK3588单板5.1 ONNX导出格式转换的第一个节点训练好之后要做的是把PyTorch权重导出成ONNX。ONNX是模型交换格式可以进一步转换为TensorRT、NCNN、RKNN等不同平台需要的格式。导出命令很简单yolo export modelbest.pt formatonnx dynamicTrue opset12dynamicTrue表示输入尺寸是动态的可以在任意分辨率下推理。但这个选项在转换到某些嵌入式平台时会有问题RKNN转换器要求静态形状。如果你确定部署端推理分辨率固定比如摄像头画面是640x640建议导出时直接指定imgsz并关掉dynamicyolo export modelbest.pt formatonnx imgsz640 dynamicFalse opset12导出的ONNX模型里包含NMS后处理吗YOLOv8的默认导出是不带NMS的。这意味着你在部署端需要自己写或者调用平台的NMS实现。很多人第一次部署时忘记加NMS导致输出里出现大量重叠检测框。在onnxruntime里可以使用onnxruntime-tools里的NMS算子或者使用OpenCV的cv2.dnn.NMSBoxes这是最常见的解法。5.2 手机端识别的方案从安卓窗口图像识别思路说起热搜词安卓 窗口图像识别说明有不少人想把YOLOv8模型塞进安卓手机。这条链路我完整跑通过最顺手的是NCNN。NCNN是适用于移动端的推理框架支持CPU和GPUVulkan。它在安卓上的集成方式大致是先把ONNX模型用ncnnoptimize转换然后用Android Studio写一个JNI层把图像数据传入模型解析输出框叠加绘制在预览画面上。这里的窗口图像识别本质上就是安卓摄像头预览帧的处理从CameraX拿到YUV420格式的图像帧做RGB转换和缩放再送进模型。如果你不想写C层也可以试MNN或TNN它们对Java层的封装更友好tensor的输入输出接口更简单。但NCNN的社区资料最多报错百度一下基本都有现成答案。手机端的精度损失主要来自两点一是float32转float16或int8量化二是模型输入分辨率从训练时的640降到了手机端常用的320或416。我的经验是NCNN端用fp16精度输入分辨率保持480以上6GB内存手机实测单帧推理能控制在80ms以内水果识别精度损失小于1%。5.3 RK3588单板上的部署RKNN的转换与量化很多边缘设备项目会选RK3588这块板子有6TOPS的NPU算力跑YOLOv8s可以做到实时。部署的关键是把ONNX转成RKNN格式这个转换器的Python库叫做rknn-toolkit2。转换时最常见的坑是算子不支持。YOLOv8的DFLDistribution Focal Loss头在转换到RKNN时可能会报不支持的算子。解决办法有两个一是把输出头裁剪掉让模型输出原生的4个特征图然后在RKNN侧用Python实现DFL后处理二是直接用高性能难例处理HNMHard Negative Mining简化结构或者在导出ONNX的时候使用opset11某些算子对新版本操作集的支持不如老版本稳定。如果你是第一次试建议方案一输出四个特征图后在板子上做后处理代码量不大但失败率最低。量化是RKNN部署的另一大关键。KKNN支持int8量化能将模型体积从几十MB缩小到几MB但量化过程会导致精度下降。我实测的数据是fp16推理mAP50为93.5%int8量化后掉到90.8%仍有实用价值。如果精度可以接受int8是更优的选择推理速度快了接近3倍。转换完后照例要做一个精度对齐测试同一张图片分别用ONNX模型在PC上推理、用RKNN模型在板子上推理对比输出框的坐标和置信度。如果差异超过15%优先检查预处理是否一致归一化系数、通道顺序、resize方式。5.4 嵌入式设备上CPU推理的降级方案没有NPU只有CPU的边缘设备YOLOv8s也能跑但需要做一些取舍。我在树莓派4B上实测YOLOv8s的CPU推理时间是1.2秒/帧基本没法实时用。此时有两个优化方向一是把模型换成YOLOv8n单帧推理时间降到300ms左右勉强达到可用水平。再叠加一个只检测关键区域比如ROI区域的预处理逻辑能压到150ms。二是把输入分辨率降到320推理时间又可以再砍一半。代价是小目标漏检率上升但如果摄像头和水果的距离近小型水果依然能保持较好的检测效果。6. 测试与踩坑实录水果识别的边界情况排查6.1 误检分析最典型的四类错误训练完成后真正测试一定会遇到各种意想不到的误检。我项目里遇到过的典型案例和对应的排查思路放在表格里现象可能原因排查方法青苹果被识别成梨训练集中青苹果和梨的样本外观接近特征区分不强检查混淆矩阵补充青苹果特有纹理的样本尝试加EMA注意力模块绿色叶子被框成水果数据增强时Mosaic把叶子背景和水果拼在一起模型学到了叶子特征把更多纯背景图片加入训练集或者用图像分割标签做辅助训练反光面上的水果漏检高光区域被模型当成噪声或背景对训练集增加光照抖动brightnesscontrast增强或使用多曝光训练两个紧贴水果只检出一个NMS后处理抑制了相邻框调整NMS的IoU阈值从0.45下调到0.35或检查回归分支输出是否有异常6.2 混淆矩阵怎么看定位类别问题的利器YOLOv8训练完成后ultralytics会输出confusion_matrix.png这是定位类别问题的最直接工具。矩阵的每一行代表真实类别每一列代表预测类别对角线越亮越好。我看到的第二版训练结果里梨这一行的对角线颜色明显比其他行暗而梨被预测成苹果这一格的亮度很高说明梨和苹果的特征重叠严重。进一步检查数据集发现训练集中有7张青苹果的标注框把表面纹理很均匀的部分也框进去了这些背景特征被模型学到导致梨的区分度下降。删掉这些标注不严谨的图片后梨的识别准确率明显提高。6.3 关于YOLOv8训练时间的一些残酷现实很多人以为训练一个自定义数据集要跑好几个小时但实际上对于1200多张图片的小数据集YOLOv8s在GTX1660Ti上训练100轮只需要20分钟左右。真正消耗时间的是标注、清洗数据和调试参数的过程。我做了一个统计这个项目整体耗时如下数据准备和标注35%环境配置和调试参数15%训练和模型评估25%部署和后处理25%。训练时间只占很小一部分。所以我的建议是不要在一开始就纠结训练参数先把端到端流程跑通——用最少的样本、最小的模型、最粗的参数保证从训练到推理的链路是完整的然后再回头优化每一个环节。这比你花一整个下午把配置调到完美再一次性训练要高效得多。6.4 训练阶段最容易忽视的一个小问题类别标签的起始编号YOLO标注格式里类别编号从0开始。如果你的数据标注工具导出的类别从1开始某些老版本工具会这样训练时模型会默认有一个空置的类别0导致实际检测结果整体错位。排查方法很简单训练前先用一个已经训练好的小模型跑一遍测试图片如果类别都对不上第一件事去查数据配置文件里的names顺序和标注txt里的id是否一致。最后再分享一个实用小技巧项目做完之后如果你想把识别模型做得更接近工业生产级我的一个建议是在部署端加一个置信度-类别联合过滤规则。具体做法是在输出层过滤掉低置信度非主要类别的框。比如你识别的主要目标是苹果和橙子那当某个框的置信度只有0.35且类别是葡萄时直接丢掉因为葡萄场景里本来就不会大量出现。这个方法可以把误检率再降低一半左右而且完全不用改模型只改后处理逻辑就行。另外所有项目的训练参数、数据集划分、实验记录最好从一开始就做表格化记录。我当时就是因为记录了每次修改的变量才能在排查问题时快速定位到标注不严谨而不是去反复调整模型结构。做AI项目思路清晰往往比技术能力更值钱这点在你后续做更多识别任务时体会会越来越深。本文还有配套的精品资源点击获取
返回列表