python调用 stable diffusion批量生成图片代码解析
文中大多数内容来源github,版权属于原作者,
1. 基础环境
在windows上做示例,
- 本地要安装了python
- python的pip模块 安装 webuiapi
- 编辑器 pyCharm 2024.2(community Edition)
2. 如果上述条件跳过本节安装
2.1 下载并安装 python
https://www.python.org/
2.2 安装webuiapi
D:\Python\Python310\python.exe -m pip install webuiapi
2.3 pycharm
3. 代码参考
参考网站
解释说明
3.1 sdwebuiapi
API client for AUTOMATIC1111/stable-diffusion-webuiAUTOMATIC1111/stable-diffusion-webui 的 API 客户端
支持 txt2img、img2img、extra-single-image、extra-batch-images API 调用。
必须从 webui 启用 API 支持。在运行 webui 时添加 --api。这里解释了。
您可以使用 --api-auth user1:pass1,user2:pass2 选项为 api 访问启用身份验证。(由于是基本的 http 认证,密码以明文形式传输)
截至 2022 年 11 月 21 日,API 调用(几乎)是 http://127.0.0.1:7860/docs 的直接翻译。
我使用了秋叶启动器.
3.2 用法
webuiapi_demo.ipynb 包含带有原始图像的示例代码。在本文档中,图像被压缩为 jpeg。
3.2.1 create API client 创建 API 客户端
# 导入 webuiapi 包
import webuiapi
# 创建 API 客户端
api = webuiapi.WebUIApi()
# 使用自定义主机和端口创建 API 客户端
#api = webuiapi.WebUIApi(host='127.0.0.1', port=7860)
# 使用自定义主机、端口和 https 创建 API 客户端
#api = webuiapi.WebUIApi(host='webui.example.com', port=443, use_https=True)
# 使用默认的采样器和步数创建 API 客户端。
#api = webuiapi.WebUIApi(sampler='Euler a', steps=20)
# 如果 webui 上设置了 --api-auth=username:password,则可以选择设置用户名和密码。
# 注意:用户名和密码不受保护,如果通信通道未加密,则很容易被破解。
# 你也可以将用户名和密码传递给 WebUIApi 构造函数。
api.set_auth('用户名', '密码')
# 从 webuiapi 文件夹中使用 webuiapi.py
import sys
sys.path.append('./webuiapi')
# 或者使用 pip 安装 webuiapi
# pip install webuiapi
import webuiapi
# api = webuiapi.WebUIApi()
api = webuiapi.WebUIApi(host='127.0.0.1',port=7860,sampler='Euler a',steps=20)
3.2.2 文生图
# 文字转图片
result1 = api.txt2img(prompt="可爱的松鼠",
negative_prompt="丑陋的,画面之外的",
seed=1003,
styles=["动漫风格"],
cfg_scale=7,
# sampler_index='DDIM', # 可选参数,未使用
# steps=30, # 可选参数,未使用
)
result1.image # 图片结果
3.2.3 图片转图片
result2 = api.img2img(images=[result1.image], prompt="可爱的猫", seed=5555, cfg_scale=6.5, denoising_strength=0.6)
result2.image
# 转换后的图片结果
这段代码表示的是使用某个API(可能是与图像生成或编辑相关的API)将一张图片(result1.image)根据给定的文字提示(prompt="可爱的猫")和其他参数转换成另一张图片。其中,seed是用于生成图片的随机种子,以确保结果的可重复性;cfg_scale可能是控制生成图片质量或细节的参数;denoising_strength可能是控制去噪强度的参数,以影响生成图片的平滑度或细节保留程度。
3.2.4 使用img2img进行图像修复(补全)
# 使用img2img进行图像修复(补全)
从PIL库导入Image和ImageDraw模块
from PIL import Image, ImageDraw
# 创建一个与result2.image相同尺寸的新图像,颜色为黑色,用作遮罩
mask = Image.new('RGB', result2.image.size, color='black')
# 注意:下面这行代码被注释掉了,因为它会复制result2.image作为遮罩,而不是创建一个新的黑色图像
# mask = result2.image.copy()
# 使用ImageDraw在遮罩上绘制
draw = ImageDraw.Draw(mask)
# 绘制一个椭圆,位置在(210,150)到(310,250),填充为白色
draw.ellipse((210,150,310,250), fill='white')
# 绘制另一个椭圆,位置在(80,120)到(160,200),填充为白色
draw.ellipse((80,120,160,120+80), fill='white')
# 遮罩图像已准备好
# 使用img2img函数进行图像修复(补全)
inpainting_result = api.img2img(images=[result2.image],
mask_image=mask, # 传入遮罩图像
inpainting_fill=1, # 可能表示启用图像补全功能
prompt="可爱的猫", # 文字提示,用于指导图像补全的内容
seed=104, # 随机种子,用于确保结果的可重复性
cfg_scale=5.0, # 控制生成图片质量或细节的参数
denoising_strength=0.7) # 控制去噪强度的参数
# 获取图像修复(补全)后的结果
inpainting_result.image
这段代码展示了如何使用一个API(api)的img2img函数来进行图像修复(或称为图像补全)。首先,它创建了一个与原始图像(result2.image)相同尺寸的黑色图像作为遮罩,然后在遮罩上绘制了两个白色的椭圆区域。这些白色区域表示需要被修复(或补全)的部分。接着,img2img函数被调用,传入原始图像、遮罩图像、一些配置参数(如inpainting_fill、prompt、seed、cfg_scale和denoising_strength)来生成修复后的图像。最后,代码通过inpainting_result.image获取并可能显示或保存修复后的图像。
3.2.5 对单张图片进行额外处理(如超分辨率放大)
# 对单张图片进行额外处理(如超分辨率放大)
result3 = api.extra_single_image(image=result2.image, # 输入图片为result2.image
upscaler_1="ESRGAN_4x", # 使用的第一个超分辨率放大模型为ESRGAN,放大倍数为4倍
upscaling_resize=1.5) # 在超分辨率放大后,对图片进行额外的缩放,缩放比例为1.5倍
# 打印处理后的图片尺寸
print(result3.image.size)
# 显示或进一步处理处理后的图片
result3.image
在这段代码中,api.extra_single_image函数被用于对单张图片进行额外处理,这里的处理主要是超分辨率放大。image参数指定了要处理的图片,upscaler_1参数指定了使用的超分辨率放大模型(这里是ESRGAN,放大倍数为4倍),而upscaling_resize参数则指定了在超分辨率放大后,对图片进行额外的缩放的比例(这里是1.5倍)。
处理完成后,函数返回了一个包含处理结果的对象(这里假设为result3),通过result3.image可以访问处理后的图片。此外,还通过print(result3.image.size)打印了处理后的图片尺寸,以便了解图片在经过超分辨率放大和额外缩放后的具体大小。
3.2.6 显示或进一步处理处理后的图片
result4 = api.extra_batch_images(images=[result1.image,
result2.image],upscaler_1="ESRGAN_4x",upscaling_resize=1.5)len(result4.images)
2
result4.images[0]
result4.images[1]
3.2.7 txt2img with scripts
XYPlotAvailableScripts = ["Nothing","Seed","Var. seed","Var. strength","Steps","CFG Scale","Prompt S/R","Prompt order","Sampler","Checkpoint Name","Hypernetwork","Hypernet str.","Sigma Churn","Sigma min","Sigma max","Sigma noise","Eta","Clip skip","Denoising","Hires upscaler","Cond. Image Mask Weight","VAE","Styles"]
# 示例调用
# 设置X轴类型为“Steps”
XAxisType = "Steps"
# 设置X轴的值,这里表示32和64两个步数点
XAxisValues = "32,64"
# 设置Y轴类型为“Sampler”
YAxisType = "Sampler"
# 设置Y轴的值,这里表示三种不同的采样器:k_euler_a, ddim, k_dpm_2_a
YAxisValues = "k_euler_a, ddim, k_dpm_2_a"
# 设置是否绘制图例,这里为True表示绘制
drawLegend = "True"
# 设置是否包含单独的图像,这里为False表示不包含
includeSeparateImages = "False"
# 设置是否保持随机种子不变,这里为False表示不保持
keepRandomSeed = "False"
# 使用txt2img函数根据提供的参数生成图片
result5 = api.txt2img(
prompt="可爱的松鼠", # 文字提示,用于指导图片生成的内容
negative_prompt="丑陋的,画面之外的", # 负面提示,用于排除不希望出现在图片中的内容
seed=1003, # 随机种子,用于确保结果的可重复性
cfg_scale=7, # 控制生成图片质量或细节的参数
script_name="X/Y Plot", # 指定使用的脚本名称,这里表示要生成X/Y折线图
script_args=[ # 脚本所需的参数列表
XYPlotAvailableScripts.index(XAxisType), # X轴类型在可用脚本中的索引
XAxisValues, # X轴的值
XYPlotAvailableScripts.index(YAxisType), # Y轴类型在可用脚本中的索引
YAxisValues, # Y轴的值
drawLegend, # 是否绘制图例
includeSeparateImages, # 是否包含单独的图像
keepRandomSeed # 是否保持随机种子不变
]
)
# 获取生成的图片
result5.image
3.2.8 webuiapi的常用函数
# return map of current options
options = api.get_options()
# change sd model
options = {}
options['sd_model_checkpoint'] = 'model.ckpt [7460a6fa]'
api.set_options(options)
# when calling set_options, do not pass all options returned by get_options().
# it makes webui unusable (2022/11/21).
# get available sd models
api.get_sd_models()
# misc get apis
api.get_samplers()
api.get_cmd_flags()
api.get_hypernetworks()
api.get_face_restorers()
api.get_realesrgan_models()
api.get_prompt_styles()
api.get_artist_categories() # deprecated ?
api.get_artists() # deprecated ?
api.get_progress()
api.get_embeddings()
api.get_cmd_flags()
api.get_scripts()
api.get_schedulers()
api.get_memory()
# misc apis
api.interrupt()
api.skip()
3.2.9 Utility methods 实用程序方法
# 保存当前模型名称
old_model = api.util_get_current_model()
# 获取可用模型列表
models = api.util_get_model_names()
# 获取可用采样器列表
# api.util_get_sampler_names() (此行为一个函数调用,无输出注释)
# 获取可用调度器列表
# api.util_get_scheduler_names() (此行为一个函数调用,无输出注释)
# 刷新模型列表
api.refresh_checkpoints()
# 设置模型(使用确切名称)
api.util_set_model(models[0])
# 设置模型(查找最接近的匹配项)
api.util_set_model('robodiffusion')
# 等待作业完成
api.util_wait_for_ready()
# 获取当前模型(函数名,非代码行)
# util_get_current_model (注意:这是一个函数名,若要调用需加上api.前缀及括号,如api.util_get_current_model())
3.2.10 LORA 和 alwayson_scripts 示例
# 调用 api.txt2img 函数生成图片
r = api.txt2img(
prompt='photo of a cute girl with green hair <lora:Moxin_10:0.6> shuimobysim __juice__', # 文字提示,包含LORA模型和shuimobysim的提示词
seed=1000, # 随机种子,确保结果的可重复性
save_images=True, # 保存生成的图片
alwayson_scripts={"Simple wildcards":[]} # 始终开启的脚本,但此处wildcards扩展不接受额外参数
)
# 通过 r.image 访问生成的图片
r.image
# 注意:以下是一个函数名,并非直接执行的代码
# 若要获取当前模型,应调用 api.util_get_current_model() 函数
util_get_current_model # 这是一个函数,用于获取当前使用的模型名称
3.2.11 扩展支持 - Model-Keyword
Bash |
ModelKeywordResult(keywords=['nousr robot'], model='robo-diffusion-v1.ckpt', oldhash='41fef4bd', match_source='model-keyword.txt')
ModelKeywordResult(keywords=['nousr robot'], model='robo-diffusion-v1.ckpt', oldhash='41fef4bd', match_source='model-keyword.txt')
3.2.12 扩展支持 - Instruct-Pix2Pix
# Instruct-Pix2Pix 扩展现已弃用,并已成为 webui 的一部分。
# 当加载 instruct-pix2pix 模型时,您可以使用带有 image_cfg_scale 参数的普通 img2img 功能。
r = api.img2img(prompt='sunset', images=[pil_img], cfg_scale=7.5, image_cfg_scale=1.5)
# 上述代码行调用了 img2img 函数,并生成了名为 r 的结果对象,其中包含了生成的图像。
r.image # 通过 r.image 可以访问生成的图像。
# 获取当前模型的工具函数(注意:这是一个函数名,用于说明,不是直接执行的代码)
# 若要调用此函数以获取当前加载的模型名称,应使用 api.util_get_current_model()
util_get_current_model # 此处仅作为函数名展示,实际使用时需通过 api 调用
3.2.13 扩展支持 - ControlNet
# https://github.com/Mikubill/sd-webui-controlnet
api.controlnet_model_list()
['control_v11e_sd15_ip2p [c4bb465c]',
'control_v11e_sd15_shuffle [526bfdae]',
'control_v11f1p_sd15_depth [cfd03158]',
'control_v11p_sd15_canny [d14c016b]',
'control_v11p_sd15_inpaint [ebff9138]',
'control_v11p_sd15_lineart [43d4be0d]',
'control_v11p_sd15_mlsd [aca30ff0]',
'control_v11p_sd15_normalbae [316696f1]',
'control_v11p_sd15_openpose [cab727d4]',
'control_v11p_sd15_scribble [d4ba51ff]',
'control_v11p_sd15_seg [e1f51eb9]',
'control_v11p_sd15_softedge [a8575a2a]',
'control_v11p_sd15s2_lineart_anime [3825e83e]',
'control_v11u_sd15_tile [1f041471]']
['control_v11e_sd15_ip2p [c4bb465c]','control_v11e_sd15_shuffle [526bfdae]','control_v11f1p_sd15_depth [cfd03158]','control_v11p_sd15_canny [d14c016b]','control_v11p_sd15_inpaint [ebff9138]','control_v11p_sd15_lineart [43d4be0d]','control_v11p_sd15_mlsd [aca30ff0]','control_v11p_sd15_normalbae [316696f1]','control_v11p_sd15_openpose [cab727d4]','control_v11p_sd15_scribble [d4ba51ff]','control_v11p_sd15_seg [e1f51eb9]','control_v11p_sd15_softedge [a8575a2a]','control_v11p_sd15s2_lineart_anime [3825e83e]','control_v11u_sd15_tile [1f041471]']
api.controlnet_version()
api.controlnet_module_list()
普通txt2img
r = api.txt2img(prompt="photo of a beautiful girl with blonde hair", height=512, seed=100)
img = r.image
img
# 创建一个ControlNetUnit实例,用于指定控制网络的类型和模型
# 注意:这里的'image'参数是新的API要求,用于接收要处理的图像
# 'module'指定了控制网络的类型(例如,边缘检测'canny')
# 'model'指定了具体的控制网络模型
unit1 = webuiapi.ControlNetUnit(image=img, module='canny', model='control_v11p_sd15_canny [d14c016b]')
# 使用txt2img函数生成图像,该函数接收文本提示和控制网络单元列表
# 'prompt'参数是指导图像生成的文本描述
# 'controlnet_units'参数包含了用于图像生成的控制网络单元
r = api.txt2img(prompt="photo of a beautiful girl", controlnet_units=[unit1])
# 显示或处理生成的图像
r.image
# img2img with multiple ControlNets
unit1 = webuiapi.ControlNetUnit(image=img, module='canny', model='control_v11p_sd15_canny [d14c016b]')
unit2 = webuiapi.ControlNetUnit(image=img, module='depth', model='control_v11f1p_sd15_depth [cfd03158]', weight=0.5)
r2 = api.img2img(prompt="girl",
images=[img],
width=512,
height=512,
controlnet_units=[unit1, unit2],
sampler_name="Euler a",
cfg_scale=7,
)
r2.image
Bash |
3.2.14 扩展支持 - AnimateDiff
# https://github.com/continue-revolution/sd-webui-animatediff
# 创建一个AnimateDiff对象,用于生成动画差异图像
adiff = webuiapi.AnimateDiff(
model='mm_sd15_v3.safetensors', # 指定使用的模型
video_length=24, # 设置动画的视频长度(帧数)
closed_loop='R+P', # 设置循环方式,'R+P'可能表示某种特定的循环逻辑
format=['GIF'] # 指定输出格式为GIF
)
# 使用txt2img函数生成动画图像,传入AnimateDiff对象作为参数
r = api.txt2img(prompt='可爱的小狗', animatediff=adiff)
# 保存GIF文件。注意,为了保存动画GIF,需要设置save_all=True
r.image.save('小狗.gif', save_all=True)
# 在Jupyter笔记本中显示动画GIF
# 从IPython.display导入HTML类
from IPython.display import HTML
# 使用HTML类显示动画GIF,通过base64编码将图像数据嵌入到HTML中
HTML('<img src="data:image/gif;base64,{0}"/>'.format(r.json['images'][0]))
# util_get_current_model(此行代码为注释或说明,并非实际代码)
# 这是一个工具函数或方法的名称,用于获取当前正在使用的模型(此处未给出具体实现)
- 在上面的代码中,webuiapi.AnimateDiff 和 api.txt2img 是假设存在的函数或方法,它们可能是某个特定库(如sd-webui-animatediff)的一部分。在实际使用中,你需要确保已经正确安装了该库,并且了解这些函数或方法的具体用法和参数。
- r.json['images'][0] 这部分代码假设r对象有一个json属性,该属性是一个字典,其中包含一个images键,该键对应的值是一个列表,列表中的第一个元素是动画GIF的base64编码字符串。这取决于api.txt2img函数的返回值结构。在实际使用中,你需要根据该函数的返回值结构来访问动画GIF的数据。
- 在Jupyter笔记本中显示动画GIF时,使用HTML类并嵌入base64编码的图像数据是一种常见的方法。但是,如果动画GIF较大或帧数较多,这种方法可能会导致Jupyter笔记本的性能下降或加载时间变长。在这种情况下,你可能需要考虑其他方法来显示动画GIF,比如将动画GIF保存到文件系统中,并在Jupyter笔记本中使用<img>标签直接引用该文件。
- util_get_current_model 这部分更像是一个说明或注释,而不是实际可执行的代码。如果你需要获取当前正在使用的模型信息,你需要查找该库提供的相应函数或方法。
3.2.15 扩展支持 - RemBG (由 webcoderz 提供)
Bash |
3.2.16 扩展支持 - SegmentAnything(由 TimNekk 提供)
3.2.17 扩展支持 - ADetailer(由 tomj2ee 和 davidmartinrius 提供)
# https://github.com/continue-revolution/sd-webui-segment-anything
# 初始化 SegmentAnything 接口
segment = webuiapi.SegmentAnythingInterface(api)
# 使用SAM模型及点信息进行分割预测
sam_result = segment.sam_predict(
image=img, # 输入图像
sam_positive_points=[(0.5, 0.25), (0.75, 0.75)], # SAM模型的正向点
# 根据需要添加其他参数
)
# 使用GroundingDINO和SAM模型进行分割预测
sam_result2 = segment.sam_predict(
image=img, # 输入图像
dino_enabled=True, # 启用GroundingDINO
dino_text_prompt="GroundingDINO的文本提示", # GroundingDINO的文本提示
# 根据需要添加其他参数
)
# 示例:对掩码进行膨胀处理
dilation_result = segment.dilate_mask(
image=img, # 输入图像
mask=sam_result.masks[0], # 使用SAM预测中的第一个掩码
dilate_amount=30 # 膨胀量
)
# 示例:生成带类别ID的语义分割
semantic_seg_result = segment.sam_and_semantic_seg_with_cat_id(
image=img, # 输入图像
category="1+2+3", # 用'+'分隔的类别ID
# 根据需要添加其他参数
)
# 获取当前模型(这是一个函数或方法,不是直接执行的代码)
# 注意:在实际代码中,应使用如 api.util_get_current_model() 的形式来调用
# 此处仅作为示例说明,并未直接执行
util_get_current_model
txt2img with ADetailer txt2img 与 ADetailer
# https://github.com/Bing-su/adetailer
import webuiapi
api = webuiapi.WebUIApi()
ads = webuiapi.ADetailer(ad_model="face_yolov8n.pt")
result1 = api.txt2img(prompt="cute squirrel",
negative_prompt="ugly, out of frame",
seed=-1,
styles=["anime"],
cfg_scale=7,
adetailer=[ads],
steps=30,
enable_hr=True,
denoising_strength=0.5
)
img = result1.image
img
# OR
file_path = "output_image.png"
result1.image.save(file_path)
img2img with ADetailer img2img 与 ADetailer
import webuiapi
from PIL import Image
img = Image.open("/path/to/your/image.jpg")
ads = webuiapi.ADetailer(ad_model="face_yolov8n.pt")
api = webuiapi.WebUIApi()
result1 = api.img2img(
images=[img],
prompt="a cute squirrel",
steps=25,
seed=-1,
cfg_scale=7,
denoising_strength=0.5,
resize_mode=2,
width=512,
height=512,
adetailer=[ads],
)
file_path = "img2img_output_image.png"
result1.image.save(file_path)
3.2.18 支持使用 “deepdanbooru / deepbooru” 进行询问(由 davidmartinrius 提供)
Bash |
3.2.19 支持 ReActor,用于换脸(由 davidmartinrius 提供)
import webuiapi
from PIL import Image
img = Image.open("/path/to/your/image.jpg")
api = webuiapi.WebUIApi()
your_desired_face = Image.open("/path/to/your/desired/face.jpeg")
reactor = webuiapi.ReActor(
img=your_desired_face,
enable=True
)
result1 = api.img2img(
images=[img],
prompt="a cute squirrel",
steps=25,
seed=-1,
cfg_scale=7,
denoising_strength=0.5,
resize_mode=2,
width=512,
height=512,
reactor=reactor
)
file_path = "face_swapped_image.png"
result1.image.save(file_path)
3.2.20 支持自我注意指导(由 yano 提供)
import webuiapi
from PIL import Image
img = Image.open("/path/to/your/image.jpg")
api = webuiapi.WebUIApi()
your_desired_face = Image.open("/path/to/your/desired/face.jpeg")
sag = webuiapi.Sag(
enable=True,
scale=0.75,
mask_threshold=1.00
)
result1 = api.img2img(
images=[img],
prompt="a cute squirrel",
steps=25,
seed=-1,
cfg_scale=7,
denoising_strength=0.5,
resize_mode=2,
width=512,
height=512,
sag=sag
)
file_path = "face_swapped_image.png"
result1.image.save(file_path)
3.2.21 David Martin Rius 的提示生成器 API:
Bash |
3.2.21.1 从用户界面
3.2.21.2 从命令行
Bash |
Bash |
3.2.22 使用 Flux David Martin Rius 的提示:
在这两种情况下,都需要 cfg_scale = 1,sampler_name = “Euler”,scheduler = “Simple” 并且在 txt2img 中 enable_hr=False
对于 txt2img
import webuiapi
result1 = api.txt2img(prompt="cute squirrel",
negative_prompt="ugly, out of frame",
seed=-1,
styles=["anime"],
cfg_scale=1,
steps=20,
enable_hr=False,
denoising_strength=0.5,
sampler_name= "Euler",
scheduler= "Simple"
)
img = result1.image
img
# OR
file_path = "output_image.png"
result1.image.save(file_path)
对于 img2img
import webuiapi
from PIL import Image
img = Image.open("/path/to/your/image.jpg")
api = webuiapi.WebUIApi()
result1 = api.img2img(
images=[img],
prompt="a cute squirrel",
steps=20,
seed=-1,
cfg_scale=1,
denoising_strength=0.5,
resize_mode=2,
width=512,
height=512,
sampler_name= "Euler",
scheduler= "Simple"
)
file_path = "face_swapped_image.png"
result1.image.save(file_path)
4. 基础技术储备
4.1 Pillow