cleanup yolo

Signed-off-by: vladmandic <mandic00@live.com>
pull/4690/head
vladmandic 2026-03-16 08:30:23 +01:00
parent ee9e93e62f
commit 6a9b9297c1
3 changed files with 118 additions and 124 deletions

View File

@ -2,7 +2,7 @@ from modules.image.metadata import image_data, read_info_from_image
from modules.image.save import save_image, sanitize_filename_part
from modules.image.resize import resize_image
from modules.image.namegen import FilenameGenerator
from modules.image.grid import Grid, image_grid, check_grid_size, get_grid_size, draw_grid_annotations, draw_prompt_matrix, combine_grid
from modules.image.grid import Grid, image_grid, check_grid_size, get_grid_size, draw_grid_annotations, draw_prompt_matrix, combine_grid, get_font
__all__ = [
'check_grid_size',
@ -18,4 +18,5 @@ __all__ = [
'resize_image',
'sanitize_filename_part',
'save_image',
'get_font',
]

View File

@ -143,7 +143,7 @@ class YoloRestorer(Detailer):
log.error(f'Detailer predict: {e}')
return result
classes_str = classes if classes is not None else shared.opts.detailer_classes
classes_str = classes if classes is not None else get_opt(p, 'detailer_classes')
desired = classes_str.split(',')
desired = [d.lower().strip() for d in desired]
desired = [d for d in desired if len(d) > 0]
@ -265,7 +265,7 @@ class YoloRestorer(Detailer):
color = (0, 190, 190)
log.debug(f'Detailer: draw={items}')
for i, item in enumerate(items):
use_seg = segmentation if segmentation is not None else shared.opts.detailer_seg
use_seg = segmentation if segmentation is not None else get_opt(None, "detailer_segmentation")
if use_seg and item.mask is not None:
mask = item.mask.convert('L')
else:
@ -299,25 +299,23 @@ class YoloRestorer(Detailer):
return np_image
models = []
p_models = getattr(p, 'detailer_models', None)
if p_models is not None and len(p_models) > 0:
models = p_models
models = get_opt(p, 'detailer_models') or []
if models is not None and len(models) > 0:
pass
elif len(shared.opts.detailer_args) > 0:
models = [m.strip() for m in re.split(r'[\n,;]+', shared.opts.detailer_args)]
models = [m for m in models if len(m) > 0]
if len(models) == 0:
models = shared.opts.detailer_models
if len(models) == 0:
log.warning('Detailer: model=None')
return np_image
log.debug(f'Detailer: models={models}')
# resolve per-request detailer settings with fallback to global opts
use_seg = getattr(p, 'detailer_segmentation', None)
use_save = getattr(p, 'detailer_include_detections', None)
use_merge = getattr(p, 'detailer_merge', None)
use_sort = getattr(p, 'detailer_sort', None)
use_classes = getattr(p, 'detailer_classes', None)
use_seg = get_opt(p, "detailer_segmentation")
use_save = get_opt(p, "detailer_include_detections")
use_merge = get_opt(p, "detailer_merge")
use_sort = get_opt(p, "detailer_sort")
use_classes = get_opt(p, "detailer_classes")
# create backups
orig_p = p.__dict__.copy()
@ -326,7 +324,6 @@ class YoloRestorer(Detailer):
np_images = []
annotated = Image.fromarray(np_image)
image = None
do_save = use_save if use_save is not None else shared.opts.detailer_save
for i, model_val in enumerate(models):
if ':' in model_val:
@ -349,8 +346,7 @@ class YoloRestorer(Detailer):
log.info(f'Detailer: model="{name}" no items detected')
continue
do_merge = use_merge if use_merge is not None else shared.opts.detailer_merge
if do_merge and len(items) > 1:
if use_merge and len(items) > 1:
log.debug(f'Detailer: model="{name}" items={len(items)} merge')
items = self.merge(items)
@ -421,10 +417,9 @@ class YoloRestorer(Detailer):
pc.schedulers_sigma_adjust_max = get_opt(p, 'detailer_sigma_adjust_max')
pc.mask_apply_overlay = True
do_sort = use_sort if use_sort is not None else shared.opts.detailer_sort
if do_sort:
if use_sort:
items = sorted(items, key=lambda x: x.box[0]) # sort items left-to-right to improve consistency
if do_save:
if use_save:
annotated = self.draw_masks(annotated, items, segmentation=use_seg)
for j, item in enumerate(items):
@ -480,7 +475,7 @@ class YoloRestorer(Detailer):
if image is not None:
np_images.append(np.array(image))
if do_save and annotated is not None:
if use_save and annotated is not None:
np_images.append(annotated) # save debug image with boxes
return np_images

View File

@ -18,34 +18,34 @@ options_templates = {}
def list_checkpoint_titles():
import modules.sd_models # pylint: disable=redefined-outer-name
import modules.sd_models
return modules.sd_models.checkpoint_titles()
def refresh_checkpoints():
import modules.sd_models # pylint: disable=redefined-outer-name
import modules.sd_models
return modules.sd_models.list_models()
def refresh_vaes():
import modules.sd_vae # pylint: disable=redefined-outer-name
import modules.sd_vae
modules.sd_vae.refresh_vae_list()
def refresh_upscalers():
import modules.modelloader # pylint: disable=redefined-outer-name
import modules.modelloader
modules.modelloader.load_upscalers()
def list_samplers():
import modules.sd_samplers # pylint: disable=redefined-outer-name
import modules.sd_samplers
modules.sd_samplers.set_samplers()
return modules.sd_samplers.all_samplers
def get_openvino_device_list():
try:
import modules.intel.openvino # pylint: disable=redefined-outer-name
import modules.intel.openvino
return modules.intel.openvino.get_device_list()
except Exception:
return []
@ -665,14 +665,16 @@ def create_settings(cmd_opts):
}))
# --- Hidden Options ---
options_templates.update(options_section(('hidden_options', "Hidden options"), {
options_templates.update(
options_section(
("hidden_options", "Hidden options"),
{
# internal options
"diffusers_version": OptionInfo("", "Diffusers version", gr.Textbox, {"visible": False}),
"transformers_version": OptionInfo("", "Transformers version", gr.Textbox, {"visible": False}),
"disabled_extensions": OptionInfo([], "Disable these extensions", gr.Textbox, {"visible": False}),
"sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint", gr.Textbox, {"visible": False}),
"tooltips": OptionInfo("UI Tooltips", "UI tooltips", gr.Radio, {"choices": ["None", "Browser default", "UI tooltips"], "visible": False}),
# Caption settings (controlled via Caption Tab UI)
"caption_default_type": OptionInfo("VLM", "Default caption type", gr.Radio, {"choices": ["VLM", "OpenCLiP", "Tagger"], "visible": False}),
"tagger_show_scores": OptionInfo(False, "Tagger: show confidence scores in results", gr.Checkbox, {"visible": False}),
@ -706,7 +708,6 @@ def create_settings(cmd_opts):
"tagger_exclude_tags": OptionInfo("", "Tagger: exclude tags", gr.Textbox, {"visible": False}),
"waifudiffusion_model": OptionInfo("wd-eva02-large-tagger-v3", "WaifuDiffusion: default model", gr.Dropdown, {"choices": [], "visible": False}),
"waifudiffusion_character_threshold": OptionInfo(0.85, "WaifuDiffusion: character tag threshold", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.01, "visible": False}),
# control settings are handled separately
"control_hires": OptionInfo(False, "Hires use Control", gr.Checkbox, {"visible": False}),
"control_aspect_ratio": OptionInfo(False, "Aspect ratio resize", gr.Checkbox, {"visible": False}),
@ -714,36 +715,34 @@ def create_settings(cmd_opts):
"control_tiles": OptionInfo("1x1, 1x2, 1x3, 1x4, 2x1, 2x1, 2x2, 2x3, 2x4, 3x1, 3x2, 3x3, 3x4, 4x1, 4x2, 4x3, 4x4", "Tiling options", gr.Textbox, {"visible": False}),
"control_move_processor": OptionInfo(False, "Processor move to CPU when complete", gr.Checkbox, {"visible": False}),
"control_unload_processor": OptionInfo(False, "Processor unload after use", gr.Checkbox, {"visible": False}),
# sampler settings are handled separately
"show_samplers": OptionInfo([], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()], "visible": False}),
'eta_noise_seed_delta': OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0, "visible": False}),
"eta_noise_seed_delta": OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0, "visible": False}),
"scheduler_eta": OptionInfo(1.0, "Noise multiplier (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
"schedulers_solver_order": OptionInfo(0, "Solver order (where", gr.Slider, {"minimum": 0, "maximum": 5, "step": 1, "visible": False}),
"schedulers_use_loworder": OptionInfo(True, "Use simplified solvers in final steps", gr.Checkbox, {"visible": False}),
"schedulers_prediction_type": OptionInfo("default", "Override model prediction type", gr.Radio, {"choices": ['default', 'epsilon', 'sample', 'v_prediction', 'flow_prediction'], "visible": False}),
"schedulers_sigma": OptionInfo("default", "Sigma algorithm", gr.Radio, {"choices": ['default', 'karras', 'exponential', 'polyexponential'], "visible": False}),
"schedulers_beta_schedule": OptionInfo("default", "Beta schedule", gr.Dropdown, {"choices": ['default', 'linear', 'scaled_linear', 'squaredcos_cap_v2', 'sigmoid'], "visible": False}),
"schedulers_prediction_type": OptionInfo("default", "Override model prediction type", gr.Radio, {"choices": ["default", "epsilon", "sample", "v_prediction", "flow_prediction"], "visible": False}),
"schedulers_sigma": OptionInfo("default", "Sigma algorithm", gr.Radio, {"choices": ["default", "karras", "exponential", "polyexponential"], "visible": False}),
"schedulers_beta_schedule": OptionInfo("default", "Beta schedule", gr.Dropdown, {"choices": ["default", "linear", "scaled_linear", "squaredcos_cap_v2", "sigmoid"], "visible": False}),
"schedulers_use_thresholding": OptionInfo(False, "Use dynamic thresholding", gr.Checkbox, {"visible": False}),
"schedulers_timestep_spacing": OptionInfo("default", "Timestep spacing", gr.Dropdown, {"choices": ['default', 'linspace', 'leading', 'trailing'], "visible": False}),
'schedulers_timesteps': OptionInfo('', "Timesteps", gr.Textbox, {"visible": False}),
"schedulers_timestep_spacing": OptionInfo("default", "Timestep spacing", gr.Dropdown, {"choices": ["default", "linspace", "leading", "trailing"], "visible": False}),
"schedulers_timesteps": OptionInfo("", "Timesteps", gr.Textbox, {"visible": False}),
"schedulers_rescale_betas": OptionInfo(False, "Rescale betas with zero terminal SNR", gr.Checkbox, {"visible": False}),
'schedulers_beta_start': OptionInfo(0, "Beta start", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.00001}),
'schedulers_beta_end': OptionInfo(0, "Beta end", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.00001}),
'schedulers_timesteps_range': OptionInfo(1000, "Timesteps range", gr.Slider, {"minimum": 250, "maximum": 4000, "step": 1}),
'schedulers_shift': OptionInfo(3, "Sampler shift", gr.Slider, {"minimum": 0.1, "maximum": 10, "step": 0.1, "visible": False}),
'schedulers_dynamic_shift': OptionInfo(False, "Sampler dynamic shift", gr.Checkbox, {"visible": False}),
'schedulers_sigma_adjust': OptionInfo(1.0, "Sigma adjust", gr.Slider, {"minimum": 0.5, "maximum": 1.5, "step": 0.01, "visible": False}),
'schedulers_sigma_adjust_min': OptionInfo(0.2, "Sigma adjust start", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
'schedulers_sigma_adjust_max': OptionInfo(0.8, "Sigma adjust end", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
'schedulers_base_shift': OptionInfo(0.5, "Sampler base shift", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
'schedulers_max_shift': OptionInfo(1.15, "Sampler max shift", gr.Slider, {"minimum": 0.0, "maximum": 4.0, "step": 0.01, "visible": False}),
'uni_pc_variant': OptionInfo("bh2", "UniPC variant", gr.Radio, {"choices": ["bh1", "bh2", "vary_coeff"], "visible": False}),
'uni_pc_skip_type': OptionInfo("time_uniform", "UniPC skip type", gr.Radio, {"choices": ["time_uniform", "time_quadratic", "logSNR"], "visible": False}),
"schedulers_beta_start": OptionInfo(0, "Beta start", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.00001}),
"schedulers_beta_end": OptionInfo(0, "Beta end", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.00001}),
"schedulers_timesteps_range": OptionInfo(1000, "Timesteps range", gr.Slider, {"minimum": 250, "maximum": 4000, "step": 1}),
"schedulers_shift": OptionInfo(3, "Sampler shift", gr.Slider, {"minimum": 0.1, "maximum": 10, "step": 0.1, "visible": False}),
"schedulers_dynamic_shift": OptionInfo(False, "Sampler dynamic shift", gr.Checkbox, {"visible": False}),
"schedulers_sigma_adjust": OptionInfo(1.0, "Sigma adjust", gr.Slider, {"minimum": 0.5, "maximum": 1.5, "step": 0.01, "visible": False}),
"schedulers_sigma_adjust_min": OptionInfo(0.2, "Sigma adjust start", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
"schedulers_sigma_adjust_max": OptionInfo(0.8, "Sigma adjust end", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
"schedulers_base_shift": OptionInfo(0.5, "Sampler base shift", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
"schedulers_max_shift": OptionInfo(1.15, "Sampler max shift", gr.Slider, {"minimum": 0.0, "maximum": 4.0, "step": 0.01, "visible": False}),
"uni_pc_variant": OptionInfo("bh2", "UniPC variant", gr.Radio, {"choices": ["bh1", "bh2", "vary_coeff"], "visible": False}),
"uni_pc_skip_type": OptionInfo("time_uniform", "UniPC skip type", gr.Radio, {"choices": ["time_uniform", "time_quadratic", "logSNR"], "visible": False}),
# detailer settings are handled separately
"detailer_model": OptionInfo("Detailer", "Detailer model", gr.Radio, lambda: {"choices": [x.name() for x in shared.detailers], "visible": False}),
"detailer_classes": OptionInfo("", "Detailer classes", gr.Textbox, { "visible": False}),
"detailer_classes": OptionInfo("", "Detailer classes", gr.Textbox, {"visible": False}),
"detailer_conf": OptionInfo(0.6, "Min confidence", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.05, "visible": False}),
"detailer_max": OptionInfo(2, "Max detected", gr.Slider, {"minimum": 1, "maximum": 10, "step": 1, "visible": False}),
"detailer_iou": OptionInfo(0.5, "Max overlap", gr.Slider, {"minimum": 0, "maximum": 1.0, "step": 0.05, "visible": False}),
@ -753,15 +752,14 @@ def create_settings(cmd_opts):
"detailer_max_size": OptionInfo(1.0, "Max object size", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.05, "visible": False}),
"detailer_padding": OptionInfo(20, "Item padding", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1, "visible": False}),
"detailer_blur": OptionInfo(10, "Item edge blur", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1, "visible": False}),
"detailer_models": OptionInfo(['face-yolo8n'], "Detailer models", gr.Dropdown, lambda: {"multiselect":True, "choices": list(shared.yolo.list) if shared.yolo else [], "visible": False}),
"detailer_args": OptionInfo("", "Detailer args", gr.Textbox, { "visible": False}),
"detailer_models": OptionInfo(["face-yolo8n"], "Detailer models", gr.Dropdown, lambda: {"multiselect": True, "choices": list(shared.yolo.list) if shared.yolo else [], "visible": False}),
"detailer_args": OptionInfo("", "Detailer args", gr.Textbox, {"visible": False}),
"detailer_merge": OptionInfo(False, "Merge multiple results from each detailer model", gr.Checkbox, {"visible": False}),
"detailer_sort": OptionInfo(False, "Sort detailer output by location", gr.Checkbox, {"visible": False}),
"detailer_save": OptionInfo(False, "Include detection results", gr.Checkbox, {"visible": False}),
"detailer_seg": OptionInfo(False, "Use segmentation", gr.Checkbox, {"visible": False}),
}))
# Placeholder for more settings
# ... more settings ...
"detailer_segmentation": OptionInfo(False, "Use segmentation", gr.Checkbox, {"visible": False}),
},
)
)
return options_templates