调通 Fooocus 的 Gradio 接口

AI 画图相信有兴趣的朋友已经玩了一阵子了,我也在玩,用着比较好用的工具是 fooocus, 可以让我这种对大模型通了九窍的家伙也能轻松上手,不过当我想批量执行图生图的时候, 却犯了难:官方没有计划支援批量处理,那我们只能自己动手了。 今天我们来完成第一步:把 fooocus 的接口调通。

环境

事先声明,我的 python 水平基本为 0,所以相关的处理可能会比较简单粗暴, 请各位见谅,水平有限。

python

首先还是要准备一下 python 的环境, 由于最新版的 python 使用 pip 安装 gradio client 会有问题, 所以,我安装了 python 3.11.5 :

接下来直接安装 gradio client 就好,我没有特别选择版本号:

fooocus

fooocus 每次运行会自动检查更新,目前我的版本是 2.3.0:

我这里是直接运行 run.bat。请注意每次更新后,甚至采用不同的 preset 运行, fooocus 的接口可能会发生一些变化, 所以如果目前你的 fooocus 与我当时的 fooocus 版本不同, 那么可能我给出的代码就没有办法直接使用,这时需要按照下文描述的步骤更新一下代码。

调通 Fooocus API

Fooocus 的本地页面的底部有一个「Use via API」的连接, 看上去是用来介绍 API 如何使用对不对,不要高兴太早,点进去你就会发现, 这个页面的内容似乎是自动生成的,也没有太多可用的信息:

可怕的是官方也没有一个像样的说明,不然也不会有我这篇文章。虽说可用信息不多, 但是关键的信息是有的,首先我们要寻找到传参最多的接口:

再次声明,fn_index 和参数的数量和排序根据 fooocus 版本和预设的不同可能会有差异, 我们第一步就是要把这段代码复制到一个 python 文件,然后把它调通到没有报错。

熟悉 python 的应该不必我多说,不熟悉的话,容我唠叨一下, 贴过去的代码直接跑是跑不通的,有几个问题:

  1. "704×1408 <span style="color: grey;"> ∣ 1:2</span>" 这其实不是一个标准的字符串,因为引号之中还有引号,简单一点可以改成 "704×1408 <span style='color: grey;'> ∣ 1:2</span>" 不过我没有验证这一点是否有效,只是不再报错了
  2. 上图中的灰色字体其实都是注解,但是因为某种原因断行了,需要我们手工去掉断行
  3. random seed 其实是一个字符串格式的数字,我直接填了 "0"
  4. 代码中对图像的引用是以网址形式(https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png)给出的,这个链接是有效的,不过本文中我是清空了

解决了以上四个问题,使用 python 执行这个文件后,应该不会有报错,但是同时, 我们发现 fooocus 应用其实也没有开始画图,所以换句话说, 可能 gradio client 还没有把图片发送给 fooocus,只是本地记录了配置。

所以我们还需要接口,来通知 fooocus 干活,那么最像的接口是这个:

看上去这个接口返回了完成图像和预览,那么很有可能是这个接口, 我们把调用加在上面 python 文件中:

from gradio_client import Client
client = Client("http://127.0.0.1:7865/")

result = client.predict(
  ...
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)

再执行这个文件,你就看到 fooocus 在干活了,不过 gradio client 会有一长串的报错:

能力有限,我看不出这个报错是什么问题,但是图片已经生出来了, 在 fooocus output 目录:

非常写意的一张图,我甚至看不出来它画的是什么,诡异的是, 即使我们反复修改看着像提示词的参数,它也不会有明显的变化,不过很快我意识到, 是因为参数的默认值,其实不是 fooocus 的默认值,所以我们要去 fooocus 界面, 把界面上的设定和函数的传参对应起来,这是一个繁琐的过程,我们简单总结一下。

函数的参数对应设定有以下几种:

  1. 文本框 Textbox:字符串,一般为提示词
  2. 多选框 Checkbox:布尔值,表示是否
  3. 单选框 Radio:字符串,表示单选项的值
  4. 下拉菜单 Dropdown:字符串,与单选类似
  5. 滑杆 Slider:数字,表示一个区间变化的数字
  6. 多选组 Checkbox Group:字符串列表,明显的例子是选择多种风格
  7. 图像 Image:字符串,图像的路径或 url

基本上所有参数都可以在界面中找到对应的设定,繁琐的过程我们就不展开了, 以下是 2.3.0 的两组设定,对应参数含义写在注解中:

run 默认配置

from gradio_client import Client

client = Client("http://127.0.0.1:7865/")

# Textbox: string
# Checkbox: bool
# Radio: string
# Dropdown: string
# Slider: float | int
# Checkboxgroup: list[string]
# Image: filepath or URL to image

result = client.predict(
	False,	# 'Generate Image Grid for Each Batch' Checkbox
	"a girl sitting in chair",	# 'Prompt' Textbox
	"",	# 'Negative Prompt' Textbox
    # 'Selected Styles' Checkboxgroup
	["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp", "Fooocus Negative"],
	"Speed",	# 'Performance' Radio
	"704×1408 <span style='color: grey;'> ∣ 1:2</span>",	# 'Aspect Ratios' Radio
	1,		# 'Image Number' Slider [1,32]
	"png",	# 'Output Format' Radio
	"0",	# 'Seed' Textbox
    False,	# 'Read wildcards in order' Checkbox
	2,		# 'Image Sharpness' Slider [0.0,30.0]
	4,		#  'Guidance Scale' Slider [1.0,30.0]
	"juggernautXL_v8Rundiffusion.safetensors",	# 'Base Model (SDXL only)' Dropdown
	"None",	# 'Refiner (SDXL or SD 1.5)' Dropdown
	0.1,	# 'Refiner Switch At' Slider [0.1,1.0]
	True,	# 'LoRA 1 Enable' Checkbox
	"sd_xl_offset_example-lora_1.0.safetensors",	# 'LoRA 1' Dropdown
	0.1,	# 'LoRA 1 Weight' Slider [-2,2]
	True,	# 'LoRA 2 Enable' Checkbox
	"None",	# 'LoRA 2' Dropdown
	1,		# 'LoRA 2 Weight' Slider [-2,2]
	True,	# 'LoRA 3 Enable' Checkbox
	"None",	# 'LoRA 3' Dropdown
	1,		# 'LoRA 3 Weight' Slider [-2,2]
	True,	# 'LoRA 4 Enable' Checkbox
	"None",	# 'LoRA 4' Dropdown
	1,		# 'LoRA 4 Weight' Slider [-2,2]
	True,	# 'LoRA 5 Enable' Checkbox
	"None",	# 'LoRA 5' Dropdown component
	1,		# 'LoRA 5 Weight' Slider [-2,2]
	False,	#'Input Image' Checkbox
	"",		# 'parameter_91' Textbox? maybe: Upscale or Variation Prompt
	"Disabled",	# 'Upscale or Variation:' Radio
	"",			# 'Upscale or Variation' Image
	["Left"],	# 'Outpaint Direction' Checkboxgroup
	"",		# 'Inpaint or Outpaint' Image
	"",		# 'Inpaint Additional Prompt' Textbox
	"",		# 'Inpaint or Outpaint Mask Upload' Image
	True,	# 'Developer Debug Mode: Disable Preview' Checkbox
	True,	# 'Developer Debug Mode: Disable Intermediate Results' Checkbox
	True,	# 'Developer Debug Mode: Disable seed increment' Checkbox
	1.5,	# 'Developer Debug Mode: Positive ADM Guidance Scaler' Slider [0.1,3.0]
	0.8,	# 'Developer Debug Mode: Negative ADM Guidance Scaler' Slider [0.1,3.0]
	0.3,	# 'Developer Debug Mode: ADM Guidance End At Step' Slider [0.0,1.0]
	7,		# 'Developer Debug Mode: CFG Mimicking from TSNR' Slider [1.0,30.0]
	"dpmpp_2m_sde_gpu",	# 'Developer Debug Mode: Sampler' Dropdown
	"karras",	# 'Developer Debug Mode: Scheduler' Dropdown
	-1,	# 'Developer Debug Mode: Forced Overwrite of Sampling Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Refiner Switch Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Width' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Height' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Vary"' Slider [-1,1.0]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Upscale"' Slider [-1,1.0]
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Vary/Upscale' Checkbox
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Inpaint' Checkbox
	False,	# 'Developer Debug Mode: Debug Preprocessors' Checkbox
	False,	# 'Developer Debug Mode: Skip Preprocessors' Checkbox
	64,		# 'Developer Debug Mode: Canny Low Threshold' Slider [1,255]
	128,	# 'Developer Debug Mode: Canny High Threshold' Slider [1,255]
	"joint",	# 'Developer Debug Mode: Refiner swap method' Dropdown
	0.25,	# 'Developer Debug Mode: Softness of ControlNet' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: FreeU Enabled' Checkbox
	1.01,	# 'Developer Debug Mode: FreeU B1' Slider [0,2]
	1.02,	# 'Developer Debug Mode: FreeU B2' Slider [0,2]
	0.99,	# 'Developer Debug Mode: FreeU S1' Slider [0,4]
	0.95,	# 'Developer Debug Mode: FreeU S2' Slider [0,4]
	False,	# 'Developer Debug Mode: Debug Inpaint Preprocessing' Checkbox
	False,	# 'Developer Debug Mode: Disable initial latent in inpaint' Checkbox
	"v2.6",	# 'Developer Debug Mode: Inpaint Engine' Dropdown
	1,		# 'Developer Debug Mode: Inpaint Denoising Strength' Slider [0.0,1.0]
	0.618,	# 'Developer Debug Mode: Inpaint Respective Field' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: Enable Mask Upload' Checkbox
	False,	# 'Developer Debug Mode: Invert Mask' Checkbox
	0,		# 'Developer Debug Mode: Mask Erode or Dilate' Slider [-64,64]
	False,	# 'Developer Debug Mode: Save Metadata to Images' Checkbox
	"fooocus",	# 'Metadata Scheme' Radio
	"",				# 'Image Prompt Image 1' Image component
	0,				# 'Image Prompt Image 1 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 1 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 1 Type' Radio
	"",				# 'Image Prompt Image 2' Image component
	0,				# 'Image Prompt Image 2 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 2 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 2 Type' Radio
	"",				# 'Image Prompt Image 3' Image component
	0,				# 'Image Prompt Image 3 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 3 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 3 Type' Radio
	"",				# 'Image Prompt Image 4' Image component
	0,				# 'Image Prompt Image 4 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 4 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 4 Type' Radio
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)
# print(result)

run_anime 默认配置

from gradio_client import Client

client = Client("http://127.0.0.1:7865/")

# Textbox: string
# Checkbox: bool
# Radio: string
# Dropdown: string
# Slider: float | int
# Checkboxgroup: list[string]
# Image: filepath or URL to image

result = client.predict(
	False,	# 'Generate Image Grid for Each Batch' Checkbox
	"a girl sitting in chair",	# 'Prompt' Textbox
	"",	# 'Negative Prompt' Textbox
    # 'Selected Styles' Checkboxgroup
	["Fooocus V2", "Fooocus Semi Realistic", "Fooocus Masterpiece"],
	"Speed",	# 'Performance' Radio
	"704×1408 <span style='color: grey;'> ∣ 1:2</span>",	# 'Aspect Ratios' Radio
	1,		# 'Image Number' Slider [1,32]
	"png",	# 'Output Format' Radio
	"0",	# 'Seed' Textbox
    False,	# 'Read wildcards in order' Checkbox
	2,		# 'Image Sharpness' Slider [0.0,30.0]
	7,		#  'Guidance Scale' Slider [1.0,30.0]
	"animaPencilXL_v100.safetensors",	# 'Base Model (SDXL only)' Dropdown
	"None",	# 'Refiner (SDXL or SD 1.5)' Dropdown
	0.1,	# 'Refiner Switch At' Slider [0.1,1.0]
	True,	# 'LoRA 1 Enable' Checkbox
	"None",	# 'LoRA 1' Dropdown
	1,	# 'LoRA 1 Weight' Slider [-2,2]
	True,	# 'LoRA 2 Enable' Checkbox
	"None",	# 'LoRA 2' Dropdown
	1,		# 'LoRA 2 Weight' Slider [-2,2]
	True,	# 'LoRA 3 Enable' Checkbox
	"None",	# 'LoRA 3' Dropdown
	1,		# 'LoRA 3 Weight' Slider [-2,2]
	True,	# 'LoRA 4 Enable' Checkbox
	"None",	# 'LoRA 4' Dropdown
	1,		# 'LoRA 4 Weight' Slider [-2,2]
	True,	# 'LoRA 5 Enable' Checkbox
	"None",	# 'LoRA 5' Dropdown component
	1,		# 'LoRA 5 Weight' Slider [-2,2]
	False,	#'Input Image' Checkbox
	"",		# 'parameter_91' Textbox? maybe: Upscale or Variation Prompt
	"Disabled",	# 'Upscale or Variation:' Radio
	"",			# 'Upscale or Variation' Image
	["Left"],	# 'Outpaint Direction' Checkboxgroup
	"",		# 'Inpaint or Outpaint' Image
	"",		# 'Inpaint Additional Prompt' Textbox
	"",		# 'Inpaint or Outpaint Mask Upload' Image
	True,	# 'Developer Debug Mode: Disable Preview' Checkbox
	True,	# 'Developer Debug Mode: Disable Intermediate Results' Checkbox
	True,	# 'Developer Debug Mode: Disable seed increment' Checkbox
	1.5,	# 'Developer Debug Mode: Positive ADM Guidance Scaler' Slider [0.1,3.0]
	0.8,	# 'Developer Debug Mode: Negative ADM Guidance Scaler' Slider [0.1,3.0]
	0.3,	# 'Developer Debug Mode: ADM Guidance End At Step' Slider [0.0,1.0]
	7,		# 'Developer Debug Mode: CFG Mimicking from TSNR' Slider [1.0,30.0]
	"dpmpp_2m_sde_gpu",	# 'Developer Debug Mode: Sampler' Dropdown
	"karras",	# 'Developer Debug Mode: Scheduler' Dropdown
	-1,	# 'Developer Debug Mode: Forced Overwrite of Sampling Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Refiner Switch Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Width' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Height' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Vary"' Slider [-1,1.0]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Upscale"' Slider [-1,1.0]
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Vary/Upscale' Checkbox
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Inpaint' Checkbox
	False,	# 'Developer Debug Mode: Debug Preprocessors' Checkbox
	False,	# 'Developer Debug Mode: Skip Preprocessors' Checkbox
	64,		# 'Developer Debug Mode: Canny Low Threshold' Slider [1,255]
	128,	# 'Developer Debug Mode: Canny High Threshold' Slider [1,255]
	"joint",	# 'Developer Debug Mode: Refiner swap method' Dropdown
	0.25,	# 'Developer Debug Mode: Softness of ControlNet' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: FreeU Enabled' Checkbox
	1.01,	# 'Developer Debug Mode: FreeU B1' Slider [0,2]
	1.02,	# 'Developer Debug Mode: FreeU B2' Slider [0,2]
	0.99,	# 'Developer Debug Mode: FreeU S1' Slider [0,4]
	0.95,	# 'Developer Debug Mode: FreeU S2' Slider [0,4]
	False,	# 'Developer Debug Mode: Debug Inpaint Preprocessing' Checkbox
	False,	# 'Developer Debug Mode: Disable initial latent in inpaint' Checkbox
	"v2.6",	# 'Developer Debug Mode: Inpaint Engine' Dropdown
	1,		# 'Developer Debug Mode: Inpaint Denoising Strength' Slider [0.0,1.0]
	0.618,	# 'Developer Debug Mode: Inpaint Respective Field' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: Enable Mask Upload' Checkbox
	False,	# 'Developer Debug Mode: Invert Mask' Checkbox
	0,		# 'Developer Debug Mode: Mask Erode or Dilate' Slider [-64,64]
	False,	# 'Developer Debug Mode: Save Metadata to Images' Checkbox
	"fooocus",	# 'Metadata Scheme' Radio
	"",				# 'Image Prompt Image 1' Image component
	0,				# 'Image Prompt Image 1 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 1 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 1 Type' Radio
	"",				# 'Image Prompt Image 2' Image component
	0,				# 'Image Prompt Image 2 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 2 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 2 Type' Radio
	"",				# 'Image Prompt Image 3' Image component
	0,				# 'Image Prompt Image 3 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 3 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 3 Type' Radio
	"",				# 'Image Prompt Image 4' Image component
	0,				# 'Image Prompt Image 4 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 4 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 4 Type' Radio
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)
# print(result)

用这套程序,我们就可以用提示词画图了。

再唠叨一下,由于 api 的接口并不稳定,所以如果版本发生变化, 我们就要再和界面对一下参数了。

总结

目前我们做到了用接口指挥 fooocus 画图,看上去应该向批量生图的目标更近了一步。 接下来,我们来看一下如何用接口来进行图生图的操作。