Qwen模型部署以及调用(和YOLO检测结合)
Qwen模型与YOLO检测结合
- 模型部署
方法一:(用于安装Qwen3以下)
先创建一个虚拟环境,这里我们使用anaconda

创建成功后前缀会变成Qwen
![]()
下面开始配置环境:
先激活我们的虚拟环境:conda activate Qwen
安装pytorch和cuda(根据自己的显卡进行选择,如果环境配置不熟的可以参考:本博客将对yolov12训练环境配置,如何进行训练进行介绍_yolov12配置环境-CSDN博客):
pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu124
安装其他依赖:
pip install gradio>=5.4.0 gradio_client>=1.4.2 qwen-vl-utils==0.0.10 transformers-stream-generator==0.0.4 transformers>=4.49.0 accelerate av modelscope
由于显卡配置问题,无法使用原版的Qwen(BF16/FP16)模型,只能使用量化模型(这里解释一下下载的模型依旧是原版模型,只是我们需要通过bitsandbytes将它压缩成4bit的精度)
安装ModelScope(依旧是在Qwen环境中):
pip install modelscope
创建一个脚本:
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen2.5-VL-3B-Instruct', cache_dir='D:/Qwen3-VL-main/model')
print(f'模型下载完成,保存在:{model_dir}')
红字为下载地址,根据自己进行修改


下载成功之后。
找到模型路径:
"D:\Qwen3-VL-main\model\Qwen\Qwen2___5-VL-3B-Instruct"
前面是自己设置的。
安装量化工具:
pip install https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.0-py3-none-win_amd64.whl

方法二:(Qwen3以上模型)
通过Ollama工具,部署简单,而且原生支持GGUF格式量化模型,很方便。
- 通过官网地址下载Ollama:
https://github.com/ollama/ollama/releases/latest/download/OllamaSetup.exe
如果官网下载缓慢,可以使用镜像源:
https://cnb.cool/hex/ollama/-/releases/latest/download/OllamaSetup.exe
下载完成后,进行安装,在安装时如果不想安装到默认盘(C盘),可以修改安装路径:
从网站上下载好OllamaSetup.exe文件后,找到文件所在地址栏输入cmd并回车

在终端窗口 输入:
.\OllamaSetup.exe /DIR="D:\Program Files\Ollama"
(将 D:\Program Files\Ollama 替换为你想要安装的路径)
安装完成后,开始安装模型:
在Ollama界面右下角可以选择想安装的模型,
在安装之前也可以先设置自己要安装的地址
设置好后,来到界面右下角选择要安装的模型:

模型大小如下:

选择好后在窗口输入对应的下载命令就可以了。

(这是把模型部署到本地调用,比较吃自己电脑的配置,胜在安全性高且免费,我们也可以通过调用阿里云服务器的API,可以使用更强大的模型,且完全不吃自己电脑配置,不过需要担心泄密问题且需要付费,不过0.8元百万token还有免费额度仅用于学习和测试完全足够了)
下面我们开始调用,因为目前只有两个模型,一个检测人脸一个检测横幅,那我们就设置一个通过YOLO识别横幅,然后将识别区域送给Qwen3-VL模型,让他识别上面的字,我们通过调用API的方法调用Qwen3-VL,这里就有问题了,之前我们不是已经下载了Qwen3-VL到本地了吗,为什么还需要通过API进行调用呢?
因为上面我们是通过Ollama下载的模型,他是会把模型存储到本地,但是模型本身是不会被python代码调用的,因为大模型的运行需要复杂的推理环境(GPU 内存管理、计算图优化、分词器等),Ollama将这些复杂性封装成了一个独立的后台服务。
我们在通过API调用时实际是通过HTTP请求(requests.post)向Ollama服务器发送图片和提示词,Ollama服务器完成推理后,再将结果通过HTTP响应返回。Ollama在后台监听127.0.0.1:11434,负责加载模型,管理GPU内存,执行推理,提供了RESTful API接口,供其他程序调用。(整个过程全部发生在本地机器上,数据不需要上传到互联网,完全免费,因为Qwen模型本身是开源的)
为什么是监听127.0.0.1:11434?
127.0.0.1 是一个特殊的 IP 地址,被称为 回环地址(Loopback Address),通俗地说就是 “本机” 或 “localhost”, 当你访问 127.0.0.1 时,你的计算机会将网络流量直接转发给自己,不会经过网卡或外部网络,而11434 是 Ollama 默认使用的端口号,就像 Web 服务默认用 80/443、MySQL 默认用 3306 一样。端口号的作用是让计算机区分不同的网络服务
而请求就是我们提供的提示词(prompt)


我们可以通过更改提示词,发送不同的问题,


当然也可以在后面修改成交互页面,即时提问即时生成。
下面是单张横幅通过YOLO检测并送给Qwen模型提问的代码,后面会继续更新新生成的代码,这个只是暂时用来测试的毕竟我也是第一次调用大模型。
"""
横幅检测与文字识别脚本(支持中文显示)
功能:
1. 使用YOLO模型检测图像中的横幅。
2. 对每个检测到的横幅区域,调用Qwen3-VL视觉模型识别其中的文字。
3. 在原图上用中文绘制检测框及识别出的文字,并保存结果图像到指定目录。
"""
import cv2
import base64
import requests
import os
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from ultralytics import YOLO
# ==================== 配置区域(请根据实际情况修改) ====================
# YOLO模型路径
BANNER_MODEL_PATH = r"D:\yoloV12\yolov12-main\yolov12-main\banner_detection\exp_20260205_143453\weights\best.pt"
# 待检测图像路径
IMAGE_PATH = r"C:\Users\JAMES HARDEN\Pictures\数据集\2c5c74ca-94ae-11ee-bf17-089df4d67ddc.jpg"
# 是否保存裁剪的横幅子图(用于调试)
SAVE_CROPS = True
# 裁剪子图及最终结果保存目录(自动创建)
CROP_DIR = r"D:\yoloV12\yolov12-main\yolov12-main\OutPut\single_face_predict\banner_predict\4.0"
# Ollama API 地址(通常无需修改)
OLLAMA_API_URL = "http://localhost:11434/api/generate"
# Qwen3-VL 模型名称(需提前通过 `ollama pull qwen3-vl:4b` 下载)
QWEN_VL_MODEL = "qwen3-vl:4b"
# 检测框置信度阈值
CONF_THRESHOLD = 0.5
# ======================================================================
os.makedirs(CROP_DIR, exist_ok=True)
def get_font():
"""
尝试获取一个支持中文的字体文件,若找不到则返回 None。
返回:
ImageFont 对象或 None
"""
# 常见中文字体路径(可根据系统调整)
font_paths = [
"C:/Windows/Fonts/simhei.ttf", # 黑体
"C:/Windows/Fonts/msyh.ttc", # 微软雅黑
"C:/Windows/Fonts/simsun.ttc", # 宋体
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", # Linux
]
for path in font_paths:
if os.path.exists(path):
try:
# 字体大小可调整
return ImageFont.truetype(path, size=24)
except:
continue
return None
def draw_results(image, boxes, texts):
"""
在图像上绘制检测框和识别出的文字(支持中文)。
参数:
image: numpy 数组(BGR格式),会被修改
boxes: 边界框列表 [[x1,y1,x2,y2,conf], ...]
texts: 对应每个框的识别文字列表(可能为None)
"""
# 将 OpenCV BGR 转换为 RGB(PIL 使用 RGB)
img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(img_rgb)
draw = ImageDraw.Draw(pil_img)
# 获取字体
font = get_font()
if font is None:
print("警告:未找到支持中文的字体,将使用 OpenCV 默认字体(中文可能显示为问号)。")
for box, text in zip(boxes, texts):
x1, y1, x2, y2, conf = box
# 绘制矩形框(PIL 中颜色为 RGB)
draw.rectangle([x1, y1, x2, y2], outline=(0, 255, 0), width=2)
# 准备显示的文字
display_text = text[:30] + "..." if text and len(text) > 30 else text
if display_text:
if font:
# 使用 PIL 绘制中文
draw.text((x1, y1 - 30), display_text, fill=(0, 255, 0), font=font)
else:
# 回退到 OpenCV(不推荐,但避免报错)
cv2.putText(image, display_text, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# 将 PIL 图像转回 OpenCV BGR 格式
image[:] = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
def detect_banners(image, model):
"""
使用YOLO模型检测图像中的横幅。
参数:
image: 读取的BGR图像(numpy数组)
model: 已加载的YOLO模型
返回:
列表,每个元素为 [x1, y1, x2, y2, confidence]
"""
results = model(image)
boxes = []
for result in results:
for box in result.boxes:
conf = box.conf[0].item()
if conf < CONF_THRESHOLD:
continue
x1, y1, x2, y2 = box.xyxy[0].tolist()
boxes.append([int(x1), int(y1), int(x2), int(y2), conf])
return boxes
def crop_roi(image, box):
"""
根据边界框从图像中裁剪出感兴趣区域。
参数:
image: 原始图像
box: [x1, y1, x2, y2, confidence]
返回:
裁剪后的图像(numpy数组)
"""
x1, y1, x2, y2, _ = box
return image[y1:y2, x1:x2]
def image_to_base64(image):
"""
将OpenCV图像(BGR格式)转换为Base64字符串(JPEG编码)。
参数:
image: numpy数组图像
返回:
Base64字符串
"""
_, buffer = cv2.imencode('.jpg', image)
return base64.b64encode(buffer).decode('utf-8')
def recognize_text_with_qwen(image):
"""
调用Qwen3-VL模型识别图像中的文字。
参数:
image: 包含文字的图像(numpy数组)
返回:
识别出的文字字符串,若失败则返回None
"""
base64_img = image_to_base64(image)
payload = {
"model": QWEN_VL_MODEL,
"prompt": #"请告诉我横幅的颜色和横幅上字体的颜色",
"请仔细识别图片中的文字,并原样输出。如果图片中没有文字,请输出'无文字'。",
"images": [base64_img],
"stream": False
}
try:
response = requests.post(OLLAMA_API_URL, json=payload, timeout=60)
response.raise_for_status()
result = response.json()
return result.get('response', '').strip()
except Exception as e:
print(f"调用Qwen模型时出错: {e}")
return None
def main():
print("正在加载YOLO横幅检测模型...")
banner_model = YOLO(BANNER_MODEL_PATH)
# 读取图像
img = cv2.imread(IMAGE_PATH)
if img is None:
print(f"错误:无法读取图像 {IMAGE_PATH}")
return
print("图像读取成功。")
# 检测横幅
boxes = detect_banners(img, banner_model)
print(f"检测到 {len(boxes)} 个横幅。")
texts = []
# 对每个横幅进行文字识别
for i, box in enumerate(boxes):
x1, y1, x2, y2, conf = box
print(f"\n处理第 {i+1} 个横幅(置信度: {conf:.2f}, 位置: ({x1},{y1},{x2},{y2}))")
roi = crop_roi(img, box)
if roi.size == 0:
print("裁剪区域为空,跳过。")
texts.append(None)
continue
# 保存裁剪图(可选)
if SAVE_CROPS:
crop_path = os.path.join(CROP_DIR, f"banner_{i}.jpg")
cv2.imwrite(crop_path, roi)
print(f"裁剪图已保存至 {crop_path}")
# 识别文字
text = recognize_text_with_qwen(roi)
if text:
print(f"识别结果:{text}")
else:
print("文字识别失败。")
texts.append(text)
# 在原图上绘制结果(支持中文)
draw_results(img, boxes, texts)
# 显示并保存结果
cv2.imshow("检测结果", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
output_path = os.path.join(CROP_DIR, "result_with_text.jpg")
cv2.imwrite(output_path, img)
print(f"\n处理完成,结果图已保存至 {output_path}")
if __name__ == "__main__":
main()
根据自己下载的模型进行设置:

更多推荐



所有评论(0)