基于ViT和YOLOv5的多模态目标识别系统让AI“看得更准认得更多”你有没有遇到过这种情况用手机拍一张公园的照片AI能识别出“树”和“人”但具体是什么树、人在做什么它就说不清楚了。或者在监控画面里系统能框出“车辆”却分不清是轿车、卡车还是自行车。这就是传统单一模型在复杂场景下的局限。它们要么像YOLOv5这样擅长快速定位物体在哪里目标检测但对物体具体是什么细粒度分类可能不够精确要么像ViT这样能对整张图进行非常细致的分类但无法告诉你画面里每个物体具体在哪个位置。今天我想跟你分享一个我们实际搭建和测试过的方案把ViT的图像分类能力和YOLOv5的目标检测能力结合起来构建一个多模态识别系统。简单说就是让两个AI模型“联手干活”一个负责“找东西”一个负责“认东西”最终实现112的效果。下面我就带你看看这个系统在实际场景中到底有多厉害以及我们是怎么把它搭起来的。1. 为什么需要“多模态”单一模型的瓶颈在深入效果展示之前我们先花几分钟聊聊背景。理解“为什么”才能更好地欣赏“怎么做”和“结果如何”。想象一下你让一个朋友描述一张家庭聚餐的照片。朋友A只擅长定位可能会说“这里有个东西那里也有个东西那边还有一堆东西。”——这就像YOLOv5能快速框出物体位置但细节模糊。朋友B只擅长描述可能会说“这张图是关于‘家庭聚餐’的氛围很温馨。”——这就像ViT能对图像整体给出一个高级、抽象的标签但无法指出具体哪个物体在哪。而我们想要的是一个既能指出“餐桌在这里爸爸坐在左边妈妈在右边”又能说出“桌上摆的是烤鸡旁边那瓶是红酒”的“超级朋友”。这就是多模态系统要干的事。具体来说单一模型的挑战主要有两个YOLOv5的“分类粗糙”问题YOLO系列模型为了追求极致的检测速度在分类头负责判断物体类别的那部分网络上通常做得比较轻量。它的标签体系往往是像“人”、“车”、“狗”这样的大类。对于“金毛犬”、“柯基犬”、“茶杯犬”都统一归为“狗”。在需要精细识别的场景下这就不够用了。ViT的“位置盲区”问题Vision TransformerViT通过将图像切分成小块patch来理解全局上下文在图像分类任务上表现惊人。但它本质上是一个“给整张图打标签”的模型。你给它一张图它输出一个最可能的类别标签。它无法告诉你画面中有多个同类物体时各自的位置也无法处理“一张图里包含多个主要物体”的复杂场景。所以一个很自然的想法就产生了能不能让YOLOv5先快速地把画面中所有感兴趣的物体都“框”出来然后针对每一个“框”出来的小图再用ViT进行二次精细分类呢这就是我们构建的这个多模态系统的核心思路。接下来我们看看它实际表现如何。2. 系统效果惊艳展示当“定位专家”遇见“分类大师”理论说再多不如实际效果有说服力。我找了几张有代表性的图片分别用单独的YOLOv5、单独的ViT以及我们的融合系统跑了一遍。结果对比非常直观。2.1 场景一家庭客厅 – 识别家具与电器我用了下面这张典型的客厅图片。画面里有沙发、茶几、台灯、植物、装饰画等。单独模型的表现YOLOv5成功检测到了“沙发”、“花瓶”植物、“电视”。但它把台灯识别成了“杯子”把装饰画识别成了“时钟”。分类不够精确。ViT日常物品版给整张图的分类是“客厅场景”。它“感觉”到了这是一个客厅但无法指出各个物体的具体位置和名称。我们的多模态系统表现系统先让YOLOv5出手框出了5个主要物体区域。然后针对每一个区域裁剪出的小图调用ViT模型进行细分类。区域1沙发YOLOv5输出“沙发”ViT二次分类后置信度最高的标签是“布艺沙发”。区域2台灯YOLOv5错误地认为是“杯子”但经过ViT一看立刻纠正为“现代台灯”并且给出了很高的置信度。区域3植物YOLOv5说是“花瓶”ViT细分为“龟背竹”一种常见室内绿植。区域4装饰画YOLOv5误判为“时钟”ViT正确识别为“抽象装饰画”。区域5电视两者结果一致均为“液晶电视”。效果对比一目了然融合系统不仅继承了YOLOv5强大的定位能力每一个框都准确无误更关键的是它借助ViT将每一个物体的识别精度提升到了一个新的层次。从“有台灯”升级到“有现代风格的台灯”从“有植物”升级到“有龟背竹”。2.2 场景二户外公园 – 区分动物与行人第二张图是一个公园场景远景有飞鸟中景有跑步的人近景有草坪和长椅。单独模型的表现YOLOv5检测到了“人”、“鸟”。但对于远处天空中的多个小点它可能因为尺寸太小而漏检或者统一归为“鸟”无法区分种类。ViT整体分类可能是“公园”或“户外场景”再次丢失了细节信息。我们的多模态系统表现YOLOv5框出了“人”和天空中的一团“物体”它可能无法区分是鸟群还是云朵。系统将天空区域裁剪后送给ViT。对人的检测YOLOv5结果稳定ViT可以进一步判断人的姿态例如“跑步的人”虽然当前ViT日常物品标签库可能不包含此细类但展示了扩展可能性。对天空区域的分类ViT发挥了巨大作用。它没有简单地说“鸟”而是给出了“鸽子群”这个更具体的标签并且置信度很高。如果画面中混入了无人机等其他物体ViT也能有效区分。这个案例展示了系统在处理小目标、密集目标和需要上下文理解的场景下的优势。YOLOv5负责发现“那里有一团东西”ViT负责解答“这团东西到底是什么”。2.3 场景三办公桌面 – 精细物品分类最后看一个更“微观”的场景一张杂乱的书桌上面有笔记本电脑、马克杯、书籍、笔、手机等。单独模型的表现YOLOv5能检测出“笔记本电脑”、“杯子”、“书”。但对于“笔”这种细小物体容易漏检。并且它无法区分“马克杯”和“玻璃杯”。ViT整体分类可能是“办公桌”同样缺乏细节。我们的多模态系统表现系统精准定位了桌面上的7个主要物品。ViT的二次分类带来了质的飞跃杯子从“杯子”细分为“带手柄的陶瓷马克杯”。电脑从“笔记本电脑”细分为“某品牌超薄笔记本电脑”如果ViT训练数据足够好。书ViT甚至能识别出书籍封面的部分文字或颜色主题给出“蓝色封面的精装书”这样的描述依赖于ViT的识别能力。成功检测出细小的“笔”由于YOLOv5先将其框出ViT在放大的裁剪图上能清晰识别这是单一模型处理整图时可能忽略的。这个场景完美诠释了多模态系统在提升识别粒度和召回率方面的价值。它让机器视觉从“看到物体”进化到“看清物体”。3. 如何构建这个系统融合与后处理的最佳实践看到上面的效果你可能已经心动了。下面我就把搭建这个系统的核心思路和关键步骤分享给你。代码不会太多重点是理解流程和其中的“坑”。整个系统的流程可以概括为YOLOv5检测 → 区域裁剪 → ViT分类 → 结果融合与后处理。3.1 第一步模型准备与初始化首先你需要准备好两个模型。这里我以PyTorch环境为例。import torch import cv2 from PIL import Image import numpy as np # 1. 加载YOLOv5模型 (假设你已下载好yolov5s.pt) yolo_model torch.hub.load(ultralytics/yolov5, yolov5s, pretrainedTrue) yolo_model.conf 0.25 # 置信度阈值过滤掉不可靠的检测框 yolo_model.iou 0.45 # NMS的IoU阈值 # 2. 加载ViT图像分类模型 # 这里以Hugging Face Transformers库中的ViT为例你也可以使用ModelScope等平台的模型 from transformers import ViTImageProcessor, ViTForImageClassification processor ViTImageProcessor.from_pretrained(google/vit-base-patch16-224) vit_model ViTForImageClassification.from_pretrained(google/vit-base-patch16-224) # 如果你使用中文日常物品ViT可以替换为对应的模型路径例如 damo/cv_vit-base_image-classification_Dailylife-labels关键点选择YOLOv5的版本s, m, l, x取决于你对速度和精度的权衡。ViT模型也可以根据需求替换为更轻量或更强大的变体。3.2 第二步运行YOLOv5获取检测框这是系统的“眼睛”负责扫描全图找到所有可能的目标。def detect_objects(image_path): 使用YOLOv5进行目标检测 img cv2.imread(image_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # YOLOv5推理 results yolo_model(img_rgb) # 解析结果获取边界框、置信度、类别ID detections results.pandas().xyxy[0] # 转换为Pandas DataFrame格式 boxes detections[[xmin, ymin, xmax, ymax]].values.astype(int) confidences detections[confidence].values class_ids detections[class].values class_names detections[name].values # YOLO自带的类别名 return img, boxes, confidences, class_ids, class_names3.3 第三步裁剪与ViT精细分类针对YOLOv5给出的每一个框我们裁剪出该区域送给ViT进行“专家会诊”。def refine_with_vit(original_image, boxes, class_names): 使用ViT对每个检测框进行精细分类 refined_results [] for i, (box, yolo_cls) in enumerate(zip(boxes, class_names)): x1, y1, x2, y2 box # 1. 裁剪检测区域并适当扩展边界避免裁剪过紧 expand_pixels 5 h, w original_image.shape[:2] x1_exp max(0, x1 - expand_pixels) y1_exp max(0, y1 - expand_pixels) x2_exp min(w, x2 expand_pixels) y2_exp min(h, y2 expand_pixels) cropped_img original_image[y1_exp:y2_exp, x1_exp:x2_exp] # 如果裁剪区域太小则跳过ViT可能无法有效处理 if cropped_img.size 0: refined_results.append((box, yolo_cls, 未知 (区域过小), 0.0)) continue # 2. 预处理并送入ViT pil_image Image.fromarray(cv2.cvtColor(cropped_img, cv2.COLOR_BGR2RGB)) inputs processor(imagespil_image, return_tensorspt) with torch.no_grad(): outputs vit_model(**inputs) logits outputs.logits # 3. 获取ViT的预测结果 predicted_class_idx logits.argmax(-1).item() vit_cls vit_model.config.id2label[predicted_class_idx] confidence torch.nn.functional.softmax(logits, dim-1)[0, predicted_class_idx].item() refined_results.append((box, yolo_cls, vit_cls, confidence)) return refined_results这里有个重要技巧裁剪时进行适当的边界扩展expand_pixels。因为YOLOv5的框有时会切得太紧可能把物体的边缘特征切掉影响ViT的分类。扩展几个像素能保留更多上下文信息。3.4 第四步结果融合与后处理策略拿到两个模型的结果后不能简单拼接需要一些策略来决定最终输出什么。这是系统智慧的体现。def fuse_results(refined_results, confidence_threshold0.7): 融合YOLOv5和ViT的结果并后处理 final_detections [] for box, yolo_cls, vit_cls, vit_conf in refined_results: # 策略1置信度过滤 if vit_conf confidence_threshold: # 如果ViT对自己结果都不自信则 fallback 到YOLOv5的结果 final_cls yolo_cls final_conf vit_conf # 或用YOLOv5的置信度 note (ViT低置信度采用YOLO结果) else: # 策略2类别一致性检查可选如果两个模型类别体系可映射 # 例如如果yolo_cls是“狗”而vit_cls是“金毛犬”则认为一致采用vit_cls # 这里简化处理直接采用高置信度的ViT结果 final_cls vit_cls final_conf vit_conf note (ViT高置信度细化) # 策略3非极大值抑制NMS已在YOLOv5内部完成这里主要处理重叠框的类别合并略 # 策略4可以根据业务逻辑过滤掉不感兴趣的类别 final_detections.append({ box: box, class: final_cls, confidence: final_conf, note: note }) return final_detections后处理是提升系统鲁棒性的关键常见的策略包括置信度加权以ViT的置信度为主但如果太低则回退到YOLO的粗分类结果避免ViT的误判带来灾难。类别映射与过滤如果两个模型的类别体系不同如YOLO是“狗”ViT是“金毛犬”可以建立映射关系。也可以过滤掉“人”、“天空”等不需要进一步细分的背景类。重叠框合并对于同一物体被检测出多个框的情况可以根据IoU和类别进行合并。3.5 第五步可视化输出最后将融合后的结果漂亮地画在图上。def visualize_results(image, final_detections): 在图像上绘制最终检测和分类结果 output_img image.copy() for det in final_detections: x1, y1, x2, y2 det[box] label f{det[class]} ({det[confidence]:.2f}) # 画框 cv2.rectangle(output_img, (x1, y1), (x2, y2), (0, 255, 0), 2) # 画标签背景 (text_width, text_height), baseline cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2) cv2.rectangle(output_img, (x1, y1 - text_height - 10), (x1 text_width, y1), (0, 255, 0), -1) # 写标签文字 cv2.putText(output_img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2) return output_img把上面所有步骤串起来一个基础版的多模态识别系统就搭建完成了。你可以用这个流程去处理图片或视频流。4. 系统优势与潜在挑战用了一段时间这个系统后我对它的优势和需要留意的地方有了更深的体会。最明显的几个优势识别精度大幅提升这不用多说上面的对比图已经很明显了。从“物体”到“具体物体”是质的飞跃。灵活性高YOLOv5和ViT模型可以独立替换和升级。比如你可以把YOLOv5换成更快的YOLOv8-Nano或者把ViT换成专门针对某个垂直领域如医学影像、工业零件微调过的模型系统架构基本不用动。易于理解和调试因为流程是分阶段的如果结果不对很容易定位问题。是YOLOv5没框出来还是ViT分错了排查起来比一个端到端的黑盒模型要容易得多。资源利用相对合理虽然运行两个模型比运行一个慢但你可以通过策略优化。例如只对YOLOv5高置信度的检测框进行ViT分类或者对视频流采用隔帧检测等。当然也有一些挑战和需要注意的地方速度与精度的权衡这是最大的挑战。运行两个模型尤其是ViT这种计算量较大的模型肯定会比单YOLOv5慢。在实时性要求极高的场景如自动驾驶需要精心优化或使用更轻量的分类模型。类别体系对齐YOLOv5的80个COCO类别和ViT的1300个日常物品类别并非完全子集关系。需要设计聪明的映射和冲突解决策略。有时ViT会输出一个YOLO体系里没有的类别如何呈现给用户需要设计。错误传播风险如果YOLOv5第一步就漏检或错检那么后续的ViT分类再厉害也无用武之地。所以保证YOLOv5的召回率尽可能不漏检至关重要。计算资源对每一个检测框都要跑一次ViT当画面中物体很多时计算开销会成倍增加。可以考虑使用批处理batch来加速ViT推理。5. 总结与展望回过头来看把ViT和YOLOv5结合的这个思路其实挺直观的就是让专业的人做专业的事。但实际做下来里面的细节和调优功夫才是决定系统好不好用的关键。从效果上看这个多模态系统在复杂场景、细粒度识别和要求高精度的应用里优势非常明显。它不再是冷冰冰地框出一个“东西”而是能告诉你那具体是个“什么东西”体验提升了一大截。如果你也想尝试搭建类似的系统我的建议是先从简单的场景和图片开始。别一上来就处理高清视频流。用几张有代表性的图片把整个流程跑通看看效果体会一下两个模型各自的特点和配合方式。然后再根据你的具体需求去调整置信度阈值、尝试不同的后处理策略或者更换更合适的ViT模型比如用NextViT这种为实时性优化的版本。未来这个方向还有很多可以玩的地方。比如能不能让两个模型在中间层就进行特征交互而不是这样串行处理或者设计一个更轻量、更统一的网络结构同时完成检测和精细分类这些都是很有趣的研究点。不过就工程落地而言目前这个“检测分类”的Pipeline已经非常实用和有效了。它用一种相对简单清晰的方式解决了“既准又细”的视觉识别难题。希望今天的分享能给你带来一些启发。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。