postprocessing_upscale.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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, ToolButton
  6. from modules.ui import switch_values_symbol
  7. upscale_cache = {}
  8. class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
  9. name = "Upscale"
  10. order = 1000
  11. def ui(self):
  12. selected_tab = gr.State(value=0)
  13. with gr.Column():
  14. with FormRow():
  15. with gr.Tabs(elem_id="extras_resize_mode"):
  16. with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
  17. upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
  18. with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
  19. with FormRow():
  20. with gr.Column(elem_id="upscaling_column_size", scale=4):
  21. upscaling_resize_w = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w")
  22. upscaling_resize_h = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h")
  23. with gr.Column(elem_id="upscaling_dimensions_row", scale=1, elem_classes="dimensions-tools"):
  24. upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="upscaling_res_switch_btn", tooltip="Switch width/height")
  25. upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
  26. with FormRow():
  27. 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)
  28. with FormRow():
  29. 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)
  30. 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")
  31. upscaling_res_switch_btn.click(lambda w, h: (h, w), inputs=[upscaling_resize_w, upscaling_resize_h], outputs=[upscaling_resize_w, upscaling_resize_h], show_progress=False)
  32. tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab])
  33. tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab])
  34. return {
  35. "upscale_mode": selected_tab,
  36. "upscale_by": upscaling_resize,
  37. "upscale_to_width": upscaling_resize_w,
  38. "upscale_to_height": upscaling_resize_h,
  39. "upscale_crop": upscaling_crop,
  40. "upscaler_1_name": extras_upscaler_1,
  41. "upscaler_2_name": extras_upscaler_2,
  42. "upscaler_2_visibility": extras_upscaler_2_visibility,
  43. }
  44. def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop):
  45. if upscale_mode == 1:
  46. upscale_by = max(upscale_to_width/image.width, upscale_to_height/image.height)
  47. info["Postprocess upscale to"] = f"{upscale_to_width}x{upscale_to_height}"
  48. else:
  49. info["Postprocess upscale by"] = upscale_by
  50. cache_key = (hash(np.array(image.getdata()).tobytes()), upscaler.name, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  51. cached_image = upscale_cache.pop(cache_key, None)
  52. if cached_image is not None:
  53. image = cached_image
  54. else:
  55. image = upscaler.scaler.upscale(image, upscale_by, upscaler.data_path)
  56. upscale_cache[cache_key] = image
  57. if len(upscale_cache) > shared.opts.upscaling_max_images_in_cache:
  58. upscale_cache.pop(next(iter(upscale_cache), None), None)
  59. if upscale_mode == 1 and upscale_crop:
  60. cropped = Image.new("RGB", (upscale_to_width, upscale_to_height))
  61. cropped.paste(image, box=(upscale_to_width // 2 - image.width // 2, upscale_to_height // 2 - image.height // 2))
  62. image = cropped
  63. info["Postprocess crop to"] = f"{image.width}x{image.height}"
  64. return image
  65. 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):
  66. if upscaler_1_name == "None":
  67. upscaler_1_name = None
  68. upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_1_name]), None)
  69. assert upscaler1 or (upscaler_1_name is None), f'could not find upscaler named {upscaler_1_name}'
  70. if not upscaler1:
  71. return
  72. if upscaler_2_name == "None":
  73. upscaler_2_name = None
  74. upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
  75. assert upscaler2 or (upscaler_2_name is None), f'could not find upscaler named {upscaler_2_name}'
  76. upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  77. pp.info["Postprocess upscaler"] = upscaler1.name
  78. if upscaler2 and upscaler_2_visibility > 0:
  79. second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
  80. upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility)
  81. pp.info["Postprocess upscaler 2"] = upscaler2.name
  82. pp.image = upscaled_image
  83. def image_changed(self):
  84. upscale_cache.clear()
  85. class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
  86. name = "Simple Upscale"
  87. order = 900
  88. def ui(self):
  89. with FormRow():
  90. upscaler_name = gr.Dropdown(label='Upscaler', choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
  91. upscale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label="Upscale by", value=2)
  92. return {
  93. "upscale_by": upscale_by,
  94. "upscaler_name": upscaler_name,
  95. }
  96. def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_by=2.0, upscaler_name=None):
  97. if upscaler_name is None or upscaler_name == "None":
  98. return
  99. upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None)
  100. assert upscaler1, f'could not find upscaler named {upscaler_name}'
  101. pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, False)
  102. pp.info["Postprocess upscaler"] = upscaler1.name