文生图开源王者 Qwen-Image:实战代码与量化代码独家分享
鲨疯了,上周陆续几个重磅开源,阿里云和openai陆续加入了战场,都是非商用显卡可以跑的,太炸裂了。文本模型:openai_gpt-oss 文本生成,文生图:Qwen-Image文生图,文/图生视频: 通义万相2.2-图生视频。今天重点体验一下Qwen-Image文生图。
大家好,我是烤鸭:
鲨疯了,上周陆续几个重磅开源,阿里云和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
更多推荐
所有评论(0)