调通 Fooocus 的 Gradio 接口

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

English Version

I’ve noticed a number of non-Chinese readers reaching here. An English version of this article is posted here for the convenience.

环境

事先声明,我的 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 画图,看上去应该向批量生图的目标更近了一步。 接下来,我们来看一下如何用接口来进行图生图的操作。