ssboost commited on
Commit
02748b3
ยท
verified ยท
1 Parent(s): 587821b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +214 -158
app.py CHANGED
@@ -1,192 +1,248 @@
1
  import os
2
  import sys
3
- import base64
4
- import io
5
  import logging
6
- import tempfile
7
- import traceback
8
- import requests
9
- from PIL import Image
10
- import gradio as gr
11
  import replicate
 
 
 
 
12
 
13
  # ๋กœ๊น… ์„ค์ •
14
  logging.basicConfig(
15
  level=logging.INFO,
16
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
17
- handlers=[
18
- logging.FileHandler("app.log"),
19
- logging.StreamHandler(sys.stdout)
20
- ]
21
  )
22
- logger = logging.getLogger("enhancer-app")
23
 
24
- # ์ž„์‹œ ํŒŒ์ผ ์ €์žฅ ํ•จ์ˆ˜
25
- def save_uploaded_file(uploaded_file, suffix='.png'):
26
- try:
27
- if uploaded_file is None:
28
- return None
29
-
30
- with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
31
- temp_filename = temp_file.name
32
-
33
- if isinstance(uploaded_file, str):
34
- return uploaded_file
35
-
36
- if isinstance(uploaded_file, Image.Image):
37
- uploaded_file.save(temp_filename, format="PNG")
38
- return temp_filename
39
-
40
- with open(temp_filename, "wb") as f:
41
- if hasattr(uploaded_file, "read"):
42
- content = uploaded_file.read()
43
- f.write(content)
44
- else:
45
- f.write(uploaded_file)
46
-
47
- return temp_filename
48
- except Exception as e:
49
- logger.error(f"Error saving uploaded file: {e}")
50
- logger.error(traceback.format_exc())
51
- return None
52
 
53
- # ์ด๋ฏธ์ง€ ํ™”์งˆ ๊ฐœ์„  ํ•จ์ˆ˜
54
- def enhance_image(
55
- image,
56
  output_format="jpg",
57
- enhancement_level=2 # Fixed enhancement level
 
 
 
 
 
 
 
58
  ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  try:
60
- if image is None:
61
- return None, None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
 
 
62
 
63
- # ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
64
- temp_paths = []
65
- img_path = save_uploaded_file(image)
66
- if not img_path:
67
- return None, None, "์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."
68
 
69
- temp_paths.append(img_path)
 
 
 
 
 
 
 
 
 
 
70
 
71
- # Replicate API ํ† ํฐ ํ™•์ธ
72
- if not os.environ.get("REPLICATE_API_TOKEN"):
73
- return None, None, "API ํ† ํฐ์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
- try:
76
- # Replicate API๋กœ ํ™”์งˆ ํ–ฅ์ƒ
77
- output = replicate.run(
78
- "philz1337x/clarity-upscaler:dfad41707589d68ecdccd1dfa600d55a208f9310748e44bfe35b4a6291453d5e",
79
- input={
80
- "image": open(img_path, "rb"),
81
- "scale_factor": enhancement_level,
82
- "resemblance": 0.8,
83
- "creativity": 0.2,
84
- "output_format": output_format.lower(),
85
- "prompt": "",
86
- "negative_prompt": "(worst quality, low quality, normal quality:2)"
87
- }
88
- )
89
 
90
- # Replicate API ์‘๋‹ต ์ฒ˜๋ฆฌ
91
- if output and isinstance(output, list) and len(output) > 0:
92
- enhanced_url = output[0]
93
 
94
- # ํ–ฅ์ƒ๋œ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ
95
- enhanced_response = requests.get(enhanced_url)
96
- if enhanced_response.status_code == 200:
97
- enhanced_image = Image.open(io.BytesIO(enhanced_response.content))
98
-
99
- # ์ด๋ฏธ์ง€ ํ˜•์‹ ๋ณ€ํ™˜
100
- if output_format.lower() != "png" and enhanced_image.mode == "RGBA":
101
- background = Image.new("RGB", enhanced_image.size, (255, 255, 255))
102
- background.paste(enhanced_image, mask=enhanced_image.split()[3])
103
- enhanced_image = background
104
-
105
- # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ์ €์žฅ
106
- enhanced_path = tempfile.mktemp(suffix=f'.{output_format}')
107
- enhanced_image.save(enhanced_path)
108
- temp_paths.append(enhanced_path)
109
-
110
- return enhanced_image, enhanced_path, ""
111
- else:
112
- return None, None, "์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ ์˜ค๋ฅ˜"
113
- else:
114
- return None, None, "API ์‘๋‹ต ์—†์Œ"
115
 
116
- except Exception as e:
117
- logger.error(f"Error enhancing image: {e}")
118
- logger.error(traceback.format_exc())
119
- return None, None, f"{str(e)}"
120
-
121
- finally:
122
- # ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ (๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋Š” ์œ ์ง€)
123
- for path in temp_paths[:-1]: # ๋งˆ์ง€๋ง‰ ํŒŒ์ผ(๊ฒฐ๊ณผ)์€ ๋‚จ๊น€
124
- if os.path.exists(path):
125
- try:
126
- os.remove(path)
127
- except Exception as e:
128
- logger.error(f"Error removing temp file {path}: {e}")
129
 
130
  except Exception as e:
131
- logger.error(f"Error in enhance_image function: {e}")
132
- logger.error(traceback.format_exc())
133
- return None, None, f"{str(e)}"
 
 
 
134
 
135
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
136
- def create_gradio_interface():
137
- try:
138
- with gr.Blocks() as app:
139
- with gr.Row():
140
- with gr.Column():
141
- input_image = gr.Image(type="pil")
142
-
143
- # Hidden parameters with fixed values
144
- output_format = gr.Dropdown(
145
- choices=["jpg", "png", "webp"],
146
- value="jpg",
147
- visible=False
148
- )
149
- enhancement_level = gr.Number(
150
- value=2,
151
- visible=False
 
 
 
 
 
152
  )
153
-
154
- process_btn = gr.Button("์‹คํ–‰")
 
 
 
155
 
156
- with gr.Column():
157
- output_image = gr.Image()
158
- output_download = gr.File(interactive=False)
159
-
160
- def on_process(img, format, level):
161
- if img is None:
162
- return None, None
163
 
164
- enhanced_img, download_path, error = enhance_image(
165
- img, format, level
166
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- if error:
169
- return None, None
170
 
171
- return enhanced_img, download_path
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
- process_btn.click(
174
- on_process,
175
- inputs=[input_image, output_format, enhancement_level],
176
- outputs=[output_image, output_download]
177
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- return app
180
- except Exception as e:
181
- logger.error(f"Error creating Gradio interface: {e}")
182
- logger.error(traceback.format_exc())
183
- raise
 
 
 
 
 
184
 
185
- # ์•ฑ ์‹คํ–‰
186
  if __name__ == "__main__":
187
- try:
188
- app = create_gradio_interface()
189
- app.launch(share=True)
190
- except Exception as e:
191
- logger.error(f"Error running app: {e}")
192
- logger.error(traceback.format_exc())
 
1
  import os
2
  import sys
 
 
3
  import logging
 
 
 
 
 
4
  import replicate
5
+ import gradio as gr
6
+ from PIL import Image
7
+ import tempfile
8
+ import uuid
9
 
10
  # ๋กœ๊น… ์„ค์ •
11
  logging.basicConfig(
12
  level=logging.INFO,
13
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
14
+ handlers=[logging.StreamHandler(sys.stdout)]
 
 
 
15
  )
16
+ logger = logging.getLogger("clarity-upscaler")
17
 
18
+ # Replicate API ํ† ํฐ ์„ค์ •
19
+ REPLICATE_API_TOKEN = os.environ.get("REPLICATE_API_TOKEN", "")
20
+ if not REPLICATE_API_TOKEN:
21
+ logger.warning("REPLICATE_API_TOKEN์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.")
22
+
23
+ # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
24
+ TEMP_DIR = os.path.join(tempfile.gettempdir(), "clarity_upscaler")
25
+ os.makedirs(TEMP_DIR, exist_ok=True)
26
+ logger.info(f"์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ: {TEMP_DIR}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ def upscale_image(
29
+ image,
30
+ scale_factor=2,
31
  output_format="jpg",
32
+ sd_model="juggernaut_reborn.safetensors [338b85bc4f]",
33
+ resemblance=0.6,
34
+ creativity=0.35,
35
+ prompt="masterpiece, best quality, highres, <lora:more_details:0.5> <lora:SDXLrender_v2.0:1>",
36
+ negative_prompt="(worst quality, low quality, normal quality:2) JuggernautNegative-neg",
37
+ seed=1337,
38
+ dynamic=6,
39
+ sharpen=0
40
  ):
41
+ """
42
+ Clarity Upscaler๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ํ™”์งˆ์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.
43
+
44
+ Args:
45
+ image: ์ž…๋ ฅ ์ด๋ฏธ์ง€
46
+ scale_factor: ํ™•๋Œ€ ๋น„์œจ (๊ธฐ๋ณธ๊ฐ’: 2)
47
+ output_format: ์ถœ๋ ฅ ํ˜•์‹ (๊ธฐ๋ณธ๊ฐ’: jpg)
48
+ sd_model: ์‚ฌ์šฉํ•  SD ๋ชจ๋ธ
49
+ resemblance: ์›๋ณธ๊ณผ์˜ ์œ ์‚ฌ๋„ (0.0-1.0)
50
+ creativity: ์ฐฝ์˜์„ฑ ์ˆ˜์ค€ (0.0-1.0)
51
+ prompt: ์—…์Šค์ผ€์ผ๋ง ๊ฐ€์ด๋“œ ํ”„๋กฌํ”„ํŠธ
52
+ negative_prompt: ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ”„๋กฌํ”„ํŠธ
53
+ seed: ๋žœ๋ค ์‹œ๋“œ
54
+ dynamic: ๋‹ค์ด๋‚˜๋ฏน ์ž„๊ณ„๊ฐ’ (1-10)
55
+ sharpen: ์„ ๋ช…๋„ (0-2)
56
+
57
+ Returns:
58
+ ๊ฐœ์„ ๋œ ์ด๋ฏธ์ง€
59
+ """
60
+ if REPLICATE_API_TOKEN == "":
61
+ raise ValueError("REPLICATE_API_TOKEN์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
62
+
63
  try:
64
+ # ์ด๋ฏธ์ง€ ์ €์žฅ
65
+ temp_input_path = os.path.join(TEMP_DIR, f"input_{uuid.uuid4()}.png")
66
+ image.save(temp_input_path)
67
+ logger.info(f"์ž…๋ ฅ ์ด๋ฏธ์ง€ ์ €์žฅ: {temp_input_path}")
68
 
69
+ # Replicate ์„ค์ •
70
+ replicate.client.Client(api_token=REPLICATE_API_TOKEN)
 
 
 
71
 
72
+ # ๋กœ๊ทธ ์ •๋ณด ์ถœ๋ ฅ
73
+ logger.info("=== Clarity Upscaler ์‹คํ–‰ ์ •๋ณด ===")
74
+ logger.info(f"๋ชจ๋ธ: philz1337x/clarity-upscaler")
75
+ logger.info(f"SD ๋ชจ๋ธ: {sd_model}")
76
+ logger.info(f"์Šค์ผ€์ผ ํŒฉํ„ฐ: {scale_factor}")
77
+ logger.info(f"์ถœ๋ ฅ ํ˜•์‹: {output_format}")
78
+ logger.info(f"์œ ์‚ฌ๋„: {resemblance}")
79
+ logger.info(f"์ฐฝ์˜์„ฑ: {creativity}")
80
+ logger.info(f"๋‹ค์ด๋‚˜๋ฏน: {dynamic}")
81
+ logger.info(f"์„ ๋ช…๋„: {sharpen}")
82
+ logger.info(f"์‹œ๋“œ: {seed}")
83
 
84
+ # API ํ˜ธ์ถœ
85
+ output = replicate.run(
86
+ "philz1337x/clarity-upscaler:dfad41707589d68ecdccd1dfa600d55a208f9310748e44bfe35b4a6291453d5e",
87
+ input={
88
+ "seed": seed,
89
+ "image": open(temp_input_path, "rb"),
90
+ "prompt": prompt,
91
+ "dynamic": dynamic,
92
+ "handfix": "disabled",
93
+ "pattern": False,
94
+ "sharpen": sharpen,
95
+ "sd_model": sd_model,
96
+ "scheduler": "DPM++ 3M SDE Karras",
97
+ "creativity": creativity,
98
+ "lora_links": "",
99
+ "downscaling": False,
100
+ "resemblance": resemblance,
101
+ "scale_factor": scale_factor,
102
+ "tiling_width": 112,
103
+ "output_format": output_format,
104
+ "tiling_height": 144,
105
+ "custom_sd_model": "",
106
+ "negative_prompt": negative_prompt,
107
+ "num_inference_steps": 18,
108
+ "downscaling_resolution": 768
109
+ }
110
+ )
111
 
112
+ logger.info(f"Replicate API ์‘๋‹ต: {output}")
113
+
114
+ # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ ๋ฐ ๋ฐ˜ํ™˜
115
+ if output and isinstance(output, list) and len(output) > 0:
116
+ import requests
117
+ from io import BytesIO
 
 
 
 
 
 
 
 
118
 
119
+ response = requests.get(output[0])
120
+ if response.status_code == 200:
121
+ result_image = Image.open(BytesIO(response.content))
122
 
123
+ # JPG๋กœ ๋ณ€ํ™˜ (output_format์ด jpg์ธ ๊ฒฝ์šฐ)
124
+ if output_format.lower() == "jpg":
125
+ temp_output = BytesIO()
126
+ if result_image.mode == 'RGBA':
127
+ result_image = result_image.convert('RGB')
128
+ result_image.save(temp_output, format='JPEG', quality=95)
129
+ temp_output.seek(0)
130
+ result_image = Image.open(temp_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
+ logger.info("์ด๋ฏธ์ง€ ํ™”์งˆ ๊ฐœ์„  ์™„๋ฃŒ!")
133
+ return result_image
134
+ else:
135
+ logger.error(f"๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ ์‹คํŒจ: {response.status_code}")
136
+ return None
137
+ else:
138
+ logger.error("API ์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
139
+ return None
 
 
 
 
 
140
 
141
  except Exception as e:
142
+ logger.error(f"ํ™”์งˆ ๊ฐœ์„  ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
143
+ raise
144
+ finally:
145
+ # ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ
146
+ if os.path.exists(temp_input_path):
147
+ os.remove(temp_input_path)
148
 
149
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
150
+ def create_interface():
151
+ with gr.Blocks(title="Clarity Upscaler - ์ด๋ฏธ์ง€ ํ™”์งˆ ๊ฐœ์„ ") as demo:
152
+ gr.Markdown("# Clarity Upscaler - ์ด๋ฏธ์ง€ ํ™”์งˆ ๊ฐœ์„  ๋„๊ตฌ")
153
+ gr.Markdown("Replicate์˜ Clarity Upscaler ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€์˜ ํ™”์งˆ์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.")
154
+
155
+ with gr.Row():
156
+ with gr.Column():
157
+ input_image = gr.Image(label="์›๋ณธ ์ด๋ฏธ์ง€", type="pil")
158
+
159
+ with gr.Accordion("๊ณ ๊ธ‰ ์„ค์ •", open=False):
160
+ scale_factor = gr.Slider(minimum=1, maximum=4, value=2, step=0.5, label="ํ™•๋Œ€ ๋น„์œจ")
161
+ output_format = gr.Radio(["jpg", "png"], value="jpg", label="์ถœ๋ ฅ ํ˜•์‹")
162
+ sd_model = gr.Dropdown(
163
+ choices=[
164
+ "juggernaut_reborn.safetensors [338b85bc4f]",
165
+ "sd_xl_base_1.0.safetensors [39d4e625d]",
166
+ "sdxl_base_v0.9-9961.safetensors [3048045c]",
167
+ "realisticVisionV51_v51VAE.safetensors [5ecbfa0ac]",
168
+ ],
169
+ value="juggernaut_reborn.safetensors [338b85bc4f]",
170
+ label="SD ๋ชจ๋ธ"
171
  )
172
+ resemblance = gr.Slider(minimum=0.0, maximum=1.0, value=0.6, step=0.05, label="์›๋ณธ ์œ ์‚ฌ๋„")
173
+ creativity = gr.Slider(minimum=0.0, maximum=1.0, value=0.35, step=0.05, label="์ฐฝ์˜์„ฑ")
174
+ dynamic = gr.Slider(minimum=1, maximum=10, value=6, step=1, label="๋‹ค์ด๋‚˜๋ฏน ์ž„๊ณ„๊ฐ’")
175
+ sharpen = gr.Slider(minimum=0, maximum=2, value=0, step=0.1, label="์„ ๋ช…๋„")
176
+ seed = gr.Number(value=1337, label="์‹œ๋“œ", precision=0)
177
 
178
+ submit_btn = gr.Button("ํ™”์งˆ ๊ฐœ์„  ์‹œ์ž‘", variant="primary")
 
 
 
 
 
 
179
 
180
+ with gr.Column():
181
+ output_image = gr.Image(label="๊ฐœ์„ ๋œ ์ด๋ฏธ์ง€")
182
+ log_output = gr.Textbox(label="๋กœ๊ทธ", lines=10)
183
+
184
+ # ๋กœ๊ทธ ์บก์ฒ˜ ํ•จ์ˆ˜
185
+ class LogCapture:
186
+ def __init__(self):
187
+ self.logs = []
188
+ self.handler = self.create_handler()
189
+
190
+ def create_handler(self):
191
+ handler = logging.StreamHandler(stream=self)
192
+ handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
193
+ return handler
194
+
195
+ def write(self, message):
196
+ self.logs.append(message)
197
 
198
+ def flush(self):
199
+ pass
200
 
201
+ def get_logs(self):
202
+ return "".join(self.logs)
203
+
204
+ def clear(self):
205
+ self.logs.clear()
206
+
207
+ log_capture = LogCapture()
208
+ logger.addHandler(log_capture.handler)
209
+
210
+ # ์ œ์ถœ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋™์ž‘
211
+ def process_image(image, scale_factor, output_format, sd_model, resemblance, creativity, dynamic, sharpen, seed):
212
+ if image is None:
213
+ return None, "์˜ค๋ฅ˜: ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
214
 
215
+ log_capture.clear()
216
+
217
+ try:
218
+ result = upscale_image(
219
+ image=image,
220
+ scale_factor=scale_factor,
221
+ output_format=output_format,
222
+ sd_model=sd_model,
223
+ resemblance=resemblance,
224
+ creativity=creativity,
225
+ dynamic=dynamic,
226
+ sharpen=sharpen,
227
+ seed=int(seed)
228
+ )
229
+ return result, log_capture.get_logs()
230
+ except Exception as e:
231
+ logger.error(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
232
+ return None, log_capture.get_logs()
233
 
234
+ submit_btn.click(
235
+ process_image,
236
+ inputs=[
237
+ input_image, scale_factor, output_format, sd_model,
238
+ resemblance, creativity, dynamic, sharpen, seed
239
+ ],
240
+ outputs=[output_image, log_output]
241
+ )
242
+
243
+ return demo
244
 
245
+ # ๋ฉ”์ธ ์‹คํ–‰
246
  if __name__ == "__main__":
247
+ demo = create_interface()
248
+ demo.launch(share=True)