大家好,我是烤鸭:

​ 鲨疯了,上周陆续几个重磅开源,阿里云和openai陆续加入了战场,都是非商用显卡可以跑的,太炸裂了。文本模型: openai_gpt-oss 文本生成,文生图:Qwen-Image文生图,文/图生视频: 通义万相2.2-图生视频。今天重点体验一下Qwen-Image文生图。

介绍

魔塔社区模型地址:https://www.modelscope.cn/models/Qwen/Qwen-Image

看看官方的示例,效果还是非常强的,而且家用的4090就可以跑。

请添加图片描述

环境

linux ubuntu

python 3.13

显卡是4090 24G * 3

使用优化后官方的示例代码,显示模式使用均衡模式,单卡24G跑一张图片大概在8min。

展示几张效果

这里和豆包生成做一个对比,能看出来qwen-image应该是用的doubao结果做的训练数据,某些场景下相似度比较接近。但是文本较多的情况下,qwen-image明显优化做得更好。

prompt:熊猫坐在法拉利机盖上抽烟

豆包:

请添加图片描述

千问:

请添加图片描述

prompt: 白衣老人在公园打太极拳

豆包:
请添加图片描述

千问:

请添加图片描述

prompt: A coffee shop entrance features a chalkboard sign reading “Qwen Coffee 😊 $2 per cup,” with a neon light beside it displaying “通义千问”. Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written “π≈3.1415926-53589793-23846264-33832795-02384197”. Ultra HD, 4K, cinematic composition

豆包:

请添加图片描述

千问:

请添加图片描述

源码

调用的shell脚本

export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True && /data/qwen-image/venv/bin/python qwen-image.py --num_images 1 --output /data/sharedpvc/qwen-image/test1.png

源码:

import os
import torch
from modelscope import DiffusionPipeline
from accelerate import Accelerator
import argparse
import json
def generate_image_by_qwen(
        resolution,  # 分辨率,元组形式如(1280, 720)
        output_path,  # 生成图像保存路径
        prompt,  # 提示词
        use_gpus=None,  # 要使用的显卡编号列表,如[0,1,2],None则使用所有可用显卡
        num_images=1, # 生成图片的数量
        output_dir="/data/sharedpvc"  # 生成图像保存目录
):
    """
    使用Qwen-Image模型生成图像的可调用方法

    参数:
        resolution: 元组 (width, height),生成图像的分辨率
        output_path: 字符串,生成图像的保存路径
        prompt: 字符串,图像生成的提示词
        use_gpus: 列表,指定使用的显卡编号,如[0,1,2]
    """
    # 设置环境变量解决通信问题
    os.environ["NCCL_P2P_DISABLE"] = "1"
    os.environ["NCCL_IB_DISABLE"] = "1"
    os.environ["TORCH_CUDNN_V8_API_ENABLED"] = "1"

    # 配置显卡可见性
    if use_gpus is not None and isinstance(use_gpus, list) and len(use_gpus) > 0:
        os.environ["CUDA_VISIBLE_DEVICES"] = ",".join(map(str, use_gpus))
        num_gpus = len(use_gpus)
    else:
        # 自动检测可用显卡
        num_gpus = torch.cuda.device_count()
        use_gpus = list(range(num_gpus))

    # 初始化加速器
    accelerator = Accelerator()

    # 准备模型加载参数
    device_map = "balanced"
    max_memory = {gpu: "22GiB" for gpu in use_gpus} if num_gpus > 1 else None

    try:
        # 加载模型
        pipe = DiffusionPipeline.from_pretrained(
            "Qwen/Qwen-Image",
            torch_dtype=torch.bfloat16,
            device_map=device_map,
            max_memory=max_memory,
            trust_remote_code=True
        )
        
        # 启用高效注意力机制
        try:
            pipe.enable_flash_attention_2()
        except (AttributeError, ImportError):
            try:
                pipe.enable_xformers_memory_efficient_attention()
            except ImportError:
                print("警告:未启用高效注意力优化,速度可能较慢")
        
        # 提取分辨率参数
        width, height = resolution

        # 添加质量增强词
        positive_magic = {"zh": "超清,4K,电影级构图", "en": "Ultra HD, 4K, cinematic composition."}
        # 自动判断提示词语言并添加对应的增强词
        if any("\u4e00" <= c <= "\u9fff" for c in prompt):  # 检测中文
            prompt += positive_magic["zh"]
        else:
            prompt += positive_magic["en"]

        # 生成图像 - 一次调用生成多张
        with torch.no_grad():
            with accelerator.autocast():
                # 关键修改:创建包含相同提示词的列表,长度为要生成的图片数量

                # 生成多张图片
                results = pipe(
                    prompt=prompt,
                    negative_prompt="low quality, blurry, text distortion",
                    width=width,
                    height=height,
                    num_inference_steps=40,
                    true_cfg_scale=4.0,
                    generator=torch.Generator(device=accelerator.device).manual_seed(42)
                )
                print(f"图像生成完成 size: {len(results.images)}")
                
                # 检查并创建输出目录
                if not os.path.exists(output_dir):
                    os.makedirs(output_dir, exist_ok=True)
                    print(f"创建输出目录: {output_dir}")
                # 存储所有生成的图片路径
                output_paths = []
                if output_path:
                    results.images[0].save(output_path)
                    output_paths.append(output_path)
                else:
                    for i, image in enumerate(results.images):
                        output_path = os.path.join(output_dir, f"output_{i + 1}.png")
                        image.save(output_path)
                        output_paths.append(output_path)
                        

        
        return True, output_paths

    except Exception as e:
        print(f"生成过程出错: {str(e)}")
        return False, str(e)
    finally:
        # 清理显存
        if torch.cuda.is_available():
            torch.cuda.empty_cache()


def parse_arguments():
    """解析命令行参数,带有默认值"""
    parser = argparse.ArgumentParser(description='使用Qwen-Image模型生成图像')

    # 带有默认值的参数(不再是必选)
    parser.add_argument('--image',
                        default="./example.png",  # 编辑的图片地址
                        help='编辑的图片地址')
    parser.add_argument('--resolution',
                        default="1280,720",  # 默认正方形分辨率
                        help='图像分辨率,格式为"宽度,高度",例如"1280,720",默认值为"1024,1024"')
    parser.add_argument('--output',
                        default='./output.png',
                        help='生成图像的保存路径,例如"output.png"')
    parser.add_argument('--output_dir',
                        default='/data/sharedpvc',
                        help='生成图像的保存完整路径目录,用于多张图片,例如"output.png"')
    parser.add_argument('--num_images',
                        default=1,
                        help='生成图像数量,用于多张图片,例如 4')
    parser.add_argument('--prompt',
                        default='A coffee shop entrance features a chalkboard sign reading "Qwen Coffee 😊 $2 per cup," with a neon light beside it displaying "通义千问". Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written "π≈3.1415926-53589793-23846264-33832795-02384197". Ultra HD, 4K, cinematic composition ',
                        help='图像生成的提示词')

    # 可选参数,有默认值(None)
    parser.add_argument('--gpus',
                        default='1',
                        help='要使用的显卡编号,用逗号分隔,例如"0,1,2",默认使用所有可用显卡')
    # 新增:推理步数参数,带有默认值
    parser.add_argument('--steps',
                        type=int,
                        default=30,
                        help='推理步数,默认值为30,值越大生成质量可能越高但速度越慢')

    return parser.parse_args()

if __name__ == "__main__":
    # 解析命令行参数
    args = parse_arguments()

    # 处理分辨率参数
    try:
        width, height = map(int, args.resolution.split(','))
        resolution = (width, height)
    except ValueError:
        print("错误:分辨率格式不正确,请使用'宽度,高度'格式,例如'1280,720'")
        exit(1)

    # 处理显卡参数
    use_gpus = None
    if args.gpus:
        try:
            use_gpus = list(map(int, args.gpus.split(',')))
        except ValueError:
            print("错误:显卡编号格式不正确,请使用逗号分隔的数字,例如'0,1,2'")
            exit(1)

        # 调用生成函数
    result = generate_image_by_qwen(
        resolution=resolution,
        output_path=args.output,
        output_dir=args.output_dir,  # 传入目录
        num_images=args.num_images,  # 传入生成数量
        prompt=args.prompt,
        use_gpus=use_gpus
    )
    result = json.dumps({"files": result[1]})
    # 打印包含list[str]的JSON
    print(f"generate end:{result}")

显存占用情况:
请添加图片描述

量化模型

虽然效果好,但是1张图片8min还是有点长。不慌,各位大神量化版本已出,

DFloat11 压缩模型: Qwen/Qwen-Image

https://www.modelscope.cn/models/DFloat11/Qwen-Image-DF11

Qwen-Image 全量蒸馏加速模型

https://www.modelscope.cn/models/DiffSynth-Studio/Qwen-Image-Distill-Full

上面的两个量化模型的,我的单卡跑不起来,显存不够…
所以现在使用的DFloat11的CPU模式,最大显存16G+。速度比之前快了一倍吧,一张图片可以压缩到4分钟。

贴个效果图,某些场景下还是可以的:

在这里插入图片描述

shell调用:

export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True && /data/qwen-image/venv/bin/python qwen-image-df11.py --cpu_offload --num_images 1 --output /data/sharedpvc/qwen-image/test1.png

代码:

from modelscope import DiffusionPipeline, QwenImageTransformer2DModel
import torch
from transformers.modeling_utils import no_init_weights
from dfloat11 import DFloat11Model
import argparse
from pathlib import Path
from accelerate import Accelerator
import json
import os
import time  # 需要导入time模块

# model_name = "Qwen/Qwen-Image"
model_local_path = "/root/.cache/modelscope/hub/models/Qwen/Qwen-Image"
# /root/.cache/modelscope/hub/models/Qwen/Qwen-Image/transformer
model_path = Path(model_local_path)  # 替换为实际的模型目录路径
transformer_config_path = model_path / "transformer" / "config.json"
def parse_args():
    """解析命令行参数,带有默认值"""
    parser = argparse.ArgumentParser(description='使用Qwen-Image模型生成图像')
    parser.add_argument('--cpu_offload', action='store_true', help='Enable CPU offloading')
    parser.add_argument('--no_pin_memory', action='store_true', help='Disable memory pinning')

    # 带有默认值的参数(不再是必选)
    parser.add_argument('--image',
                        default="./example.png",  # 编辑的图片地址
                        help='编辑的图片地址')
    parser.add_argument('--resolution',
                        default="1280,720",  # 默认正方形分辨率
                        help='图像分辨率,格式为"宽度,高度",例如"1280,720",默认值为"1024,1024"')
    parser.add_argument('--output',
                        default='./output.png',
                        help='生成图像的保存路径,例如"output.png"')
    parser.add_argument('--output_dir',
                        default='/data/sharedpvc',
                        help='生成图像的保存完整路径目录,用于多张图片,例如"output.png"')
    parser.add_argument('--num_images',
                        default=1,
                        help='生成图像数量,用于多张图片,例如 4')
    parser.add_argument('--prompt',
                        default='金发美女在咖啡店喝咖啡,杯子上写着"Love" ',
                        help='图像生成的提示词')

    # 可选参数,有默认值(None)
    parser.add_argument('--gpus',
                        default='1',
                        help='要使用的显卡编号,用逗号分隔,例如"0,1,2",默认使用所有可用显卡')
    # 新增:推理步数参数,带有默认值
    parser.add_argument('--steps',
                        type=int,
                        default=30,
                        help='推理步数,默认值为30,值越大生成质量可能越高但速度越慢')

    return parser.parse_args()

def generate_image_by_qwen(
        args1
):
    num_images=args1.num_images
    output_dir=args1.output_dir
    output_path=args1.output
    # 处理分辨率参数
    try:
        width, height = map(int, args1.resolution.split(','))
        resolution = (width, height)
    except ValueError:
        print("错误:分辨率格式不正确,请使用'宽度,高度'格式,例如'1280,720'")
        exit(1)

    # 处理显卡参数
    use_gpus = None
    if args1.gpus:
        try:
            use_gpus = list(map(int, args1.gpus.split(',')))
        except ValueError:
            print("错误:显卡编号格式不正确,请使用逗号分隔的数字,例如'0,1,2'")
            exit(1)
    # 设置环境变量解决通信问题
    os.environ["NCCL_P2P_DISABLE"] = "1"
    os.environ["NCCL_IB_DISABLE"] = "1"
    os.environ["TORCH_CUDNN_V8_API_ENABLED"] = "1"

    # 配置显卡可见性
    if use_gpus is not None and isinstance(use_gpus, list) and len(use_gpus) > 0:
        os.environ["CUDA_VISIBLE_DEVICES"] = ",".join(map(str, use_gpus))
    else:
        # 自动检测可用显卡
        num_gpus = torch.cuda.device_count()

    with no_init_weights():
        transformer = QwenImageTransformer2DModel.from_config(
            QwenImageTransformer2DModel.load_config(
                str(transformer_config_path),
            ),
        ).to(torch.bfloat16)

    DFloat11Model.from_pretrained(
        "/data/sharedpvc/modelscope/hub/models/DFloat11/Qwen-Image-DF11",
        device="cpu",
        cpu_offload=args1.cpu_offload,
        pin_memory=not args1.no_pin_memory,
        bfloat16_model=transformer,
    )

    pipe = DiffusionPipeline.from_pretrained(
        model_local_path,
        transformer=transformer,
        torch_dtype=torch.bfloat16,
    )
    pipe.enable_model_cpu_offload()
    # 初始化加速器
    accelerator = Accelerator()

    positive_magic = {
        "en": "Ultra HD, 4K, cinematic composition.", # for english prompt,
        "zh": "超清,4K,电影级构图" # for chinese prompt,
    }

    # 提取分辨率参数
    width, height = resolution
    with torch.no_grad():
        with accelerator.autocast():
            results = pipe(
                prompt=args1.prompt + positive_magic['zh'],
                negative_prompt="low quality, blurry, text distortion",
                width=width,
                height=height,
                num_inference_steps=30,
                true_cfg_scale=3.0,
                generator=torch.Generator(device=accelerator.device).manual_seed(42)
            )
        print(f"图像生成完成 size: {len(results.images)}")
        # 检查并创建输出目录
        if not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)
            print(f"创建输出目录: {output_dir}")
        # 存储所有生成的图片路径
        output_paths = []
        if output_path:
            results.images[0].save(output_path)
            output_paths.append(output_path)
        else:
            for i, image in enumerate(results.images):
                output_path = os.path.join(output_dir, f"output_{i + 1}.png")
                image.save(output_path)
                output_paths.append(output_path)

    max_memory = torch.cuda.max_memory_allocated()
    print(f"Max memory: {max_memory / (1000 ** 3):.2f} GB")
    return True, output_paths



if __name__ == "__main__":
    # 记录开始时间
    start_time = time.time()
    # 解析命令行参数
    args = parse_args()
    # 调用生成函数
    result = generate_image_by_qwen(args)
    result = json.dumps({"files": result[1]})
    # 打印包含list[str]的JSON
    print(f"generate end:{result}")

    # 计算并打印耗时
    end_time = time.time()
    elapsed_time = end_time - start_time
    KAFKA_LOGGER.info(f"args:{args}, cost: {elapsed_time:.2f}秒")  # 保留两位小数

总结

目前只开源了文生图的部分,不过用不了多久就会开源图生图了,官方也反馈在计划中了。

每天更新实在太快了,deepseek开源开始引起了文本大模型的质变,而阿里这次开源的qwen-image和wan2.2对多模态生成又一次进步。用不了多久,多模态模型的平价时代也会来的。

低成本的AI工具越多,就容易普及,全民AI的时代真的快来了。

文章参考

https://www.modelscope.cn/models/Qwen/Qwen-Image

https://www.modelscope.cn/models/DiffSynth-Studio/Qwen-Image-Distill-Full

https://www.modelscope.cn/models/DFloat11/Qwen-Image-DF11

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐