postprocessing_upscale.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from PIL import Image
  2. import numpy as np
  3. from modules import scripts_postprocessing, shared
  4. import gradio as gr
  5. from modules.ui_components import FormRow
  6. upscale_cache = {}
  7. class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
  8. name = "Upscale"
  9. order = 1000
  10. def ui(self):
  11. selected_tab = gr.State(value=0)
  12. with gr.Tabs(elem_id="extras_resize_mode"):
  13. with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
  14. upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
  15. with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
  16. with FormRow():
  17. upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w")
  18. upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h")
  19. upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
  20. with FormRow():
  21. extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
  22. with FormRow():
  23. extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
  24. extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility")
  25. tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab])
  26. tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab])
  27. return {
  28. "upscale_mode": selected_tab,
  29. "upscale_by": upscaling_resize,
  30. "upscale_to_width": upscaling_resize_w,
  31. "upscale_to_height": upscaling_resize_h,
  32. "upscale_crop": upscaling_crop,
  33. "upscaler_1_name": extras_upscaler_1,
  34. "upscaler_2_name": extras_upscaler_2,
  35. "upscaler_2_visibility": extras_upscaler_2_visibility,
  36. }
  37. def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop):
  38. if upscale_mode == 1:
  39. upscale_by = max(upscale_to_width/image.width, upscale_to_height/image.height)
  40. info["Postprocess upscale to"] = f"{upscale_to_width}x{upscale_to_height}"
  41. else:
  42. info["Postprocess upscale by"] = upscale_by
  43. cache_key = (hash(np.array(image.getdata()).tobytes()), upscaler.name, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  44. cached_image = upscale_cache.pop(cache_key, None)
  45. if cached_image is not None:
  46. image = cached_image
  47. else:
  48. image = upscaler.scaler.upscale(image, upscale_by, upscaler.data_path)
  49. upscale_cache[cache_key] = image
  50. if len(upscale_cache) > shared.opts.upscaling_max_images_in_cache:
  51. upscale_cache.pop(next(iter(upscale_cache), None), None)
  52. if upscale_mode == 1 and upscale_crop:
  53. cropped = Image.new("RGB", (upscale_to_width, upscale_to_height))
  54. cropped.paste(image, box=(upscale_to_width // 2 - image.width // 2, upscale_to_height // 2 - image.height // 2))
  55. image = cropped
  56. info["Postprocess crop to"] = f"{image.width}x{image.height}"
  57. return image
  58. def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_mode=1, upscale_by=2.0, upscale_to_width=None, upscale_to_height=None, upscale_crop=False, upscaler_1_name=None, upscaler_2_name=None, upscaler_2_visibility=0.0):
  59. if upscaler_1_name == "None":
  60. upscaler_1_name = None
  61. upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_1_name]), None)
  62. assert upscaler1 or (upscaler_1_name is None), f'could not find upscaler named {upscaler_1_name}'
  63. if not upscaler1:
  64. return
  65. if upscaler_2_name == "None":
  66. upscaler_2_name = None
  67. upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
  68. assert upscaler2 or (upscaler_2_name is None), f'could not find upscaler named {upscaler_2_name}'
  69. upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  70. pp.info[f"Postprocess upscaler"] = upscaler1.name
  71. if upscaler2 and upscaler_2_visibility > 0:
  72. second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  73. upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility)
  74. pp.info[f"Postprocess upscaler 2"] = upscaler2.name
  75. pp.image = upscaled_image
  76. def image_changed(self):
  77. upscale_cache.clear()