diff --git a/README.md b/README.md
index 5b20ac3..17927b8 100644
--- a/README.md
+++ b/README.md
@@ -194,6 +194,8 @@ For Fooocus CMD flags, see [here](https://github.com/lllyasviel/Fooocus?tab=read
# Change log
+**[24/01/03] v0.3.28** : add text-to-image-with-ip interface
+
**[23/12/29] v0.3.27** : Add describe interface,now you can get prompt from image
**[23/12/29] v0.3.27** : Add query job hitory api. Add webhook_url support for each generation request.
diff --git a/README_zh.md b/README_zh.md
index ae75462..b488cbb 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -194,6 +194,8 @@ python main.py --all-in-fp16 --always-gpu
# 更新日志
+**[24/01/03] v0.3.28** : 增加 text-to-image-with-ip 接口
+
**[23/12/29] v0.3.27** : 增加 describe 接口,现在你可以使用图像反推提示词了
**[23/12/29] v0.3.27** : 增加查询历史 API。增加 webhook_url 对所有请求的支持
diff --git a/docs/api_doc_en.md b/docs/api_doc_en.md
index e98c0d2..3154ebc 100644
--- a/docs/api_doc_en.md
+++ b/docs/api_doc_en.md
@@ -4,6 +4,7 @@
- [image-upscale-vary](#image-upscale-vary)
- [image-inpaint-outpaint](#image-inpaint-outpaint)
- [image-prompt](#image-prompt)
+ - [text-to-image-with-imageprompt](#text-to-image-with-imageprompt)
- [describe](#describe)
- [all-models](#all-models)
- [refresh-models](#refresh-models)
@@ -24,7 +25,9 @@
# Introduction
-Fooocus API are provided 13 REST interfaces now, I roughly divide it into two categories, the first is the ability to call Fooocus, such as generating images, refreshing models, and so on, and the second is related to Fooocus API itself, mainly related to task queries. I will try to illustrate their role and usage and provide examples in the following content.
+Fooocus API are provided more than a dozen REST interfaces now, I roughly divide it into two categories, the first is the ability to call Fooocus, such as generating images, refreshing models, and so on, and the second is related to Fooocus API itself, mainly related to task queries. I will try to illustrate their role and usage and provide examples in the following content.
+
+> Almost all interface parameters have default values, which means you only need to send the parameters you are interested in. The complete parameters and default values can be viewed in the table.
# Fooocus capability related interfaces
@@ -59,6 +62,7 @@ DataType: json
| advanced_params | AdvacedParams | Adavanced params, [AdvancedParams](#advanceparams) |
| require_base64 | bool | require base64, default to False |
| async_process | bool | is async, default to False |
+| webhook_url | str | after async task completed, address for callback, default to None, refer to [webhook](#webhook) |
**response params:**
@@ -68,80 +72,22 @@ This interface returns a universal response structure, refer to [response](#resp
**request example:**
-
- example params
-
- ```python
- params = {
- "prompt": "a girl in the ground",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weights": 0.1
- }
- ],
- "advanced_params": {
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.6,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "inpaint_engine": "v1",
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95
- },
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-example code (Python):
```python
-def generate(params: dict) -> dict:
+host = "http://127.0.0.1:8888"
+
+def text2img(params: dict) -> dict:
"""
text to image
"""
- date = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/text-to-image",
- data=date,
- timeout=30)
- return response.json()
+ result = requests.post(url=f"{host}/v1/generation/text-to-image",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
+ return result.json()
+
+result =text2img({
+ "prompt": "1girl sitting on the ground",
+ "async_process": True})
+print(result)
```
## image-upscale-vary
@@ -165,8 +111,8 @@ DataType: form|json
**requests params**
-| Name | Type | Description |
-| ---- | ---- |-------------------------------------------------------------------------------------------------------------------------------------------|
+| Name | Type | Description |
+| ---- | ---- |---------------------------|
| input_image | string($binary) | binary imagge |
| uov_method | Enum | 'Vary (Subtle)','Vary (Strong)','Upscale (1.5x)','Upscale (2x)','Upscale (Fast 2x)','Upscale (Custom)' |
| upscale_value | float | default to None , 1.0-5.0, magnification, only for uov_method is 'Upscale (Custom)' |
@@ -180,48 +126,28 @@ This interface returns a universal response structure, refer to [response](#resp
**requests example:**
-
- example params
-
- ```python
- params = {
- "uov_method": "Upscale (2x)",
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
+```python
+# headers should not contain {"Content-Type": "application/json"}
-example code(Python):
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
-```python
-def upscale(input_image: bytes, params: dict) -> dict:
+def upscale_vary(image, params: dict) -> dict:
"""
- upscale or vary
+ Upscale or Vary
"""
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/image-upscale-vary",
- data=params,
- files={"input_image": input_image},
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-upscale-vary",
+ data=params,
+ files={"input_image": image})
return response.json()
-```
+result =upscale_vary(image=image,
+ params={
+ "uov_method": "Upscale (2x)",
+ "async_process": True
+ })
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
### V2
@@ -239,85 +165,27 @@ This interface returns a universal response structure, refer to [response](#resp
**requests params:**
-
- example params
-
- ```python
- params = {
- "prompt": "a girl in the ground",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weights": 0.1
- }
- ],
- "advanced_params": {
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.6,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "inpaint_engine": "v1",
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95
- },
- "require_base64": False,
- "async_process": True,
- "uov_method": "Upscale (2x)",
- "input_image": ""
- }
- ```
-
-
-
-
-example code(Python):
-
```python
-def upscale_vary(image, params = params) -> dict:
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def upscale_vary(image, params: dict) -> dict:
"""
Upscale or Vary
"""
- params["input_image"] = image
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-upscale-vary",
- data=data,
- headers=headers,
+ params["input_image"] = base64.b64encode(image).decode('utf-8')
+ response = requests.post(url=f"{host}/v2/generation/image-upscale-vary",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"},
timeout=300)
return response.json()
+
+result =upscale_vary(image=image,
+ params={
+ "uov_method": "Upscale (2x)",
+ "async_process": True
+ })
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## image-inpaint-outpaint
@@ -340,7 +208,7 @@ DataType: form|json
| input_image | string($binary) | binary imagge |
| input_mask | string($binary) | binary imagge |
| inpaint_additional_prompt | string | additional_prompt |
-| outpaint_selections | List | Image extension direction , 'Left', 'Right', 'Top', 'Bottom' seg with comma |
+| outpaint_selections | str | Image extension direction , 'Left', 'Right', 'Top', 'Bottom' seg with comma |
| outpaint_distance_left | int | Image extension distance, default to 0 |
| outpaint_distance_right | int | Image extension distance, default to 0 |
| outpaint_distance_top | int | Image extension distance, default to 0 |
@@ -355,56 +223,39 @@ This interface returns a universal response structure, refer to [response](#resp
**requests example:**
-
- example params
-
- ```python
- params = {
- "inpaint_additional_prompt": "",
- "outpaint_selections": "Left,Right",
- "outpaint_distance_left": 0,
- "outpaint_distance_right": 0,
- "outpaint_distance_top": 0,
- "outpaint_distance_bottom": 0,
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-example code(Python):
-
```python
-def inpaint_outpaint(input_image: bytes, params: dict, input_mask: bytes = None) -> dict:
+# example for inpaint outpaint v1
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def inpaint_outpaint(params: dict, input_image: bytes, input_mask: bytes = None) -> dict:
"""
- inpaint or outpaint
+ example for inpaint outpaint v1
"""
- response = requests.post(url="http://127.0.0.1:8888//v1/generation/image-inpait-outpaint",
- data=params,
- files={"input_image": input_image,
- "input_mask": input_mask,},
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-inpait-outpaint",
+ data=params,
+ files={"input_image": input_image,
+ "input_mask": input_mask})
return response.json()
-```
-
-> this params only show `outpaint`, `inpaint` need two image, And choose whether to proceed simultaneously as needed `outpaint`, in addition, `inpaint` without `prompt` the effect is manifested as removing elements, It can be used to remove clutter and watermarks in images, and adding 'prompt' can be used to replace elements in images
+# image extension example
+result = inpaint_outpaint(params={
+ "outpaint_selections": "Left,Right",
+ "async_process": True},
+ input_image=image,
+ input_mask=None)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image inpaint example
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+result = inpaint_outpaint(params={
+ "prompt": "a cat",
+ "async_process": True},
+ input_image=source,
+ input_mask=mask)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
### V2
@@ -427,103 +278,47 @@ This interface returns a universal response structure, refer to [response](#resp
**requests example:**
-
- example params
-
- ```python
- params = {
- "prompt": "",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weight": 0.1
- }
- ],
- "advanced_params": {
- "disable_preview": False,
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.8,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95,
- "debugging_inpaint_preprocessor": False,
- "inpaint_disable_initial_latent": False,
- "inpaint_engine": "v1",
- "inpaint_strength": 1,
- "inpaint_respective_field": 1
- },
- "require_base64": False,
- "async_process": False,
- "input_image": "",
- "input_mask": None,
- "inpaint_additional_prompt": None,
- "outpaint_selections": []
- "outpaint_distance_left": 0,
- "outpaint_distance_right": 0,
- "outpaint_distance_top": 0,
- "outpaint_distance_bottom": 0
- }
- ```
-
-
-
-
-example code(Python):
-
```python
-def inpaint_outpaint(input_image: str, input_mask: str = None, params = params) -> dict:
+# example for inpaint outpaint v2
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def inpaint_outpaint(params: dict) -> dict:
"""
- Inpaint or Outpaint
+ example for inpaint outpaint v2
"""
- params["input_image"] = input_image
- params["input_mask"] = input_mask
- params["outpaint_selections"] = ["Left", "Right"]
- params["prompt"] = "cat"
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-inpaint-outpaint",
- data=data,
- headers=headers,
- timeout=300)
+ response = requests.post(url=f"{host}/v2/generation/image-inpait-outpaint",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
return response.json()
+
+# image extension example
+result = inpaint_outpaint(params={
+ "input_image": base64.b64encode(image).decode('utf-8'),
+ "input_mask": None,
+ "outpaint_selections": ["Left", "Right"],
+ "async_process": True})
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image inpaint example
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+result = inpaint_outpaint(params={
+ "prompt": "a cat",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ "input_mask": base64.b64encode(mask).decode('utf-8'),
+ "async_process": True})
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## image-prompt
+`v0.3.27` has a break change. Interface based on change to [inpaint-outpaint](#image-inpaint-outpaint)
+
+after v0.3.27, this interface implements the functions of `inpaint_outpaint` and `image-prompt`.
+
+> Multi-function interface, which does not implement the functions of `inpaint_outpaint` and `image-prompt` at the same time in the same request
+
**base info:**
```yaml
@@ -537,8 +332,16 @@ DataType: form|json
**requests params**
-| Name | Type | Description |
-| ---- | ---- |---------------------------------------------------------------------------------------------------------------------------------|
+| Name | Type | Description |
+| ---- | ---- |--------------------------------|
+| input_image | Bytes | binary image, use for inpaint |
+| input_mask | Bytes | binary image mask, use for inpaint |
+| inpaint_additional_prompt | str | inpaint additional prompt |
+| outpaint_selections | str | Image extension direction , 'Left', 'Right', 'Top', 'Bottom' seg with comma |
+| outpaint_distance_left | int | Image extension distance, default to 0 |
+| outpaint_distance_right | int | Image extension distance, default to 0 |
+| outpaint_distance_top | int | Image extension distance, default to 0 |
+| outpaint_distance_bottom | int | Image extension distance, default to 0 |
| cn_img1 | string($binary) | binary image |
| cn_stop1 | float | default to 0.6 |
| cn_weight1 | float | default to 0.6 |
@@ -565,66 +368,70 @@ This interface returns a universal response structure, refer to [response](#resp
**requests example:**
-
- example params
-
- ```python
- params = {
- "cn_stop1": 0.6,
- "cn_weight1": 0.6,
- "cn_type1": "ImagePrompt",
- "cn_stop2": 0.6,
- "cn_weight2": 0.6,
- "cn_type2": "ImagePrompt",
- "cn_stop3": 0.6,
- "cn_weight3": 0.6,
- "cn_type3": "ImagePrompt",
- "cn_stop4": 0.6,
- "cn_weight4": 0.6,
- "cn_type4": "ImagePrompt",
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-example code(Python):
-
```python
-def image_prompt(cn_img1: bytes,
- cn_img2: bytes = None,
- cn_img3: bytes = None,
- cn_img4: bytes = None,
- params: dict = {}) -> dict:
+# image_prompt v1 example
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+
+def image_prompt(params: dict,
+ input_iamge: bytes,
+ input_mask: bytes=None,
+ cn_img1: bytes=None,
+ cn_img2: bytes=None,
+ cn_img3: bytes=None,
+ cn_img4: bytes=None,) -> dict:
"""
- image_prompt
+ image prompt
"""
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/image-prompt",
- data=params,
- files={
- "cn_img1": cn_img1,
- "cn_img2": cn_img2,
- "cn_img3": cn_img3,
- "cn_img4": cn_img4
- },
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-prompt",
+ data=params,
+ files={
+ "input_image": input_iamge,
+ "input_mask": input_mask,
+ "cn_img1": cn_img1,
+ "cn_img2": cn_img2,
+ "cn_img3": cn_img3,
+ "cn_img4": cn_img4,
+ })
return response.json()
+
+# image extend
+params = {
+ "outpaint_selections": ["Left", "Right"],
+ "image_prompts": [] # 必传参数,可以为空列表
+}
+result = image_prompt(params=params, input_iamge=image)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# inpaint
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "image_prompts": [], # required, can be empty list
+ "async_process": True
+}
+result = image_prompt(params=params, input_iamge=source, input_mask=mask)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image prompt
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "image_prompts": [
+ {
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }]
+ }
+result = image_prompt(params=params, input_iamge=image, cn_img1=image, cn_img2=source)
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
### V2
@@ -633,6 +440,14 @@ def image_prompt(cn_img1: bytes,
| Name | Type | Description |
| ---- | ---- |-------------------------------------------------|
+| input_image | str | base64 image, use for inpaint |
+| input_mask | str | base64 image mask, use for inpaint |
+| inpaint_additional_prompt | str | inpaint additional prompt |
+| outpaint_selections | List[] | Image extension direction , 'Left', 'Right', 'Top', 'Bottom' seg with comma |
+| outpaint_distance_left | int | Image extension distance, default to 0 |
+| outpaint_distance_right | int | Image extension distance, default to 0 |
+| outpaint_distance_top | int | Image extension distance, default to 0 |
+| outpaint_distance_bottom | int | Image extension distance, default to 0 |
| image_prompts | List[ImagePrompt] | image list, include config, ImagePrompt struct: |
**ImagePrompt**
@@ -650,104 +465,118 @@ This interface returns a universal response structure, refer to [response](#resp
**requests example:**
-
- example params
-
- ```python
- params = {
- "prompt": "",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weight": 0.1
- }
- ],
- "advanced_params": {
- "disable_preview": False,
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.8,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95,
- "debugging_inpaint_preprocessor": False,
- "inpaint_disable_initial_latent": False,
- "inpaint_engine": inpaint_engine,
- "inpaint_strength": 1,
- "inpaint_respective_field": 1
- },
- "require_base64": False,
- "async_process": False,
- "image_prompts": []
- }
- ```
-
+```python
+# image_prompt v2 example
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+
+def image_prompt(params: dict) -> dict:
+ """
+ image prompt
+ """
+ response = requests.post(url=f"{host}/v2/generation/image-prompt",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
+ return response.json()
-
+# image extend
+params = {
+ "input_image": base64.b64encode(image).decode('utf-8'),
+ "outpaint_selections": ["Left", "Right"],
+ "image_prompts": [] # required, can be empty list
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
-example code(Python):
+# inpaint
-```python
-img_prompt = [
- {
- "cn_img": image_base64,
- "cn_stop": 0.6,
- "cn_weight": 0.6,
- "cn_type": "ImagePrompt"
- },{
- "cn_img": s_base64,
- "cn_stop": 0.6,
- "cn_weight": 0.6,
- "cn_type": "ImagePrompt"
+params = {
+ "prompt": "1girl sitting on the chair",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ "input_mask": base64.b64encode(mask).decode('utf-8'),
+ "image_prompts": [], # required, can be empty list
+ "async_process": True
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image prompt
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ # input_image here is useless,but is required。may be a bug
+ "image_prompts": [
+ {
+ "cn_img": base64.b64encode(source).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_img": base64.b64encode(image).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }]
}
-]
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
+
+## text to image with imageprompt
+
+this interface only provides v2 version
+
+**base info:**
+
+```yaml
+EndPoint: /v2/generation/text-to-image-with-ip
+Method: Post
+DataType: json
+```
+
+**requests params**
-def image_prompt(img_prompt: list, params: dict) -> dict:
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| image_prompts | List[ImagePrompt] | 图像列表 |
+
+**requests example**:
+
+```python
+# text to image with imageprompt example
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+def image_prompt(params: dict) -> dict:
"""
- Image Prompt
+ image prompt
"""
- params["prompt"] = "cat"
- params["image_prompts"] = img_prompt
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-prompt",
- data=data,
- headers=headers,
- timeout=300)
+ response = requests.post(url=f"{host}/v2/generation/text-to-image-with-ip",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
return response.json()
+
+params = {
+ "prompt": "A bear",
+ "image_prompts": [
+ {
+ "cn_img": base64.b64encode(source).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_img": base64.b64encode(image).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }
+ ]
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## describe
diff --git a/docs/api_doc_zh.md b/docs/api_doc_zh.md
index ac9f691..602f230 100644
--- a/docs/api_doc_zh.md
+++ b/docs/api_doc_zh.md
@@ -4,6 +4,7 @@
- [图像放大 | image-upscale-vary](#图像放大--image-upscale-vary)
- [局部重绘 | image-inpaint-outpaint](#局部重绘--image-inpaint-outpaint)
- [图生图 | image-prompt](#图生图--image-prompt)
+ - [text-to-image-with-imageprompt](#text-to-image-with-imageprompt)
- [图像反推 | describe](#图像反推--describe)
- [列出模型 | all-models](#列出模型--all-models)
- [刷新模型 | refresh-models](#刷新模型--refresh-models)
@@ -24,9 +25,9 @@
# 简介
-> 除了目前还不支持的 Describe, Fooocus API可以完整的使用其他任意功能
+Fooocus API 目前提供了十多个 REST 接口, 我大致将其分为两类, 第一类用来调用 Fooocus 的能力, 比如生成图像、刷新模型之类的, 第二类为 Fooocus API 自身相关的, 主要是任务查询相关。我会在接下来的内容中尝试说明它们的作用以及用法并提供示例。
-Fooocus API 目前提供了 12 个 REST 接口, 我大致将其分为两类, 第一类用来调用 Fooocus 的能力, 比如生成图像、刷新模型之类的, 第二类为 Fooocus API 自身相关的, 主要是任务查询相关。我会在接下来的内容中尝试说明它们的作用以及用法并提供示例。
+> 几乎所有的接口参数都有默认值,这意味着你只需要发送你感兴趣的参数即可。完整的参数以及默认值可以通过表格查看
# Fooocus 能力相关接口
@@ -61,6 +62,7 @@ DataType: json
| advanced_params | AdvacedParams | 高级参数, AdvancedParams 结构 [AdvancedParams](#高级参数--advanceparams) |
| require_base64 | bool | 是否返回base64编码, 默认 False |
| async_process | bool | 是否异步处理, 默认 False |
+| webhook_url | str | 异步处理完成后, 触发的 webhook 地址, 参考[webhook](#webhook) |
**响应参数:**
@@ -70,80 +72,22 @@ DataType: json
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "prompt": "a girl in the ground",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weights": 0.1
- }
- ],
- "advanced_params": {
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.6,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "inpaint_engine": "v1",
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95
- },
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-示例代码(Python):
```python
-def generate(params: dict) -> dict:
+host = "http://127.0.0.1:8888"
+
+def text2img(params: dict) -> dict:
"""
文生图
"""
- date = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/text-to-image",
- data=date,
- timeout=30)
- return response.json()
+ result = requests.post(url=f"{host}/v1/generation/text-to-image",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
+ return result.json()
+
+result =text2img({
+ "prompt": "1girl sitting on the ground",
+ "async_process": True})
+print(result)
```
## 图像放大 | image-upscale-vary
@@ -182,48 +126,28 @@ DataType: form|json
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "uov_method": "Upscale (2x)",
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
+```python
+# 不要加 {"Content-Type": "application/json"} 这个 header
-示例代码(Python):
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
-```python
-def upscale(input_image: bytes, params: dict) -> dict:
+def upscale_vary(image, params: dict) -> dict:
"""
- upscale or vary
+ Upscale or Vary
"""
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/image-upscale-vary",
- data=params,
- files={"input_image": input_image},
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-upscale-vary",
+ data=params,
+ files={"input_image": image})
return response.json()
-```
+result =upscale_vary(image=image,
+ params={
+ "uov_method": "Upscale (2x)",
+ "async_process": True
+ })
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
### V2
@@ -241,85 +165,27 @@ def upscale(input_image: bytes, params: dict) -> dict:
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "prompt": "a girl in the ground",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weights": 0.1
- }
- ],
- "advanced_params": {
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.6,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "inpaint_engine": "v1",
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95
- },
- "require_base64": False,
- "async_process": True,
- "uov_method": "Upscale (2x)",
- "input_image": ""
- }
- ```
-
-
-
-
-示例代码(Python):
-
```python
-def upscale_vary(image, params = params) -> dict:
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def upscale_vary(image, params: dict) -> dict:
"""
Upscale or Vary
"""
- params["input_image"] = image
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-upscale-vary",
- data=data,
- headers=headers,
+ params["input_image"] = base64.b64encode(image).decode('utf-8')
+ response = requests.post(url=f"{host}/v2/generation/image-upscale-vary",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"},
timeout=300)
return response.json()
+
+result =upscale_vary(image=image,
+ params={
+ "uov_method": "Upscale (2x)",
+ "async_process": True
+ })
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## 局部重绘 | image-inpaint-outpaint
@@ -342,7 +208,7 @@ DataType: form|json
| input_image | string($binary) | 二进制 str 图像 |
| input_mask | string($binary) | 二进制 str 图像 |
| inpaint_additional_prompt | string | 附加描述 |
-| outpaint_selections | List | 图像扩展方向, 逗号分割的 'Left', 'Right', 'Top', 'Bottom' |
+| outpaint_selections | str | 图像扩展方向, 逗号分割的 'Left', 'Right', 'Top', 'Bottom' |
| outpaint_distance_left | int | 图像扩展距离, 默认 0 |
| outpaint_distance_right | int | 图像扩展距离, 默认 0 |
| outpaint_distance_top | int | 图像扩展距离, 默认 0 |
@@ -357,56 +223,39 @@ DataType: form|json
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "inpaint_additional_prompt": "",
- "outpaint_selections": "Left,Right",
- "outpaint_distance_left": 0,
- "outpaint_distance_right": 0,
- "outpaint_distance_top": 0,
- "outpaint_distance_bottom": 0,
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-示例代码(Python):
-
```python
-def inpaint_outpaint(input_image: bytes, params: dict, input_mask: bytes = None) -> dict:
+# 局部重绘 v1 接口示例
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def inpaint_outpaint(params: dict, input_image: bytes, input_mask: bytes = None) -> dict:
"""
- inpaint or outpaint
+ 局部重绘 v1 接口示例
"""
- response = requests.post(url="http://127.0.0.1:8888//v1/generation/image-inpait-outpaint",
- data=params,
- files={"input_image": input_image,
- "input_mask": input_mask,},
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-inpait-outpaint",
+ data=params,
+ files={"input_image": input_image,
+ "input_mask": input_mask})
return response.json()
-```
-
-> 该参数仅展示了 `outpaint`, `inpaint` 需要上传两张图片, 并根据需要选择是否同时进行 `outpaint`, 此外, `inpaint` 如果不加任何 `prompt` 效果表现为去除元素, 可以用来移除图中杂物、水印, 添加 `prompt` 可以用来替换图中元素
+# 图片扩展示例
+result = inpaint_outpaint(params={
+ "outpaint_selections": "Left,Right",
+ "async_process": True},
+ input_image=image,
+ input_mask=None)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# 局部重绘示例
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+result = inpaint_outpaint(params={
+ "prompt": "a cat",
+ "async_process": True},
+ input_image=source,
+ input_mask=mask)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
### V2
@@ -429,103 +278,47 @@ def inpaint_outpaint(input_image: bytes, params: dict, input_mask: bytes = None)
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "prompt": "",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weight": 0.1
- }
- ],
- "advanced_params": {
- "disable_preview": False,
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.8,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95,
- "debugging_inpaint_preprocessor": False,
- "inpaint_disable_initial_latent": False,
- "inpaint_engine": "v1",
- "inpaint_strength": 1,
- "inpaint_respective_field": 1
- },
- "require_base64": False,
- "async_process": False,
- "input_image": "",
- "input_mask": None,
- "inpaint_additional_prompt": None,
- "outpaint_selections": []
- "outpaint_distance_left": 0,
- "outpaint_distance_right": 0,
- "outpaint_distance_top": 0,
- "outpaint_distance_bottom": 0
- }
- ```
-
-
-
-
-示例代码(Python):
-
```python
-def inpaint_outpaint(input_image: str, input_mask: str = None, params = params) -> dict:
+# 局部重绘 v2 接口示例
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+
+def inpaint_outpaint(params: dict) -> dict:
"""
- Inpaint or Outpaint
+ 局部重绘 v1 接口示例
"""
- params["input_image"] = input_image
- params["input_mask"] = input_mask
- params["outpaint_selections"] = ["Left", "Right"]
- params["prompt"] = "cat"
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-inpaint-outpaint",
- data=data,
- headers=headers,
- timeout=300)
+ response = requests.post(url=f"{host}/v2/generation/image-inpait-outpaint",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
return response.json()
+
+# 图像扩展示例
+result = inpaint_outpaint(params={
+ "input_image": base64.b64encode(image).decode('utf-8'),
+ "input_mask": None,
+ "outpaint_selections": ["Left", "Right"],
+ "async_process": True})
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# 局部重绘示例
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+result = inpaint_outpaint(params={
+ "prompt": "a cat",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ "input_mask": base64.b64encode(mask).decode('utf-8'),
+ "async_process": True})
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## 图生图 | image-prompt
+该接口更新自 `v0.3.27` 后有重大更新。从继承自 [文生图](#文生图--text-to-image) 更改为继承自 [局部重绘](#局部重绘--image-inpaint-outpaint)
+
+该版本之后可以通过该接口实现 `inpaint_outpaint` 以及 `image-prompt` 接口的功能
+
+> 多功能接口,并非可以同时实现 `inpaint_outpaint` 以及 `image-prompt` 接口的功能
+
**基础信息:**
```yaml
@@ -539,8 +332,18 @@ DataType: form|json
**请求参数**
+> 注意: 虽然接口更改为继承自[局部重绘](#局部重绘--image-inpaint-outpaint), 但下方表格展示的仍然继承自[文生图](#文生图--text-to-image), 但参数是完整的
+
| Name | Type | Description |
| ---- | ---- | ----------- |
+| input_image | Bytes | 二进制图像, 用于局部重绘 |
+| input_mask | Bytes | 二进制图像遮罩, 用于局部重绘 |
+| inpaint_additional_prompt | str | inpaint 附加提示词 |
+| outpaint_selections | str | 图像扩展选项, 逗号分割的 "Left", "Right", "Top", "Bottom" |
+| outpaint_distance_left | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_right | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_top | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_bottom | int | 图像扩展距离, 默认 0 |
| cn_img1 | string($binary) | 二进制 str 图像 |
| cn_stop1 | float | 默认 0.6 |
| cn_weight1 | float | 默认 0.6 |
@@ -567,66 +370,70 @@ DataType: form|json
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "cn_stop1": 0.6,
- "cn_weight1": 0.6,
- "cn_type1": "ImagePrompt",
- "cn_stop2": 0.6,
- "cn_weight2": 0.6,
- "cn_type2": "ImagePrompt",
- "cn_stop3": 0.6,
- "cn_weight3": 0.6,
- "cn_type3": "ImagePrompt",
- "cn_stop4": 0.6,
- "cn_weight4": 0.6,
- "cn_type4": "ImagePrompt",
- "prompt": "",
- "negative_prompt": "",
- "style_selections": "",
- "performance_selection": "Speed",
- "aspect_ratios_selection": '1152*896',
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": None,
- "refiner_switch": 0.5,
- "loras": '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]',
- "advanced_params": '',
- "require_base64": False,
- "async_process": True
- }
- ```
-
-
-
-
-示例代码(Python):
-
```python
-def image_prompt(cn_img1: bytes,
- cn_img2: bytes = None,
- cn_img3: bytes = None,
- cn_img4: bytes = None,
- params: dict = {}) -> dict:
+# image_prompt v1 接口示例
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+
+def image_prompt(params: dict,
+ input_iamge: bytes,
+ input_mask: bytes=None,
+ cn_img1: bytes=None,
+ cn_img2: bytes=None,
+ cn_img3: bytes=None,
+ cn_img4: bytes=None,) -> dict:
"""
- image_prompt
+ image prompt
"""
- response = requests.post(url="http://127.0.0.1:8888/v1/generation/image-prompt",
- data=params,
- files={
- "cn_img1": cn_img1,
- "cn_img2": cn_img2,
- "cn_img3": cn_img3,
- "cn_img4": cn_img4
- },
- timeout=30)
+ response = requests.post(url=f"{host}/v1/generation/image-prompt",
+ data=params,
+ files={
+ "input_image": input_iamge,
+ "input_mask": input_mask,
+ "cn_img1": cn_img1,
+ "cn_img2": cn_img2,
+ "cn_img3": cn_img3,
+ "cn_img4": cn_img4,
+ })
return response.json()
+
+# 图像扩展
+params = {
+ "outpaint_selections": ["Left", "Right"],
+ "image_prompts": [] # 必传参数,可以为空列表
+}
+result = image_prompt(params=params, input_iamge=image)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# 局部重绘
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "image_prompts": [], # 必传参数,可以为空列表
+ "async_process": True
+}
+result = image_prompt(params=params, input_iamge=source, input_mask=mask)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image prompt
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "image_prompts": [
+ {
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }]
+ }
+result = image_prompt(params=params, input_iamge=image, cn_img1=image, cn_img2=source)
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
### V2
@@ -635,6 +442,14 @@ def image_prompt(cn_img1: bytes,
| Name | Type | Description |
| ---- | ---- | ----------- |
+| input_image | str | base64 图像, 用于局部重绘 |
+| input_mask | str | base64 图像遮罩, 用于局部重绘 |
+| inpaint_additional_prompt | str | inpaint 附加提示词 |
+| outpaint_selections | List[OutpaintExpansion] | 图像扩展选项, 逗号分割的 "Left", "Right", "Top", "Bottom" |
+| outpaint_distance_left | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_right | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_top | int | 图像扩展距离, 默认 0 |
+| outpaint_distance_bottom | int | 图像扩展距离, 默认 0 |
| image_prompts | List[ImagePrompt] | 图像列表, 包含配置, ImagePrompt 结构如下: |
**ImagePrompt**
@@ -652,104 +467,118 @@ def image_prompt(cn_img1: bytes,
**请求示例:**
-
- 示例参数
-
- ```python
- params = {
- "prompt": "",
- "negative_prompt": "",
- "style_selections": [
- "Fooocus V2",
- "Fooocus Enhance",
- "Fooocus Sharp"
- ],
- "performance_selection": "Speed",
- "aspect_ratios_selection": "1152*896",
- "image_number": 1,
- "image_seed": -1,
- "sharpness": 2,
- "guidance_scale": 4,
- "base_model_name": "juggernautXL_version6Rundiffusion.safetensors",
- "refiner_model_name": "None",
- "refiner_switch": 0.5,
- "loras": [
- {
- "model_name": "sd_xl_offset_example-lora_1.0.safetensors",
- "weight": 0.1
- }
- ],
- "advanced_params": {
- "disable_preview": False,
- "adm_scaler_positive": 1.5,
- "adm_scaler_negative": 0.8,
- "adm_scaler_end": 0.3,
- "refiner_swap_method": "joint",
- "adaptive_cfg": 7,
- "sampler_name": "dpmpp_2m_sde_gpu",
- "scheduler_name": "karras",
- "overwrite_step": -1,
- "overwrite_switch": -1,
- "overwrite_width": -1,
- "overwrite_height": -1,
- "overwrite_vary_strength": -1,
- "overwrite_upscale_strength": -1,
- "mixing_image_prompt_and_vary_upscale": False,
- "mixing_image_prompt_and_inpaint": False,
- "debugging_cn_preprocessor": False,
- "skipping_cn_preprocessor": False,
- "controlnet_softness": 0.25,
- "canny_low_threshold": 64,
- "canny_high_threshold": 128,
- "freeu_enabled": False,
- "freeu_b1": 1.01,
- "freeu_b2": 1.02,
- "freeu_s1": 0.99,
- "freeu_s2": 0.95,
- "debugging_inpaint_preprocessor": False,
- "inpaint_disable_initial_latent": False,
- "inpaint_engine": inpaint_engine,
- "inpaint_strength": 1,
- "inpaint_respective_field": 1
- },
- "require_base64": False,
- "async_process": False,
- "image_prompts": []
- }
- ```
-
+```python
+# image_prompt v2 接口示例
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+mask = open("./examples/imgs/m.png", "rb").read()
+
+def image_prompt(params: dict) -> dict:
+ """
+ image prompt
+ """
+ response = requests.post(url=f"{host}/v2/generation/image-prompt",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
+ return response.json()
-
+# 图像扩展
+params = {
+ "input_image": base64.b64encode(image).decode('utf-8'),
+ "outpaint_selections": ["Left", "Right"],
+ "image_prompts": [] # 必传参数,可以为空列表
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
-示例代码(Python):
+# 局部重绘
-```python
-img_prompt = [
- {
- "cn_img": image_base64,
- "cn_stop": 0.6,
- "cn_weight": 0.6,
- "cn_type": "ImagePrompt"
- },{
- "cn_img": s_base64,
- "cn_stop": 0.6,
- "cn_weight": 0.6,
- "cn_type": "ImagePrompt"
+params = {
+ "prompt": "1girl sitting on the chair",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ "input_mask": base64.b64encode(mask).decode('utf-8'),
+ "image_prompts": [], # 必传参数,可以为空列表
+ "async_process": True
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+
+# image prompt
+
+params = {
+ "prompt": "1girl sitting on the chair",
+ "input_image": base64.b64encode(source).decode('utf-8'),
+ # 这里的 input_image 无作用,但不可为空。大概是个 bug
+ "image_prompts": [
+ {
+ "cn_img": base64.b64encode(source).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_img": base64.b64encode(image).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }]
}
-]
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
+```
-def image_prompt(img_prompt: list, params: dict) -> dict:
+## text to image with imageprompt
+
+该接口暂无 v1 版本
+
+**基础信息:**
+
+```yaml
+EndPoint: /v2/generation/text-to-image-with-ip
+Method: Post
+DataType: json
+```
+
+**请求参数**
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| image_prompts | List[ImagePrompt] | 图像列表 |
+
+**请求示例**:
+
+```python
+# text to image with imageprompt 示例
+host = "http://127.0.0.1:8888"
+image = open("./examples/imgs/bear.jpg", "rb").read()
+source = open("./examples/imgs/s.jpg", "rb").read()
+def image_prompt(params: dict) -> dict:
"""
- Image Prompt
+ image prompt
"""
- params["prompt"] = "cat"
- params["image_prompts"] = img_prompt
- data = json.dumps(params)
- response = requests.post(url="http://127.0.0.1:8888/v2/generation/image-prompt",
- data=data,
- headers=headers,
- timeout=300)
+ response = requests.post(url=f"{host}/v2/generation/text-to-image-with-ip",
+ data=json.dumps(params),
+ headers={"Content-Type": "application/json"})
return response.json()
+
+params = {
+ "prompt": "A bear",
+ "image_prompts": [
+ {
+ "cn_img": base64.b64encode(source).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ },{
+ "cn_img": base64.b64encode(image).decode('utf-8'),
+ "cn_stop": 0.6,
+ "cn_weight": 0.6,
+ "cn_type": "ImagePrompt"
+ }
+ ]
+}
+result = image_prompt(params)
+print(json.dumps(result, indent=4, ensure_ascii=False))
```
## 图像反推 | describe
@@ -1144,5 +973,3 @@ uvicorn.run(app, host="0.0.0.0", port=8000)
| finish_reason | str | 任务结束原因 |
失败响应:
-
-
diff --git a/examples/examples.ipynb b/examples/examples.ipynb
new file mode 100644
index 0000000..c0d5a80
--- /dev/null
+++ b/examples/examples.ipynb
@@ -0,0 +1,368 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import requests\n",
+ "import json\n",
+ "import base64"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 文生图示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "\n",
+ "def text2img(params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " 文生图\n",
+ " \"\"\"\n",
+ " result = requests.post(url=f\"{host}/v1/generation/text-to-image\",\n",
+ " data=json.dumps(params),\n",
+ " headers={\"Content-Type\": \"application/json\"})\n",
+ " return result.json()\n",
+ "\n",
+ "result =text2img(\n",
+ " {\"prompt\": \"1girl sitting on the ground\",\n",
+ " \"async_process\": True}\n",
+ " )\n",
+ "print(result)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# upscale or vary v1 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "\n",
+ "def upscale_vary(image, params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " Upscale or Vary\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v1/generation/image-upscale-vary\",\n",
+ " data=params,\n",
+ " files={\"input_image\": image})\n",
+ " return response.json()\n",
+ "\n",
+ "result =upscale_vary(image=image,\n",
+ " params={\n",
+ " \"uov_method\": \"Upscale (2x)\",\n",
+ " \"async_process\": True\n",
+ " })\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# upscale or vary v2 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "\n",
+ "def upscale_vary(params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " Upscale or Vary\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v2/generation/image-upscale-vary\",\n",
+ " data=json.dumps(params),\n",
+ " headers={\"Content-Type\": \"application/json\"},\n",
+ " timeout=300)\n",
+ " return response.json()\n",
+ "\n",
+ "result =upscale_vary(image=image,\n",
+ " params={\n",
+ " \"input_iamge\": base64.b64encode(image).decode('utf-8'),\n",
+ " \"uov_method\": \"Upscale (2x)\",\n",
+ " \"async_process\": True\n",
+ " })\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 局部重绘 v1 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "\n",
+ "def inpaint_outpaint(params: dict, input_image: bytes, input_mask: bytes = None) -> dict:\n",
+ " \"\"\"\n",
+ " 局部重绘 v1 接口示例\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v1/generation/image-inpait-outpaint\",\n",
+ " data=params,\n",
+ " files={\"input_image\": input_image,\n",
+ " \"input_mask\": input_mask})\n",
+ " return response.json()\n",
+ "\n",
+ "\n",
+ "result = inpaint_outpaint(params={\n",
+ " \"outpaint_selections\": \"Left,Right\",\n",
+ " \"async_process\": True},\n",
+ " input_image=image,\n",
+ " input_mask=None)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "source = open(\"./imgs/s.jpg\", \"rb\").read()\n",
+ "mask = open(\"./imgs/m.png\", \"rb\").read()\n",
+ "result = inpaint_outpaint(params={\n",
+ " \"prompt\": \"a cat\",\n",
+ " \"async_process\": True},\n",
+ " input_image=source,\n",
+ " input_mask=mask)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 局部重绘 v2 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "\n",
+ "def inpaint_outpaint(params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " 局部重绘 v1 接口示例\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v2/generation/image-inpait-outpaint\",\n",
+ " data=json.dumps(params),\n",
+ " headers={\"Content-Type\": \"application/json\"})\n",
+ " return response.json()\n",
+ "\n",
+ "# 图像扩展示例\n",
+ "result = inpaint_outpaint(params={\n",
+ " \"input_image\": base64.b64encode(image).decode('utf-8'),\n",
+ " \"input_mask\": None,\n",
+ " \"outpaint_selections\": [\"Left\", \"Right\"],\n",
+ " \"async_process\": True})\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "# 局部重绘示例\n",
+ "source = open(\"./imgs/s.jpg\", \"rb\").read()\n",
+ "mask = open(\"./imgs/m.png\", \"rb\").read()\n",
+ "result = inpaint_outpaint(params={\n",
+ " \"prompt\": \"a cat\",\n",
+ " \"input_image\": base64.b64encode(source).decode('utf-8'),\n",
+ " \"input_mask\": base64.b64encode(mask).decode('utf-8'),\n",
+ " \"async_process\": True})\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# image_prompt v1 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "source = open(\"./imgs/s.jpg\", \"rb\").read()\n",
+ "mask = open(\"./imgs/m.png\", \"rb\").read()\n",
+ "\n",
+ "def image_prompt(params: dict,\n",
+ " input_iamge: bytes,\n",
+ " input_mask: bytes=None,\n",
+ " cn_img1: bytes=None,\n",
+ " cn_img2: bytes=None,\n",
+ " cn_img3: bytes=None,\n",
+ " cn_img4: bytes=None,) -> dict:\n",
+ " \"\"\"\n",
+ " image prompt\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v1/generation/image-prompt\",\n",
+ " data=params,\n",
+ " files={\n",
+ " \"input_image\": input_iamge,\n",
+ " \"input_mask\": input_mask,\n",
+ " \"cn_img1\": cn_img1,\n",
+ " \"cn_img2\": cn_img2,\n",
+ " \"cn_img3\": cn_img3,\n",
+ " \"cn_img4\": cn_img4,\n",
+ " })\n",
+ " return response.json()\n",
+ "\n",
+ "# 图像扩展\n",
+ "params = {\n",
+ " \"outpaint_selections\": [\"Left\", \"Right\"],\n",
+ " \"image_prompts\": [] # 必传参数,可以为空列表\n",
+ "}\n",
+ "result = image_prompt(params=params, input_iamge=image)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "# 局部重绘\n",
+ "\n",
+ "params = {\n",
+ " \"prompt\": \"1girl sitting on the chair\",\n",
+ " \"image_prompts\": [], # 必传参数,可以为空列表\n",
+ " \"async_process\": True\n",
+ "}\n",
+ "result = image_prompt(params=params, input_iamge=source, input_mask=mask)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "# image prompt\n",
+ "\n",
+ "params = {\n",
+ " \"prompt\": \"1girl sitting on the chair\",\n",
+ " \"image_prompts\": [\n",
+ " {\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " },{\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " }]\n",
+ " }\n",
+ "result = image_prompt(params=params, input_iamge=image, cn_img1=image, cn_img2=source)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# image_prompt v2 接口示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "source = open(\"./imgs/s.jpg\", \"rb\").read()\n",
+ "mask = open(\"./imgs/m.png\", \"rb\").read()\n",
+ "\n",
+ "def image_prompt(params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " image prompt\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v2/generation/image-prompt\",\n",
+ " data=json.dumps(params),\n",
+ " headers={\"Content-Type\": \"application/json\"})\n",
+ " return response.json()\n",
+ "\n",
+ "# 图像扩展\n",
+ "params = {\n",
+ " \"input_image\": base64.b64encode(image).decode('utf-8'),\n",
+ " \"outpaint_selections\": [\"Left\", \"Right\"],\n",
+ " \"image_prompts\": [] # 必传参数,可以为空列表\n",
+ "}\n",
+ "result = image_prompt(params)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "# 局部重绘\n",
+ "\n",
+ "params = {\n",
+ " \"prompt\": \"1girl sitting on the chair\",\n",
+ " \"input_image\": base64.b64encode(source).decode('utf-8'),\n",
+ " \"input_mask\": base64.b64encode(mask).decode('utf-8'),\n",
+ " \"image_prompts\": [], # 必传参数,可以为空列表\n",
+ " \"async_process\": True\n",
+ "}\n",
+ "result = image_prompt(params)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))\n",
+ "\n",
+ "# image prompt\n",
+ "\n",
+ "params = {\n",
+ " \"prompt\": \"1girl sitting on the chair\",\n",
+ " \"input_image\": base64.b64encode(source).decode('utf-8'),\n",
+ " # 这里的 input_image 无作用,但不可为空。大概是个 bug\n",
+ " \"image_prompts\": [\n",
+ " {\n",
+ " \"cn_img\": base64.b64encode(source).decode('utf-8'),\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " },{\n",
+ " \"cn_img\": base64.b64encode(image).decode('utf-8'),\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " }]\n",
+ " }\n",
+ "result = image_prompt(params)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# text to image with imageprompt 示例\n",
+ "host = \"http://127.0.0.1:8888\"\n",
+ "image = open(\"./imgs/bear.jpg\", \"rb\").read()\n",
+ "source = open(\"./imgs/s.jpg\", \"rb\").read()\n",
+ "def image_prompt(params: dict) -> dict:\n",
+ " \"\"\"\n",
+ " image prompt\n",
+ " \"\"\"\n",
+ " response = requests.post(url=f\"{host}/v2/generation/text-to-image-with-ip\",\n",
+ " data=json.dumps(params),\n",
+ " headers={\"Content-Type\": \"application/json\"})\n",
+ " return response.json()\n",
+ "\n",
+ "params = {\n",
+ " \"prompt\": \"A bear\",\n",
+ " \"image_prompts\": [\n",
+ " {\n",
+ " \"cn_img\": base64.b64encode(source).decode('utf-8'),\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " },{\n",
+ " \"cn_img\": base64.b64encode(image).decode('utf-8'),\n",
+ " \"cn_stop\": 0.6,\n",
+ " \"cn_weight\": 0.6,\n",
+ " \"cn_type\": \"ImagePrompt\"\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "result = image_prompt(params)\n",
+ "print(json.dumps(result, indent=4, ensure_ascii=False))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/examples_v1.py b/examples/examples_v1.py
deleted file mode 100644
index 960a0fc..0000000
--- a/examples/examples_v1.py
+++ /dev/null
@@ -1,215 +0,0 @@
-import json
-import requests
-import os
-import base64
-from examples.models import ControlNetEnum, ImagePromptParams, ImagePromptParamsJson, ImgInpaintOrOutpaintParams, ImgInpaintOrOutpaintParamsJson, ImgUpscaleOrVaryParams, ImgUpscaleOrVaryParamsJson, Text2ImgParams, UpscaleOrVaryMethod
-
-from models import *
-
-class Config():
- fooocus_host = 'http://127.0.0.1:8888'
-
- text2img = '/v1/generation/text-to-image'
- img_upscale = '/v1/generation/image-upscale-vary'
- inpaint_outpaint = '/v1/generation/image-inpait-outpaint'
- img_prompt = '/v1/generation/image-prompt'
-
- img_upscale_v2 = '/v2/generation/image-upscale-vary'
- inpaint_outpaint_v2 = '/v2/generation/image-inpait-outpaint'
- img_prompt_v2 = '/v2/generation/image-prompt'
-
-cfg = Config()
-
-
-def txt2img(params: Text2ImgParams) -> dict:
- """
- text to image
- """
- data = json.dumps(params.model_dump())
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.text2img}",
- data=data,
- timeout=30)
- return response.json()
-
-
-def upscale_vary_v1(image: bytes,
- params: ImgUpscaleOrVaryParams = ImgUpscaleOrVaryParams()) -> dict:
- """
- image-upscale-vary
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.img_upscale}",
- data=json.loads(json.dumps(params.model_dump())),
- files={"input_image": image},
- timeout=30)
- return response.json()
-
-
-def upscale_vary_v2(params: ImgUpscaleOrVaryParamsJson) -> dict:
- """
- image-upscale-vary
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.img_upscale_v2}",
- data=json.dumps(params.model_dump()),
- timeout=30)
- return response.json()
-
-
-def inpaint_outpaint_v1(image: bytes,
- params: ImgInpaintOrOutpaintParams,
- mask: bytes = None,
- ) -> dict:
- """
- inpaint or outpaint, move watermark, replace sth, extend image
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.inpaint_outpaint}",
- data=json.loads(json.dumps(params.model_dump())),
- files={"input_image": image,
- "input_mask": mask},
- timeout=30)
- return response.json()
-
-
-def inpaint_outpaint_v2(params: ImgInpaintOrOutpaintParamsJson,) -> dict:
- """
- inpaint or outpaint, move watermark, replace sth, extend image
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.inpaint_outpaint_v2}",
- data=json.dumps(params.model_dump()),
- timeout=30)
- return response.json()
-
-
-def image_prompt_v1(cn_img1: bytes,
- cn_img2: bytes = None,
- cn_img3: bytes = None,
- cn_img4: bytes = None,
- params: ImagePromptParams = ImagePromptParams()) -> dict:
- """
- image to image
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.img_prompt}",
- data=json.loads(json.dumps(params.model_dump())),
- files={
- "cn_img1": cn_img1,
- "cn_img2": cn_img2,
- "cn_img3": cn_img3,
- "cn_img4": cn_img4
- },
- timeout=30)
- return response.json()
-
-
-def image_prompt_v2(params: ImagePromptParamsJson = ImagePromptParamsJson()) -> dict:
- """
- image to image
- """
- response = requests.post(url=f"{cfg.fooocus_host}{cfg.img_prompt_v2}",
- data=json.dumps(params.model_dump()),
- timeout=30)
- return response.json()
-
-
-if __name__ == '__main__':
- imgs_base_path = os.path.join(os.path.dirname(__file__), 'imgs')
-
- input_image = open(os.path.join(imgs_base_path,'bear.jpg'), 'rb').read()
- input_source = open(os.path.join(imgs_base_path,'s.jpg'), 'rb').read()
- input_mask = open(os.path.join(imgs_base_path,'m.png'), 'rb').read()
-
- # example for text2img
- params = {
- "prompt": "sunshine, river, trees"
- }
- res = txt2img(Text2ImgParams(**params))
- print(res)
-
-
- # exaple for upscales
- params = {
- "uov_method": "Upscale (Custom)",
- "upscale_value": 2.0
- }
- res = upscale_vary_v1(image=input_image,
- params=ImgUpscaleOrVaryParams(**params))
- print(res)
-
- # use v2
- params["input_image"] = base64.b64encode(input_image).decode('utf-8')
- res = upscale_vary_v2(params=ImgUpscaleOrVaryParamsJson(**params))
- print(res)
-
-
- # example for in_out_paint
- # inpaint
- params = {
- "prompt": "a cat"
- }
- res = inpaint_outpaint_v1(image=input_source,
- params=ImgInpaintOrOutpaintParams(**params),
- mask=input_mask)
- print(res)
-
- # use v2
- params["input_image"] = base64.b64encode(input_source).decode('utf-8')
- params["input_mask"] = base64.b64encode(input_mask).decode('utf-8')
- res = inpaint_outpaint_v2(params=ImgInpaintOrOutpaintParamsJson(**params))
- print(res)
-
-
- # outpaint
- params = {
- "prompt": "",
- "outpaint_selections": "Left,Right",
- "outpaint_distance_left": 200,
- "outpaint_distance_right": 50
- }
- res = inpaint_outpaint_v1(image=input_image,
- params=ImgInpaintOrOutpaintParams(**params))
- print(res)
-
- # use v2
- params["input_image"] = base64.b64encode(input_image).decode('utf-8')
- params["outpaint_selections"] = ["Left", "Right"]
- res = inpaint_outpaint_v2(params=ImgInpaintOrOutpaintParamsJson(**params))
- print(res)
-
-
- # example for image_prompt
- params = {
- "cn_stop1": 0.5,
- "cn_weight1": 0.5,
- "cn_type1": "ImagePrompt",
- "cn_stop2": 0.5,
- "cn_weight2": 0.5,
- "cn_type2": "ImagePrompt"
- }
- res = image_prompt_v1(cn_img1=input_image,
- cn_img2=input_source,
- params=ImagePromptParams(**params))
- print(res)
-
- # use v2
- params = {
- "prompt": "a tiger on the ground",
- "image_prompts": [
- {"cn_img": base64.b64encode(input_image).decode('utf-8'),
- "cn_stop": 0.5,
- "cn_weight": 0.5,
- "cn_type": ControlNetEnum.imagePrompt},
- {"cn_img": base64.b64encode(input_source).decode('utf-8'),
- "cn_stop": 0.5,
- "cn_weight": 0.5,
- "cn_type": ControlNetEnum.imagePrompt}
- ]
- }
- res = image_prompt_v2(params=ImagePromptParamsJson(**params))
- print(res)
-
-
- # you can also instantiate the params object like the example below.
- params = ImgUpscaleOrVaryParams(
- uov_method=UpscaleOrVaryMethod.upscale_20
- )
- res = upscale_vary_v1(image=input_image,
- params=params)
- print(res)
diff --git a/examples/models.py b/examples/models.py
deleted file mode 100644
index 15465e4..0000000
--- a/examples/models.py
+++ /dev/null
@@ -1,177 +0,0 @@
-from pydantic import BaseModel, Field, field_validator
-from typing import List
-from enum import Enum
-
-
-class AdvancedParams(BaseModel):
- """
- Advanced parameters for the API.
- """
- adm_scaler_positive: float = 1.5
- adm_scaler_negative: float = 0.6
- adm_scaler_end: float = 0.3
- refiner_swap_method: str = "joint"
- adaptive_cfg: int = 7
- sampler_name: str = "dpmpp_2m_sde_gpu"
- scheduler_name: str = "karras"
- overwrite_step: int = -1
- overwrite_switch: int = -1
- overwrite_width: int = -1
- overwrite_height: int = -1
- overwrite_vary_strength: int = -1
- overwrite_upscale_strength: int = -1
- mixing_image_prompt_and_vary_upscale: bool = False
- mixing_image_prompt_and_inpaint: bool = False
- debugging_cn_preprocessor: bool = False
- skipping_cn_preprocessor: bool = False
- controlnet_softness: float = 0.25
- canny_low_threshold: int = 64
- canny_high_threshold: int = 128
- inpaint_engine: str = 'v1'
- freeu_enabled : bool = False
- freeu_b1: float = 1.01
- freeu_b2: float = 1.02
- freeu_s1: float = 0.99
- freeu_s2: float = 0.95
-
-
-class Lora(BaseModel):
- """
- Lora model.
- """
- model_name: str = "sd_xl_offset_example-lora_1.0.safetensors"
- weights: float = 0.1
-
-
-class PerformanceEnum(str, Enum):
- """
- Performance enum.
- """
- speed = "Speed"
- quality = "Quality"
- extreme_speed = "Extreme Speed"
-
-class UpscaleOrVaryMethod(str, Enum):
- """
- UovMethod enum.
- """
- subtle = "Vary (Subtle)"
- strong = "Vary (Strong)"
- upscale_15 = "Upscale (1.5x)"
- upscale_20 = "Upscale (2x)"
- upscale_fast = "Upscale (Fast 2x)"
- upscale_custom = "Upscale (Custom)"
-
-class ControlNetEnum(str, Enum):
- """
- ControlNet enum.
- """
- imagePrompt = "ImagePrompt"
- faceSwap = "FaceSwap"
- pyraCanny = "PyraCanny"
- cpds = "CPDS"
-
-class OutpaintExpansion(str, Enum):
- left = 'Left'
- right = 'Right'
- top = 'Top'
- bottom = 'Bottom'
-
-class ImagePrompt(BaseModel):
- cn_img: str | None = None
- cn_stop: float | None = 0.6
- cn_weight: float | None = 0.6
- cn_type: ControlNetEnum = "ImagePrompt"
-
-class SharedFields(BaseModel):
- """
- SharedFields model.
- """
- prompt: str = ""
- negative_prompt: str = ""
- style_selections: str = ""
- aspect_ratios_selection: str = "1152*896"
- performance_selection: PerformanceEnum = "Speed"
- image_number: int = 1
- image_seed: int = -1
- sharpness: int = 2
- guidance_scale: int = 4
- base_model_name: str = "juggernautXL_version6Rundiffusion.safetensors"
- refiner_model_name: str = "None"
- refiner_switch: float = 0.5
- loras: str = '[{"model_name":"sd_xl_offset_example-lora_1.0.safetensors","weight":0.1}]'
- advanced_params: str = ""
- require_base64: bool = False
- async_process: bool = False
-
-
-class Text2ImgParams(SharedFields):
- """
- Text2ImgPrompt model.
- """
- style_selections: List[str] = ["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp"]
- loras: List[Lora] = [Lora()]
- advanced_params: AdvancedParams = AdvancedParams()
-
-class ImgUpscaleOrVaryParams(SharedFields):
- """
- Upscale model.
- """
- uov_method: UpscaleOrVaryMethod = "Upscale (2x)"
- upscale_value: float | None = Field(None, ge=1.0, le=5.0, description="Upscale custom value, None for default value")
-
-class ImgInpaintOrOutpaintParams(SharedFields):
- """
- Inpaint model.
- """
- outpaint_selections: str = Field("", description="A comma-separated string of 'Left', 'Right', 'Top', 'Bottom'")
- outpaint_distance_left: int = Field(default=0, description="Set outpaint left distance, 0 for default")
- outpaint_distance_right: int = Field(default=0, description="Set outpaint right distance, 0 for default")
- outpaint_distance_top: int = Field(default=0, description="Set outpaint top distance, 0 for default")
- outpaint_distance_bottom: int = Field(default=0, description="Set outpaint bottom distance, 0 for default")
-
- @field_validator("outpaint_selections")
- def validate_outpaint_selections(cls, v):
- if v == "":
- return v
- allowed_values = ['Left', 'Right', 'Top', 'Bottom']
- for val in v.split(','):
- if val not in allowed_values:
- raise ValueError(f"Value {val} is invalid, allowed values are {allowed_values}")
- return v
-
-
-class ImagePromptParams(SharedFields):
- """
- Image prompt.
- """
- cn_stop1: float = 0.6
- cn_weight1: float = 0.6
- cn_type1: ControlNetEnum = "ImagePrompt"
- cn_stop2: float = 0.6
- cn_weight2: float = 0.6
- cn_type2: ControlNetEnum = "ImagePrompt"
- cn_stop3: float = 0.6
- cn_weight3: float = 0.6
- cn_type3: ControlNetEnum = "ImagePrompt"
- cn_stop4: float = 0.6
- cn_weight4: float = 0.6
- cn_type4: ControlNetEnum = "ImagePrompt"
-
-
-class ImgUpscaleOrVaryParamsJson(Text2ImgParams):
- uov_method: UpscaleOrVaryMethod = "Upscale (2x)"
- input_image: str = Field(description="Init image for upsacale or outpaint as base64")
-
-class ImgInpaintOrOutpaintParamsJson(Text2ImgParams):
- input_image: str
- input_mask: str | None = None
- inpaint_additional_prompt: str | None = None
- outpaint_selections: List[OutpaintExpansion] = ["Left", "Right", "Top", "Bottom"]
- outpaint_distance_left: int = Field(default=0, description="Set outpaint left distance, 0 for default")
- outpaint_distance_right: int = Field(default=0, description="Set outpaint right distance, 0 for default")
- outpaint_distance_top: int = Field(default=0, description="Set outpaint top distance, 0 for default")
- outpaint_distance_bottom: int = Field(default=0, description="Set outpaint bottom distance, 0 for default")
-
-class ImagePromptParamsJson(Text2ImgParams):
- image_prompts: List[ImagePrompt] = [ImagePrompt()]
diff --git a/fooocusapi/api.py b/fooocusapi/api.py
index b0fd14e..fefc04e 100644
--- a/fooocusapi/api.py
+++ b/fooocusapi/api.py
@@ -112,6 +112,37 @@ def text2img_generation(req: Text2ImgRequest, accept: str = Header(None),
results = call_worker(req, accept)
return generation_output(results, streaming_output, req.require_base64)
+@app.post("/v2/generation/text-to-image-with-ip", response_model=List[GeneratedImageResult] | AsyncJobResponse, responses=img_generate_responses)
+def text_to_img_with_ip(req: Text2ImgRequestWithPrompt,
+ accept: str = Header(None),
+ accept_query: str | None = Query(None, alias='accept', description="Parameter to overvide 'Accept' header, 'image/png' for output bytes")):
+ if accept_query is not None and len(accept_query) > 0:
+ accept = accept_query
+
+ if accept == 'image/png':
+ streaming_output = True
+ # image_number auto set to 1 in streaming mode
+ req.image_number = 1
+ else:
+ streaming_output = False
+
+ default_image_promt = ImagePrompt(cn_img=None)
+ image_prompts_files: List[ImagePrompt] = []
+ for img_prompt in req.image_prompts:
+ img_prompt.cn_img = base64_to_stream(img_prompt.cn_img)
+ image = ImagePrompt(cn_img=img_prompt.cn_img,
+ cn_stop=img_prompt.cn_stop,
+ cn_weight=img_prompt.cn_weight,
+ cn_type=img_prompt.cn_type)
+ image_prompts_files.append(image)
+
+ while len(image_prompts_files) <= 4:
+ image_prompts_files.append(default_image_promt)
+
+ req.image_prompts = image_prompts_files
+
+ results = call_worker(req, accept)
+ return generation_output(results, streaming_output, req.require_base64)
@app.post("/v1/generation/image-upscale-vary", response_model=List[GeneratedImageResult] | AsyncJobResponse, responses=img_generate_responses)
def img_upscale_or_vary(input_image: UploadFile, req: ImgUpscaleOrVaryRequest = Depends(ImgUpscaleOrVaryRequest.as_form),
diff --git a/fooocusapi/api_utils.py b/fooocusapi/api_utils.py
index 2768d20..259d61a 100644
--- a/fooocusapi/api_utils.py
+++ b/fooocusapi/api_utils.py
@@ -43,8 +43,10 @@ def req_to_params(req: Text2ImgRequest) -> ImageGenerationParams:
refiner_model_name = req.refiner_model_name
refiner_switch = req.refiner_switch
loras = [(lora.model_name, lora.weight) for lora in req.loras]
- uov_input_image = None if not (isinstance(
- req, ImgUpscaleOrVaryRequest) or isinstance(req, ImgUpscaleOrVaryRequestJson)) else read_input_image(req.input_image)
+ uov_input_image = None
+ if not isinstance(req, Text2ImgRequestWithPrompt):
+ if isinstance(req, ImgUpscaleOrVaryRequest) or isinstance(req, ImgUpscaleOrVaryRequestJson):
+ uov_input_image = read_input_image(req.input_image)
uov_method = flags.disabled if not (isinstance(
req, ImgUpscaleOrVaryRequest) or isinstance(req, ImgUpscaleOrVaryRequestJson)) else req.uov_method.value
upscale_value = None if not (isinstance(
@@ -78,9 +80,9 @@ def req_to_params(req: Text2ImgRequest) -> ImageGenerationParams:
}
image_prompts = []
- if isinstance(req, ImgPromptRequest) or isinstance(req, ImgPromptRequestJson):
+ if isinstance(req, ImgPromptRequest) or isinstance(req, ImgPromptRequestJson) or isinstance(req, Text2ImgRequestWithPrompt):
# Auto set mixing_image_prompt_and_inpaint to True
- if len(req.image_prompts) > 0 and req.input_image is not None and req.advanced_params is not None:
+ if len(req.image_prompts) > 0 and not isinstance(req, Text2ImgRequestWithPrompt) and req.input_image is not None and req.advanced_params is not None:
req.advanced_params.mixing_image_prompt_and_inpaint = True
for img_prompt in req.image_prompts:
diff --git a/fooocusapi/models_v2.py b/fooocusapi/models_v2.py
index 2382485..bb694e8 100644
--- a/fooocusapi/models_v2.py
+++ b/fooocusapi/models_v2.py
@@ -28,3 +28,6 @@ class ImagePromptJson(BaseModel):
class ImgPromptRequestJson(ImgInpaintOrOutpaintRequestJson):
input_image: str | None = Field(None, description="Init image for inpaint or outpaint as base64")
image_prompts: List[ImagePromptJson | ImagePrompt]
+
+class Text2ImgRequestWithPrompt(Text2ImgRequest):
+ image_prompts: List[ImagePromptJson] = []
\ No newline at end of file