LLaVA-VL/LLaVA-NeXT多模态模型使用教程:从图像到视频的视觉理解

LLaVA-VL/LLaVA-NeXT多模态模型使用教程:从图像到视频的视觉理解

LLaVA-NeXT LLaVA-NeXT 项目地址: https://gitcode.com/gh_mirrors/ll/LLaVA-NeXT

前言

LLaVA-VL/LLaVA-NeXT是一个强大的多模态模型系列,能够处理图像、文本、图文混合以及视频输入。本教程将详细介绍如何使用这个模型进行各种视觉理解任务,即使是计算资源有限的设备也能运行其轻量级版本。

模型简介

LLaVA-VL/LLaVA-NeXT模型系列有几个显著特点:

  1. 统一接口:使用相同的代码接口处理不同类型输入(图像、视频、图文混合)
  2. 轻量高效:0.5B版本可在4GB显存的GPU上运行
  3. 强大性能:尽管模型体积小,但在各种视觉理解任务上表现优异

环境准备

在开始前,请确保已安装必要的Python包:

pip install torch transformers pillow requests decord

图像理解

基础图像理解

以下代码展示了如何使用LLaVA模型理解单张图像内容:

from llava.model.builder import load_pretrained_model
from llava.mm_utils import process_images, tokenizer_image_token
from llava.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN
from llava.conversation import conv_templates

from PIL import Image
import requests
import torch

# 加载模型
model_path = "lmms-lab/llava-onevision-qwen2-0.5b-si"
tokenizer, model, image_processor, _ = load_pretrained_model(
    model_path, 
    None, 
    "llava_qwen",
    device_map="auto",
    multimodal=True,
    attn_implementation="sdpa"
)

# 准备图像
image_url = "https://example.com/sample_image.jpg"  # 替换为实际图像URL
image = Image.open(requests.get(image_url, stream=True).raw)
image_tensor = process_images([image], image_processor, model.config)
image_tensor = image_tensor.to(dtype=torch.float16, device="cuda")

# 构建对话
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN}\n这张图片展示了什么内容?"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)
prompt = conv.get_prompt()

# 生成回答
input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to("cuda")
output = model.generate(
    input_ids,
    images=[image_tensor],
    image_sizes=[image.size],
    do_sample=False,
    temperature=0,
    max_new_tokens=512,
)

print(tokenizer.decode(output[0], skip_special_tokens=True))

流式输出实现

对于交互式应用,可以使用流式输出:

from threading import Thread
from transformers import TextIteratorStreamer

# ... (前面的模型加载和图像处理代码相同)

streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

gen_kwargs = {
    "inputs": input_ids,
    "images": [image_tensor],
    "image_sizes": [image.size],
    "streamer": streamer,
    "do_sample": False,
    "temperature": 0,
    "max_new_tokens": 512,
}

thread = Thread(target=model.generate, kwargs=gen_kwargs)
thread.start()

for new_text in streamer:
    print(new_text, end="", flush=True)

图文混合理解

LLaVA-OneVision模型特别擅长处理图文混合内容。以下是处理多张图像和文本交替输入的示例:

# 加载OneVision专用模型
model_path = "lmms-lab/llava-onevision-qwen2-0.5b-ov"
tokenizer, model, image_processor, _ = load_pretrained_model(
    model_path,
    None,
    "llava_qwen",
    device_map="auto",
    multimodal=True,
    overwrite_config={"image_aspect_ratio": "pad"}
)

# 准备多张图像
image_urls = [
    "https://example.com/image1.jpg",
    "https://example.com/image2.jpg"
]
images = [Image.open(requests.get(url, stream=True).raw) for url in image_urls]
image_tensors = process_images(images, image_processor, model.config)
image_tensors = [tensor.to(dtype=torch.float16, device="cuda") for tensor in image_tensors]

# 构建图文混合问题
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN} 这是第一张图片,请描述你看到的内容。\n\n现在看第二张图片: {DEFAULT_IMAGE_TOKEN}\n这两张图片有什么区别?"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)

# 生成回答 (代码与前面类似)

视频理解

LLaVA-OneVision同样能处理视频输入,它会自动从视频中提取关键帧进行分析:

import cv2
import numpy as np
from decord import VideoReader, cpu

# 视频帧提取函数
def extract_frames(video_path, num_frames=16):
    vr = VideoReader(video_path, ctx=cpu(0))
    total_frames = len(vr)
    frame_indices = np.linspace(0, total_frames-1, num_frames, dtype=int)
    return vr.get_batch(frame_indices).asnumpy()  # (帧数, 高, 宽, 通道)

# 加载和处理视频
video_frames = extract_frames("sample_video.mp4")
frame_tensors = image_processor.preprocess(video_frames, return_tensors="pt")["pixel_values"].half().cuda()

# 构建视频问题
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN}\n描述这个视频中发生了什么。"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)

# 生成回答
output = model.generate(
    input_ids,
    images=[frame_tensors],
    image_sizes=[frame.shape[:2] for frame in video_frames],
    do_sample=False,
    temperature=0,
    max_new_tokens=1024,
    modalities=["video"],
)

print(tokenizer.decode(output[0], skip_special_tokens=True))

最佳实践建议

  1. 模型选择

    • 对于简单图像任务:使用llava-onevision-qwen2-0.5b-si
    • 对于复杂任务和视频:使用llava-onevision-qwen2-0.5b-ov
  2. 性能优化

    • 使用flash-attn可以显著提升推理速度
    • 对于长视频,适当减少提取的帧数(如8-16帧)
  3. 提示工程

    • 确保图像标记<image>在提示中只出现一次
    • 对于视频,明确说明"这个视频"而非"这张图片"
  4. 错误处理

    • 监控token长度,避免超过模型限制
    • 处理网络请求时添加超时和重试机制

结语

LLaVA-VL/LLaVA-NeXT系列模型为多模态理解提供了强大而灵活的工具。通过本教程,您应该已经掌握了处理图像、图文混合内容和视频的基本方法。无论是构建智能客服、内容审核系统还是多媒体分析工具,这些技术都能提供坚实的基础。

LLaVA-NeXT LLaVA-NeXT 项目地址: https://gitcode.com/gh_mirrors/ll/LLaVA-NeXT

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌榕萱Kelsey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值