Qwen2.5-0.5B Instruct与YOLOv5结合:智能图像标注系统

你有没有遇到过这样的情况?手头有一大堆图片需要标注,比如给电商商品打上“手机”、“耳机”的标签,或者给监控视频里的行人、车辆画上框。一张张手动处理,眼睛看花了,手也点麻了,效率低不说,还容易出错。

传统的图像标注要么靠人工,费时费力;要么用一些简单的规则,不够灵活。现在,我们有了新的思路:把“看得准”的目标检测模型和“说得清”的语言模型结合起来。今天要聊的,就是用YOLOv5来“看”图片里有什么,再用Qwen2.5-0.5B Instruct这个轻量级大模型来“描述”看到的内容,打造一个自动化的智能标注系统。

这套方案的核心价值很简单:提效。它能将大量重复、机械的标注工作自动化,把人解放出来去做更有创造性的审核和优化。无论是做数据集给AI训练用,还是管理海量的图片、视频素材,都能派上大用场。

1. 为什么是YOLOv5 + Qwen2.5-0.5B Instruct?

在动手之前,我们先看看为什么选这两个“搭档”。

YOLOv5大家都很熟悉了,在目标检测领域是经久不衰的“老兵”。它速度快、精度不错,而且生态成熟,预训练模型多,从COCO数据集的80类通用物体到各种垂直领域(比如安全帽、车牌)的专用模型,很容易找到或训练出适合你场景的版本。它的输出很直接,就是图片里每个物体的类别、位置(一个框)和置信度。这些结构化的信息,正是我们交给语言模型去理解和描述的“原材料”。

那为什么语言模型要选Qwen2.5-0.5B Instruct,而不是更大的模型呢?关键在于“性价比”和“可控性”。

Qwen2.5-0.5B Instruct虽然只有5亿参数,是个“小个子”,但它指令跟随能力不错,能很好地理解我们“请根据检测结果生成描述”这类要求。更重要的是,它足够轻量。部署和推理成本低,响应速度快,非常适合集成到需要实时或批量处理的标注流水线中。你不需要动用动辄上百亿参数的“大模型舰队”,用这个小巧的模型就能完成从结构化数据到自然语言描述的转换,成本效益比很高。

把它们俩结合,工作流就清晰了:YOLOv5充当“眼睛”,快速扫描图片,找出目标并打好框;Qwen2.5-0.5B Instruct充当“大脑”,接收这些框和类别信息,组织成通顺、规范的描述语句。比如,YOLOv5输出“坐标(x1,y1,x2,y2),类别:狗,置信度:0.95”,Qwen2.5就能生成“图片中检测到一只狗,位于画面中央偏左的位置。”

2. 搭建你的智能标注流水线

理论说完了,我们来看看具体怎么把这两部分拼装起来。整个过程可以分为三个核心步骤:环境准备、检测与信息提取、描述生成。

2.1 环境与模型准备

首先,你需要一个Python环境(建议3.8以上),并安装必要的库。核心是PyTorch(用于YOLOv5和Qwen2.5)、Transformers库(用于加载Qwen2.5),以及OpenCV或PIL来处理图片。

# 基础环境
pip install torch torchvision
# 用于加载Qwen2.5
pip install transformers accelerate
# 用于图像处理
pip install opencv-python pillow
# 克隆YOLOv5的官方仓库(我们直接使用其推理代码)
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt

模型方面,YOLOv5我们可以直接用官方预训练的yolov5s.pt(小模型,速度快)。Qwen2.5-0.5B Instruct模型可以从Hugging Face直接加载。

2.2 第一步:用YOLOv5进行目标检测

这一步的目标是让YOLOv5把图片里的物体都找出来。我们写一个简单的检测函数。

import torch
import cv2
from pathlib import Path

# 加载YOLOv5模型(确保你在yolov5目录下,或正确设置路径)
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
model.conf = 0.25  # 置信度阈值,可根据需要调整
model.iou = 0.45   # NMS的IoU阈值

def detect_objects(image_path):
    """
    使用YOLOv5检测图片中的物体。
    返回一个列表,每个元素是一个字典,包含类别、置信度和边框坐标。
    """
    # 读取图片
    img = cv2.imread(image_path)
    if img is None:
        raise ValueError(f"无法读取图片: {image_path}")
    
    # 执行推理
    results = model(img)
    
    # 解析结果
    detections = []
    # results.pandas().xyxy[0] 是一个DataFrame,包含检测结果
    df = results.pandas().xyxy[0]
    
    for _, row in df.iterrows():
        det = {
            'class': row['name'],          # 类别名,如 'person', 'car'
            'confidence': round(row['confidence'], 3), # 置信度
            'bbox': [int(row['xmin']), int(row['ymin']), 
                     int(row['xmax']), int(row['ymax'])] # [x1, y1, x2, y2]
        }
        detections.append(det)
    
    return img, detections

# 测试一下
test_img_path = 'your_test_image.jpg'
original_img, objects = detect_objects(test_img_path)
print(f"检测到 {len(objects)} 个物体:")
for obj in objects:
    print(f"  - {obj['class']} (置信度: {obj['confidence']}) 位置: {obj['bbox']}")

运行这段代码,你就能得到图片中所有检测到的物体列表。这是整个流程的“原料”。

2.3 第二步:组织信息,准备给语言模型的“提示”

直接扔给语言模型一堆数字和类别名,它可能不知道怎么组织语言。我们需要把YOLOv5的输出,转换成一段清晰的“任务描述”,也就是提示词(Prompt)。

我们的目标是让Qwen2.5生成类似这样的描述:“图片中有一只狗(置信度95%)位于画面左侧,一辆汽车(置信度88%)位于画面中央。”

def format_detections_for_llm(detections, image_width, image_height):
    """
    将检测结果格式化成一段自然语言描述,作为给LLM的上下文。
    """
    if not detections:
        return "当前图片中未检测到任何显著物体。"
    
    description_lines = []
    for det in detections:
        cls_name = det['class']
        conf = det['confidence']
        x1, y1, x2, y2 = det['bbox']
        
        # 可以简单计算一下物体的大致位置(这是一个简化示例)
        center_x = (x1 + x2) / 2
        center_y = (y1 + y2) / 2
        
        if center_x < image_width / 3:
            horiz_pos = "左侧"
        elif center_x > 2 * image_width / 3:
            horiz_pos = "右侧"
        else:
            horiz_pos = "中央"
            
        if center_y < image_height / 3:
            vert_pos = "上方"
        elif center_y > 2 * image_height / 3:
            vert_pos = "下方"
        else:
            vert_pos = "中部"
        
        # 构建每行描述
        line = f"- 一个'{cls_name}'(置信度{conf*100:.0f}%),位于画面{horiz_pos}{vert_pos}。"
        description_lines.append(line)
    
    # 组合成最终的提示上下文
    context = f"根据目标检测结果,图片中包含以下物体:\n" + "\n".join(description_lines)
    return context

# 获取图片尺寸
img_height, img_width = original_img.shape[:2]
llm_context = format_detections_for_llm(objects, img_width, img_height)
print("准备给LLM的上下文信息:")
print(llm_context)

这段代码把冰冷的坐标和类别,转换成了带有位置信息的自然语言片段,让语言模型更容易理解。

2.4 第三步:调用Qwen2.5-0.5B Instruct生成描述

现在,我们把上面生成的上下文信息,交给Qwen2.5,让它生成最终的通顺描述。

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# 加载Qwen2.5-0.5B-Instruct模型和分词器
model_name = "Qwen/Qwen2.5-0.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# 根据你的硬件情况,可以调整torch_dtype,比如torch.float16
llm_model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.float16, # 使用半精度减少显存占用
    device_map="auto",         # 自动分配GPU/CPU
    trust_remote_code=True
)

def generate_caption_with_llm(context):
    """
    使用Qwen2.5根据检测上下文生成图片描述。
    """
    # 构建对话格式的输入
    messages = [
        {"role": "system", "content": "你是一个专业的图像内容描述助手。请根据提供的目标检测信息,生成一段流畅、准确的图片描述。"},
        {"role": "user", "content": context}
    ]
    
    # 应用聊天模板
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    
    # 分词并生成
    inputs = tokenizer(text, return_tensors="pt").to(llm_model.device)
    
    with torch.no_grad():
        generated_ids = llm_model.generate(
            **inputs,
            max_new_tokens=150,      # 控制生成描述的长度
            do_sample=True,          # 启用采样,使输出更多样
            temperature=0.7,         # 采样温度
            top_p=0.9                # 核采样参数
        )
    
    # 解码输出,跳过输入部分
    generated_ids = generated_ids[:, inputs.input_ids.shape[1]:]
    response = tokenizer.decode(generated_ids[0], skip_special_tokens=True)
    
    return response.strip()

# 生成最终描述
final_caption = generate_caption_with_llm(llm_context)
print("\n=== 智能生成的图片描述 ===")
print(final_caption)

把这三步串起来,一个完整的智能标注流程就跑通了。你输入一张图片,终端就会输出一段由AI生成的、包含物体类别和位置信息的描述文字。

3. 实际效果与应用扩展

我找了一张包含多只猫和人的复杂图片进行测试。YOLOv5准确地检测出了“person”和“cat”,Qwen2.5生成的描述是:“图片中检测到两个人,分别位于画面右侧和左下方。此外,还有三只猫,其中两只在画面中央区域,一只在左侧。”

效果怎么样?对于自动化标注来说,这已经相当实用了。它不仅能说出有什么,还能大致描述位置,这比单纯输出“person, cat, cat, cat”的标签列表要友好和有用得多。

这个基础框架的扩展性很强,你可以根据实际需求轻松调整:

  1. 换更强的检测器:如果YOLOv5s的精度不够,可以换成YOLOv5m/l/x,或者YOLOv8、DETR等更先进的模型。
  2. 定制描述风格:通过修改给Qwen2.5的system提示词,你可以让它生成不同风格的描述。比如,对于电商图片,可以要求:“生成一段简洁的商品卖点描述,突出主体商品。”对于安防场景,可以要求:“以监控报告的形式描述,按时间顺序说明各目标出现的位置。”
  3. 输出结构化数据:Qwen2.5支持生成JSON格式。你可以要求它直接把描述输出成{"objects": [{"name": "dog", "position": "left"}]}这样的结构,方便后续程序处理。
  4. 处理视频流:将上述流程封装成一个函数,然后对视频的每一帧或按固定间隔帧进行处理,就能实现视频内容的自动摘要和标注。
  5. 集成到标注工具:将生成的描述作为预标注建议,导入到LabelImg、CVAT等标注工具中,人工只需要进行微调或确认,能极大提升标注团队的效率。

4. 一些实践中的小建议

在实际用起来的时候,有几点经验可以分享:

  • 阈值调整是关键:YOLOv5的conf参数直接影响检测出的物体数量。设得太高,会漏掉一些不太确定的目标;设得太低,又会引入很多误检。需要根据你的图片特点和标注要求来找到一个平衡点。
  • 提示词需要微调:Qwen2.5生成描述的质量,很大程度上取决于你给的提示词。多尝试几种不同的指令表述,比如“请详细描述”、“请用一句话总结”、“请分点列出”,看看哪种效果最符合你的预期。
  • 注意性能开销:虽然Qwen2.5-0.5B很轻量,但在批量处理成千上万张图片时,推理时间依然需要考虑。如果对速度要求高,可以研究一下模型量化(如INT8),或者使用更快的推理后端(如ONNX Runtime)。
  • 人工审核环节不可少:目前这还是一个“AI辅助”系统,生成的描述在复杂场景(物体重叠、小目标、罕见类别)下可能出错。建立一个人工审核或修正的步骤,是保证最终标注质量的重要防线。

5. 总结

把YOLOv5和Qwen2.5-0.5B Instruct结合起来,搭建一个智能图像标注系统,思路并不复杂,但效果却很实在。它抓住了两个AI模型的专长:一个擅长“看”,一个擅长“说”,通过简单的管道连接,就实现了1+1>2的效果。

这套方案最大的优势在于灵活和低成本。你不需要标注团队从零开始画框写描述,也不需要采购昂贵的专用标注软件或服务。用开源模型和少量代码,就能搭建一个适应自己业务需求的自动化流水线。无论是为了构建数据集而批量处理图片,还是为内容管理平台自动生成图片说明,都是一个值得尝试的起点。

当然,它现在可能还做不到百分之百的完美替代人工,但在处理大量重复、规则相对明确的标注任务时,它能节省的时间和人力是显而易见的。如果你正在被图像标注问题困扰,不妨按照上面的步骤动手试一试,从这个简单的结合开始,探索更多AI协同工作的可能性。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐