From b5163e057f7cad3dac2f885be1ad9140e693ed4b Mon Sep 17 00:00:00 2001
From: xhoxye <129571231+xhoxye@users.noreply.github.com>
Date: Tue, 2 Jan 2024 23:17:02 +0800
Subject: [PATCH 1/2] =?UTF-8?q?Fooocus=20mask=20enhance,=20mask=20upload?=
=?UTF-8?q?=20and=20invert.=E8=92=99=E7=89=88=E5=A2=9E=E5=BC=BA=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=B8=8A=E4=BC=A0=E8=92=99=E7=89=88=E3=80=81?=
=?UTF-8?q?=E5=8F=8D=E8=BD=AC=E6=89=8B=E6=B6=82=E8=92=99=E7=89=88=20(#1645?=
=?UTF-8?q?)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update webui.py
Added a mask upload interface.添加蒙版上传界面。
* Add mask upload feature
Add mask upload feature.添加蒙版上传功能。
* Add mask upload feature
Add mask upload feature.添加蒙版上传功能。
* Try to fix the problem when drawing mates with external enrichment.
Swap the judgment criteria and try to fix the problem when drawing mates with external enrichment.
调换判断条件,尝试修复和外部扩充绘制配合时出现的问题
* 修改注释
* 修改注释
* Update readme.md
更新日志
* Add mask upload check box,
Add check box, default does not show mask upload box, check it and then show it.
添加复选框,默认不显示蒙版上传框,勾选后再显示。
* back to normal
还原
* Try adding a mask inversion feature
Try adding a mask inversion feature.
尝试添加蒙版反转功能。
增加一个复选框来决定是否将蒙版反转。
* Try adding a mask inversion feature
Try adding a mask inversion feature.
尝试添加蒙版反转功能。
增加一个复选框来决定是否将蒙版反转。
* Fixed word errors
* Fix the words of the description
---
modules/async_worker.py | 32 +++++++++++++++++++++++++++++++-
webui.py | 23 +++++++++++++++++++++--
2 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/modules/async_worker.py b/modules/async_worker.py
index fab2508e..48626b4c 100644
--- a/modules/async_worker.py
+++ b/modules/async_worker.py
@@ -22,6 +22,12 @@ def worker():
import shared
import random
import copy
+
+ # xhoxye4
+ # 导入 OpenCV 库
+ import cv2
+ # xhoxye4
+
import modules.default_pipeline as pipeline
import modules.core as core
import modules.flags as flags
@@ -138,6 +144,14 @@ def worker():
uov_input_image = args.pop()
outpaint_selections = args.pop()
inpaint_input_image = args.pop()
+
+ # xhoxye5
+ # 接收参数
+ inpaint_mask_image = args.pop()
+ inpaint_mask_image_checkbox = args.pop()
+ invert_mask_checkbox = args.pop()
+ # xhoxye5
+
inpaint_additional_prompt = args.pop()
cn_tasks = {x: [] for x in flags.ip_list}
@@ -273,7 +287,23 @@ def worker():
current_tab == 'ip' and advanced_parameters.mixing_image_prompt_and_inpaint)) \
and isinstance(inpaint_input_image, dict):
inpaint_image = inpaint_input_image['image']
- inpaint_mask = inpaint_input_image['mask'][:, :, 0]
+
+ # xhoxye6
+ #inpaint_mask = inpaint_input_image['mask'][:, :, 0]
+ # use uploaded inpaint mask image, if not brush for inpaint.
+ # 如果没有手涂蒙版,则使用上传蒙版,并缩放。调换判断条件,尝试修复和外部扩充绘制配合时出现的问题.
+ # 添加反转手涂蒙版的判断
+ if inpaint_mask_image_checkbox and not np.any(inpaint_input_image['mask'] == [255, 255, 255]) and inpaint_mask_image is not None:
+ inpaint_height, inpaint_width = inpaint_image.shape[:2]
+ resized_mask_image = cv2.resize(inpaint_mask_image, (inpaint_width, inpaint_height))
+
+ inpaint_mask = resized_mask_image[:, :, 0]
+ else:
+ inpaint_mask = inpaint_input_image['mask'][:, :, 0]
+ if invert_mask_checkbox:
+ inpaint_mask = np.invert(inpaint_mask)
+ # xhoxye6
+
inpaint_image = HWC3(inpaint_image)
if isinstance(inpaint_image, np.ndarray) and isinstance(inpaint_mask, np.ndarray) \
and (np.any(inpaint_mask > 127) or len(outpaint_selections) > 0):
diff --git a/webui.py b/webui.py
index 8653a554..f7b09f27 100644
--- a/webui.py
+++ b/webui.py
@@ -186,12 +186,28 @@ with shared.gradio_root:
outputs=ip_ad_cols + ip_types + ip_stops + ip_weights,
queue=False, show_progress=False)
with gr.TabItem(label='Inpaint or Outpaint') as inpaint_tab:
- inpaint_input_image = grh.Image(label='Drag above image to here', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas')
+ # xhoxye1
+ #inpaint_input_image = grh.Image(label='Drag above image to here', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas')
+
+ with gr.Row():
+ inpaint_input_image = grh.Image(label='Drag inpaint or outpaint image to here', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas')
+
+ inpaint_mask_image = grh.Image(label='Drag inpaint mask image to here', source='upload', type='numpy', height=500,visible=False)
+ # xhoxye1
+
with gr.Row():
inpaint_additional_prompt = gr.Textbox(placeholder="Describe what you want to inpaint.", elem_id='inpaint_additional_prompt', label='Inpaint Additional Prompt', visible=False)
outpaint_selections = gr.CheckboxGroup(choices=['Left', 'Right', 'Top', 'Bottom'], value=[], label='Outpaint Direction')
inpaint_mode = gr.Dropdown(choices=modules.flags.inpaint_options, value=modules.flags.inpaint_option_default, label='Method')
example_inpaint_prompts = gr.Dataset(samples=modules.config.example_inpaint_prompts, label='Additional Prompt Quick List', components=[inpaint_additional_prompt], visible=False)
+
+ # xhoxye2
+ with gr.TabItem(label='Inpaint advanced') as inpaint_advanced:
+ inpaint_mask_image_checkbox = gr.Checkbox(label='Enable upload mask', value=False, container=False)
+ inpaint_mask_image_checkbox.change(lambda x: gr.update(visible=x), inputs=inpaint_mask_image_checkbox, outputs=inpaint_mask_image, queue=False)
+ invert_mask_checkbox = gr.Checkbox(label='Invert hand-drawn mask', value=False, container=False)
+ # xhoxye2
+
gr.HTML('* Powered by Fooocus Inpaint Engine \U0001F4D4 Document')
example_inpaint_prompts.click(lambda x: x[0], inputs=example_inpaint_prompts, outputs=inpaint_additional_prompt, show_progress=False, queue=False)
with gr.TabItem(label='Describe') as desc_tab:
@@ -510,7 +526,10 @@ with shared.gradio_root:
ctrls += [base_model, refiner_model, refiner_switch] + lora_ctrls
ctrls += [input_image_checkbox, current_tab]
ctrls += [uov_method, uov_input_image]
- ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt]
+ # xhoxye3
+ #ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt]
+ ctrls += [outpaint_selections, inpaint_input_image, inpaint_mask_image, inpaint_mask_image_checkbox, invert_mask_checkbox, inpaint_additional_prompt]
+ # xhoxye3
ctrls += ip_ctrls
state_is_generating = gr.State(False)
From e5af760db847a2cf374e7aaa18e62998f8445d1c Mon Sep 17 00:00:00 2001
From: lllyasviel
Date: Tue, 2 Jan 2024 07:37:53 -0800
Subject: [PATCH 2/2] mask upload
---
fooocus_version.py | 2 +-
modules/advanced_parameters.py | 9 ++++---
modules/async_worker.py | 47 ++++++++++++----------------------
modules/util.py | 10 ++++++++
update_log.md | 4 +++
webui.py | 38 +++++++++++++--------------
6 files changed, 56 insertions(+), 54 deletions(-)
diff --git a/fooocus_version.py b/fooocus_version.py
index 8cde204d..482cc12c 100644
--- a/fooocus_version.py
+++ b/fooocus_version.py
@@ -1 +1 @@
-version = '2.1.859'
+version = '2.1.860'
diff --git a/modules/advanced_parameters.py b/modules/advanced_parameters.py
index ea04db6c..0caa3eec 100644
--- a/modules/advanced_parameters.py
+++ b/modules/advanced_parameters.py
@@ -5,7 +5,8 @@ disable_preview, adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adapt
debugging_cn_preprocessor, skipping_cn_preprocessor, controlnet_softness, canny_low_threshold, canny_high_threshold, \
refiner_swap_method, \
freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2, \
- debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field = [None] * 32
+ debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field, \
+ inpaint_mask_upload_checkbox, invert_mask_checkbox, inpaint_erode_or_dilate = [None] * 35
def set_all_advanced_parameters(*args):
@@ -16,7 +17,8 @@ def set_all_advanced_parameters(*args):
debugging_cn_preprocessor, skipping_cn_preprocessor, controlnet_softness, canny_low_threshold, canny_high_threshold, \
refiner_swap_method, \
freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2, \
- debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field
+ debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field, \
+ inpaint_mask_upload_checkbox, invert_mask_checkbox, inpaint_erode_or_dilate
disable_preview, adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adaptive_cfg, sampler_name, \
scheduler_name, generate_image_grid, overwrite_step, overwrite_switch, overwrite_width, overwrite_height, \
@@ -25,6 +27,7 @@ def set_all_advanced_parameters(*args):
debugging_cn_preprocessor, skipping_cn_preprocessor, controlnet_softness, canny_low_threshold, canny_high_threshold, \
refiner_swap_method, \
freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2, \
- debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field = args
+ debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field, \
+ inpaint_mask_upload_checkbox, invert_mask_checkbox, inpaint_erode_or_dilate = args
return
diff --git a/modules/async_worker.py b/modules/async_worker.py
index 48626b4c..b2af6712 100644
--- a/modules/async_worker.py
+++ b/modules/async_worker.py
@@ -22,12 +22,6 @@ def worker():
import shared
import random
import copy
-
- # xhoxye4
- # 导入 OpenCV 库
- import cv2
- # xhoxye4
-
import modules.default_pipeline as pipeline
import modules.core as core
import modules.flags as flags
@@ -46,7 +40,7 @@ def worker():
from modules.private_logger import log
from extras.expansion import safe_str
from modules.util import remove_empty_str, HWC3, resize_image, \
- get_image_shape_ceil, set_image_shape_ceil, get_shape_ceil, resample_image
+ get_image_shape_ceil, set_image_shape_ceil, get_shape_ceil, resample_image, erode_or_dilate
from modules.upscaler import perform_upscale
try:
@@ -144,15 +138,8 @@ def worker():
uov_input_image = args.pop()
outpaint_selections = args.pop()
inpaint_input_image = args.pop()
-
- # xhoxye5
- # 接收参数
- inpaint_mask_image = args.pop()
- inpaint_mask_image_checkbox = args.pop()
- invert_mask_checkbox = args.pop()
- # xhoxye5
-
inpaint_additional_prompt = args.pop()
+ inpaint_mask_image_upload = args.pop()
cn_tasks = {x: [] for x in flags.ip_list}
for _ in range(4):
@@ -287,22 +274,22 @@ def worker():
current_tab == 'ip' and advanced_parameters.mixing_image_prompt_and_inpaint)) \
and isinstance(inpaint_input_image, dict):
inpaint_image = inpaint_input_image['image']
-
- # xhoxye6
- #inpaint_mask = inpaint_input_image['mask'][:, :, 0]
- # use uploaded inpaint mask image, if not brush for inpaint.
- # 如果没有手涂蒙版,则使用上传蒙版,并缩放。调换判断条件,尝试修复和外部扩充绘制配合时出现的问题.
- # 添加反转手涂蒙版的判断
- if inpaint_mask_image_checkbox and not np.any(inpaint_input_image['mask'] == [255, 255, 255]) and inpaint_mask_image is not None:
- inpaint_height, inpaint_width = inpaint_image.shape[:2]
- resized_mask_image = cv2.resize(inpaint_mask_image, (inpaint_width, inpaint_height))
+ inpaint_mask = inpaint_input_image['mask'][:, :, 0]
+
+ if advanced_parameters.inpaint_mask_upload_checkbox:
+ if isinstance(inpaint_mask_image_upload, np.ndarray):
+ if inpaint_mask_image_upload.ndim == 3:
+ H, W, C = inpaint_image.shape
+ inpaint_mask_image_upload = resample_image(inpaint_mask_image_upload, width=W, height=H)
+ inpaint_mask_image_upload = np.mean(inpaint_mask_image_upload, axis=2)
+ inpaint_mask_image_upload = (inpaint_mask_image_upload > 127).astype(np.uint8) * 255
+ inpaint_mask = np.maximum(inpaint_mask, inpaint_mask_image_upload)
- inpaint_mask = resized_mask_image[:, :, 0]
- else:
- inpaint_mask = inpaint_input_image['mask'][:, :, 0]
- if invert_mask_checkbox:
- inpaint_mask = np.invert(inpaint_mask)
- # xhoxye6
+ if int(advanced_parameters.inpaint_erode_or_dilate) != 0:
+ inpaint_mask = erode_or_dilate(inpaint_mask, advanced_parameters.inpaint_erode_or_dilate)
+
+ if advanced_parameters.invert_mask_checkbox:
+ inpaint_mask = 255 - inpaint_mask
inpaint_image = HWC3(inpaint_image)
if isinstance(inpaint_image, np.ndarray) and isinstance(inpaint_mask, np.ndarray) \
diff --git a/modules/util.py b/modules/util.py
index fce7efd7..052b746b 100644
--- a/modules/util.py
+++ b/modules/util.py
@@ -3,6 +3,7 @@ import datetime
import random
import math
import os
+import cv2
from PIL import Image
@@ -10,6 +11,15 @@ from PIL import Image
LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS)
+def erode_or_dilate(x, k):
+ k = int(k)
+ if k > 0:
+ return cv2.dilate(x, kernel=np.ones(shape=(3, 3), dtype=np.uint8), iterations=k)
+ if k < 0:
+ return cv2.erode(x, kernel=np.ones(shape=(3, 3), dtype=np.uint8), iterations=-k)
+ return x
+
+
def resample_image(im, width, height):
im = Image.fromarray(im)
im = im.resize((int(width), int(height)), resample=LANCZOS)
diff --git a/update_log.md b/update_log.md
index 66176145..e9a829be 100644
--- a/update_log.md
+++ b/update_log.md
@@ -1,5 +1,9 @@
**(2023 Dec 21) Hi all, the feature updating of Fooocus will be paused for about two or three weeks because we have some other workloads. See you soon and we will come back in mid or late Jan. However, you may still see updates if other collaborators are fixing bugs or solving problems.**
+# 2.1.860 (requested update)
+
+* Allow upload inpaint mask in developer mode.
+
# 2.1.857 (requested update)
* Begin to support 8GB AMD GPU on Windows.
diff --git a/webui.py b/webui.py
index f7b09f27..581e3101 100644
--- a/webui.py
+++ b/webui.py
@@ -186,28 +186,15 @@ with shared.gradio_root:
outputs=ip_ad_cols + ip_types + ip_stops + ip_weights,
queue=False, show_progress=False)
with gr.TabItem(label='Inpaint or Outpaint') as inpaint_tab:
- # xhoxye1
- #inpaint_input_image = grh.Image(label='Drag above image to here', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas')
-
with gr.Row():
inpaint_input_image = grh.Image(label='Drag inpaint or outpaint image to here', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas')
-
- inpaint_mask_image = grh.Image(label='Drag inpaint mask image to here', source='upload', type='numpy', height=500,visible=False)
- # xhoxye1
-
+ inpaint_mask_image = grh.Image(label='Mask Upload', source='upload', type='numpy', height=500, visible=False)
+
with gr.Row():
inpaint_additional_prompt = gr.Textbox(placeholder="Describe what you want to inpaint.", elem_id='inpaint_additional_prompt', label='Inpaint Additional Prompt', visible=False)
outpaint_selections = gr.CheckboxGroup(choices=['Left', 'Right', 'Top', 'Bottom'], value=[], label='Outpaint Direction')
inpaint_mode = gr.Dropdown(choices=modules.flags.inpaint_options, value=modules.flags.inpaint_option_default, label='Method')
example_inpaint_prompts = gr.Dataset(samples=modules.config.example_inpaint_prompts, label='Additional Prompt Quick List', components=[inpaint_additional_prompt], visible=False)
-
- # xhoxye2
- with gr.TabItem(label='Inpaint advanced') as inpaint_advanced:
- inpaint_mask_image_checkbox = gr.Checkbox(label='Enable upload mask', value=False, container=False)
- inpaint_mask_image_checkbox.change(lambda x: gr.update(visible=x), inputs=inpaint_mask_image_checkbox, outputs=inpaint_mask_image, queue=False)
- invert_mask_checkbox = gr.Checkbox(label='Invert hand-drawn mask', value=False, container=False)
- # xhoxye2
-
gr.HTML('* Powered by Fooocus Inpaint Engine \U0001F4D4 Document')
example_inpaint_prompts.click(lambda x: x[0], inputs=example_inpaint_prompts, outputs=inpaint_additional_prompt, show_progress=False, queue=False)
with gr.TabItem(label='Describe') as desc_tab:
@@ -435,7 +422,21 @@ with shared.gradio_root:
'Value 1 is same as "Whole Image" in A1111. '
'Only used in inpaint, not used in outpaint. '
'(Outpaint always use 1.0)')
- inpaint_ctrls = [debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine, inpaint_strength, inpaint_respective_field]
+ inpaint_erode_or_dilate = gr.Slider(label='Mask Erode or Dilate',
+ minimum=-64, maximum=64, step=1, value=0,
+ info='Positive value will make white area in the mask larger, '
+ 'negative value will make white area smaller.'
+ '(default is 0, always process before any mask invert)')
+ inpaint_mask_upload_checkbox = gr.Checkbox(label='Enable Mask Upload', value=False)
+ invert_mask_checkbox = gr.Checkbox(label='Invert Mask', value=False)
+
+ inpaint_ctrls = [debugging_inpaint_preprocessor, inpaint_disable_initial_latent, inpaint_engine,
+ inpaint_strength, inpaint_respective_field,
+ inpaint_mask_upload_checkbox, invert_mask_checkbox, inpaint_erode_or_dilate]
+
+ inpaint_mask_upload_checkbox.change(lambda x: gr.update(visible=x),
+ inputs=inpaint_mask_upload_checkbox,
+ outputs=inpaint_mask_image, queue=False, show_progress=False)
with gr.Tab(label='FreeU'):
freeu_enabled = gr.Checkbox(label='Enabled', value=False)
@@ -526,10 +527,7 @@ with shared.gradio_root:
ctrls += [base_model, refiner_model, refiner_switch] + lora_ctrls
ctrls += [input_image_checkbox, current_tab]
ctrls += [uov_method, uov_input_image]
- # xhoxye3
- #ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt]
- ctrls += [outpaint_selections, inpaint_input_image, inpaint_mask_image, inpaint_mask_image_checkbox, invert_mask_checkbox, inpaint_additional_prompt]
- # xhoxye3
+ ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt, inpaint_mask_image]
ctrls += ip_ctrls
state_is_generating = gr.State(False)