feat(api): add detailer postprocess script and /sdapi/v1/detail endpoint

Surface YoloRestorer.restore() as a standalone operation: a Detailer
postprocessing script in the Process tab and a thin /sdapi/v1/detail
endpoint, neither requiring a base generation pass.

- modules/postprocess/yolo.py: YoloRestorer.make_processing() builds the
  synthetic Img2Img processing object both entry points feed to restore(),
  resolving the seed so the inpaint passes are reproducible
- modules/api/process.py: post_detail handler exposes the full detailer
  parameter set and returns the detailed image plus optional annotations
  as base64
- scripts/postprocessing_detailer.py: reuses shared.yolo.ui('extras') and
  runs through make_processing()
- modules/postprocessing.py: run_extras takes a per-script script_args
  dict, also letting the extras API drive other scripts such as Remove
  background; omitting it leaves existing callers unchanged
- modules/api/models.py: ReqDetail / ResDetail
- modules/processing_info.py: guard create_infotext's Image/Hires CFG
  reporting against an unset (None) cfg_image, matching the is-not-None
  checks the other cfg_image readers use; the detailer inpaint pass runs
  with it unset
- test/test-detailer-api.py: covers both paths; effect tests measure the
  diff inside the detected region with extreme isolated parameter values,
  and the suite disables model quantization for the run and restores the
  original settings afterward
This commit is contained in:
CalamitousFelicitousness
2026-05-07 22:47:43 +01:00
parent c3eec8e60b
commit f9ab0bf04d
9 changed files with 715 additions and 56 deletions
+7 -3
View File
@@ -100,10 +100,10 @@ def run_postprocessing(extras_mode, image, image_folder: list[tempfile.NamedTemp
return outputs, info, params
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, save_output: bool = True):
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, save_output: bool = True, script_args: dict | None = None):
"""old handler for API"""
args = scripts_manager.scripts_postproc.create_args_for_run({
merged = {
"Upscale": {
"upscale_mode": resize_mode,
"upscale_by": upscaling_resize,
@@ -114,6 +114,10 @@ def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_
"upscaler_2_name": extras_upscaler_2,
"upscaler_2_visibility": extras_upscaler_2_visibility,
},
})
}
if script_args:
for name, kvs in script_args.items():
merged.setdefault(name, {}).update(kvs or {})
args = scripts_manager.scripts_postproc.create_args_for_run(merged)
return run_postprocessing(extras_mode, image, image_folder, input_dir, output_dir, show_extras_results, *args, save_output=save_output)