From e5af760db847a2cf374e7aaa18e62998f8445d1c Mon Sep 17 00:00:00 2001 From: lllyasviel Date: Tue, 2 Jan 2024 07:37:53 -0800 Subject: [PATCH] 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 8cde204..482cc12 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 ea04db6..0caa3ee 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 48626b4..b2af671 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 fce7efd..052b746 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 6617614..e9a829b 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 f7b09f2..581e310 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)