IronJayx commited on
Commit
9e17d8f
·
1 Parent(s): 4a08ca0
Files changed (1) hide show
  1. app.py +105 -226
app.py CHANGED
@@ -1,153 +1,86 @@
 
1
  import gradio as gr
2
  from gradio_imageslider import ImageSlider
3
- import os
4
  from comfydeploy import ComfyDeploy
5
- import requests
6
  from PIL import Image
 
7
  from io import BytesIO
8
- from dotenv import load_dotenv
9
  import base64
10
- from typing import Optional, Tuple, Union
11
  import glob
12
  import asyncio
 
13
 
14
  load_dotenv()
15
 
16
- # Initialize ComfyDeploy client
17
- client: ComfyDeploy = ComfyDeploy(bearer_auth=os.environ.get("COMFY_DEPLOY_API_KEY"))
18
- deployment_id: str = os.environ.get("COMFY_DEPLOYMENT_ID")
 
 
 
 
 
 
19
 
20
- # Add these global variables at the top of the file, after imports
21
- global_input_image = None
22
- global_image_slider = None
 
 
23
 
24
 
25
  async def process_image(
26
- image: Optional[Union[str, Image.Image]],
27
- denoise: float,
28
- steps: int,
29
- tile_size: int,
30
- downscale: float,
31
- upscale: float,
32
- color_match: float,
33
- controlnet_tile_end: float,
34
- controlnet_tile_strength: float,
35
- progress: gr.Progress = gr.Progress(),
36
- ) -> Tuple[Optional[Image.Image], Optional[Image.Image]]:
37
- # Convert image to base64
38
- if image is not None:
39
- if isinstance(image, str):
40
- with open(image, "rb") as img_file:
41
- image_base64: str = base64.b64encode(img_file.read()).decode("utf-8")
42
- else:
43
- buffered: BytesIO = BytesIO()
44
- image.save(buffered, format="PNG")
45
- image_base64: str = base64.b64encode(buffered.getvalue()).decode("utf-8")
46
- else:
47
- return None, None
48
 
49
- # Prepare inputs
50
- inputs: dict = {
51
  "image": f"data:image/png;base64,{image_base64}",
52
- "denoise": str(denoise),
53
- "steps": str(steps),
54
- "tile_size": str(tile_size),
55
- "downscale": str(downscale),
56
- "upscale": str(upscale),
57
- "color_match": str(color_match),
58
- "controlnet_tile_end": str(controlnet_tile_end),
59
- "controlnet_tile_strength": str(controlnet_tile_strength),
60
  }
61
 
62
- # Call ComfyDeploy API
63
  try:
64
  result = client.run.create(
65
- request={"deployment_id": deployment_id, "inputs": inputs}
66
  )
67
-
68
- if result and result.object:
69
- run_id: str = result.object.run_id
70
- progress(0, desc="Starting processing...")
71
- # Wait for the result
72
- while True:
73
- run_result = client.run.get(run_id=run_id)
74
- progress_value = (
75
- run_result.object.progress
76
- if run_result.object.progress is not None
77
- else 0
78
- )
79
- status = (
80
- run_result.object.live_status
81
- if run_result.object.live_status is not None
82
- else "Cold starting..."
83
- )
84
- progress(progress_value, desc=f"Status: {status}")
85
-
86
- if run_result.object.status == "success":
87
- for output in run_result.object.outputs:
88
- if output.data and output.data.images:
89
- image_url: str = output.data.images[0].url
90
- # Download and return both the original and processed images
91
- response: requests.Response = requests.get(image_url)
92
- processed_image: Image.Image = Image.open(
93
- BytesIO(response.content)
94
- )
95
- return image, processed_image
96
- return None, None
97
- elif run_result.object.status == "failed":
98
- print("Processing failed")
99
- return None, None
100
-
101
- await asyncio.sleep(2) # Wait for 2 seconds before checking again
102
  except Exception as e:
103
  print(f"Error: {e}")
104
  return None, None
105
 
106
 
107
- async def run_async(
108
- denoise,
109
- steps,
110
- tile_size,
111
- downscale,
112
- upscale,
113
- color_match,
114
- controlnet_tile_end,
115
- controlnet_tile_strength,
116
- progress: gr.Progress = gr.Progress(),
117
- ):
118
- global global_input_image
119
- global global_image_slider
120
-
121
- if not global_input_image:
122
- return None
123
-
124
- global_image_slider = None
125
-
126
- original, processed = await process_image(
127
- global_input_image,
128
- denoise,
129
- steps,
130
- tile_size,
131
- downscale,
132
- upscale,
133
- color_match,
134
- controlnet_tile_end,
135
- controlnet_tile_strength,
136
- progress,
137
- )
138
-
139
- if original and processed:
140
- global_image_slider = [original, processed]
141
-
142
- return global_image_slider
143
 
144
 
145
- # Wrapper function for gradio to use
146
- def run(*args):
147
- return asyncio.run(run_async(*args))
148
 
149
 
150
- # Function to load preset images
151
  def load_preset_images():
152
  image_files = glob.glob("images/inputs/*")
153
  return [
@@ -158,129 +91,75 @@ def load_preset_images():
158
  ]
159
 
160
 
161
- # def set_input_image(images, evt: gr.SelectData):
162
- # global global_input_image
163
- # global global_image_slider
164
-
165
- # global_input_image = images[evt.index][0]
166
- # global_image_slider = None
167
-
168
- # return global_input_image
169
-
170
-
171
- def update_global_input_image(image):
172
- global global_input_image
173
- global global_image_slider
174
- global_input_image = image
175
- global_image_slider = None
176
- return None
177
 
178
 
179
- # Define Gradio interface
180
  with gr.Blocks() as demo:
181
  gr.Markdown("# 🌊 Creative Image Upscaler")
182
  with gr.Row():
183
  with gr.Column():
184
- input_image = gr.Image(
185
- type="pil",
186
- label="Input Image",
187
- value=lambda: global_input_image,
188
- interactive=True,
189
- )
190
- input_image.change(
191
- fn=update_global_input_image,
192
- inputs=[input_image],
193
- )
194
-
195
- # Add preset images
196
- # gr.Markdown("### Preset Images")
197
- # preset_images = load_preset_images()
198
- # gallery = gr.Gallery(
199
- # [img["image"] for img in preset_images],
200
- # label="Preset Images",
201
- # columns=5,
202
- # height=130,
203
- # allow_preview=False,
204
- # )
205
- # gallery.select(set_input_image, gallery, input_image)
206
-
207
- with gr.Accordion("Advanced Parameters", open=False):
208
- denoise: gr.Slider = gr.Slider(0, 1, value=0.4, label="Denoise")
209
- steps: gr.Slider = gr.Slider(1, 25, value=10, step=1, label="Steps")
210
- tile_size: gr.Slider = gr.Slider(
211
- 256, 2048, value=1024, step=256, label="Tile Size"
212
- )
213
- downscale: gr.Slider = gr.Slider(
214
- 1, 4, value=1, step=1, label="Downscale"
215
- )
216
- upscale: gr.Slider = gr.Slider(1, 4, value=4, step=1, label="Upscale")
217
- color_match: gr.Slider = gr.Slider(0, 1, value=0, label="Color Match")
218
- controlnet_tile_end: gr.Slider = gr.Slider(
219
  0, 1, value=1, label="ControlNet Tile End"
220
- )
221
- controlnet_tile_strength: gr.Slider = gr.Slider(
222
  0, 1, value=0.7, label="ControlNet Tile Strength"
223
- )
 
224
 
225
- with gr.Column():
226
  image_slider = ImageSlider(
227
- label="Compare Original and Processed",
228
- type="pil",
229
- value=lambda: global_image_slider,
230
- interactive=True,
231
  )
232
 
233
- process_btn: gr.Button = gr.Button("Run", variant="primary", size="lg")
234
  process_btn.click(
235
- fn=run,
236
- inputs=[
237
- denoise,
238
- steps,
239
- tile_size,
240
- downscale,
241
- upscale,
242
- color_match,
243
- controlnet_tile_end,
244
- controlnet_tile_strength,
245
- ],
 
 
 
 
 
 
 
 
 
 
 
246
  outputs=[image_slider],
247
  )
248
 
249
- def build_example(input_image_path):
250
- output_image_path = input_image_path.replace("inputs", "outputs")
251
- return [
252
- input_image_path,
253
- 0.4, # denoise
254
- 10, # steps
255
- 1024, # tile_size
256
- 1, # downscale
257
- 4, # upscale
258
- 0, # color_match
259
- 1, # controlnet_tile_end
260
- 0.7, # controlnet_tile_strength
261
- (input_image_path, output_image_path),
262
- ]
263
-
264
- # Build examples
265
- input_images = glob.glob("images/inputs/*")
266
- examples = [build_example(img) for img in input_images]
267
-
268
- # Update the gr.Examples call
269
- gr.Examples(
270
- examples=examples,
271
- inputs=[
272
- input_image,
273
- denoise,
274
- steps,
275
- tile_size,
276
- downscale,
277
- upscale,
278
- color_match,
279
- controlnet_tile_end,
280
- controlnet_tile_strength,
281
- image_slider,
282
- ],
283
- )
284
 
285
  if __name__ == "__main__":
286
  demo.queue().launch(debug=True, share=True)
 
1
+ import os
2
  import gradio as gr
3
  from gradio_imageslider import ImageSlider
 
4
  from comfydeploy import ComfyDeploy
 
5
  from PIL import Image
6
+ import requests
7
  from io import BytesIO
 
8
  import base64
 
9
  import glob
10
  import asyncio
11
+ from dotenv import load_dotenv
12
 
13
  load_dotenv()
14
 
15
+ API_KEY = os.environ.get("COMFY_DEPLOY_API_KEY")
16
+ DEPLOYMENT_ID = os.environ.get("COMFY_DEPLOYMENT_ID")
17
+
18
+ if not API_KEY or not DEPLOYMENT_ID:
19
+ raise ValueError(
20
+ "Please set COMFY_DEPLOY_API_KEY and COMFY_DEPLOYMENT_ID in your environment variables"
21
+ )
22
+
23
+ client = ComfyDeploy(bearer_auth=API_KEY)
24
 
25
+
26
+ def get_base64_from_image(image: Image.Image) -> str:
27
+ buffered = BytesIO()
28
+ image.save(buffered, format="PNG")
29
+ return base64.b64encode(buffered.getvalue()).decode("utf-8")
30
 
31
 
32
  async def process_image(
33
+ image: Image.Image, params: dict, progress: gr.Progress
34
+ ) -> tuple[Image.Image, Image.Image]:
35
+ progress(0, desc="Preparing inputs...")
36
+ image_base64 = get_base64_from_image(image)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ inputs = {
 
39
  "image": f"data:image/png;base64,{image_base64}",
40
+ **{k: str(v) for k, v in params.items()},
 
 
 
 
 
 
 
41
  }
42
 
 
43
  try:
44
  result = client.run.create(
45
+ request={"deployment_id": DEPLOYMENT_ID, "inputs": inputs}
46
  )
47
+ run_id = result.object.run_id
48
+ progress(0, desc="Starting processing...")
49
+
50
+ while True:
51
+ run_result = client.run.get(run_id=run_id)
52
+ progress_value = run_result.object.progress or 0
53
+ status = run_result.object.live_status or "Cold starting..."
54
+ progress(progress_value, desc=f"Status: {status}")
55
+
56
+ print(run_result)
57
+
58
+ if run_result.object.status == "success":
59
+ for output in run_result.object.outputs:
60
+ if output.data and output.data.images:
61
+ image_url: str = output.data.images[0].url
62
+
63
+ response = requests.get(image_url)
64
+ processed_image = Image.open(BytesIO(response.content))
65
+ return image, processed_image
66
+ elif run_result.object.status == "failed":
67
+ print("Processing failed")
68
+ return None, None
69
+
70
+ await asyncio.sleep(2)
 
 
 
 
 
 
 
 
 
 
 
71
  except Exception as e:
72
  print(f"Error: {e}")
73
  return None, None
74
 
75
 
76
+ async def run_async(image: Image.Image, params: dict, progress: gr.Progress):
77
+ return await process_image(image, params, progress)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
 
80
+ def run(image: Image.Image, params: dict):
81
+ return asyncio.run(run_async(image, params, gr.Progress()))
 
82
 
83
 
 
84
  def load_preset_images():
85
  image_files = glob.glob("images/inputs/*")
86
  return [
 
91
  ]
92
 
93
 
94
+ def build_example(input_image_path):
95
+ output_image_path = input_image_path.replace("inputs", "outputs")
96
+ return [
97
+ input_image_path,
98
+ 0.4,
99
+ 10,
100
+ 1024,
101
+ 1,
102
+ 4,
103
+ 0,
104
+ 1,
105
+ 0.7,
106
+ (input_image_path, output_image_path),
107
+ ]
 
 
108
 
109
 
 
110
  with gr.Blocks() as demo:
111
  gr.Markdown("# 🌊 Creative Image Upscaler")
112
  with gr.Row():
113
  with gr.Column():
114
+ input_image = gr.Image(type="pil", label="Input Image", interactive=True)
115
+ params = {
116
+ "denoise": gr.Slider(0, 1, value=0.4, label="Denoise"),
117
+ "steps": gr.Slider(1, 25, value=10, label="Steps"),
118
+ "tile_size": gr.Slider(256, 2048, value=1024, label="Tile Size"),
119
+ "downscale": gr.Slider(1, 4, value=1, label="Downscale"),
120
+ "upscale": gr.Slider(1, 4, value=4, label="Upscale"),
121
+ "color_match": gr.Slider(0, 1, value=0, label="Color Match"),
122
+ "controlnet_tile_end": gr.Slider(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  0, 1, value=1, label="ControlNet Tile End"
124
+ ),
125
+ "controlnet_tile_strength": gr.Slider(
126
  0, 1, value=0.7, label="ControlNet Tile Strength"
127
+ ),
128
+ }
129
 
130
+ process_btn = gr.Button("Run", variant="primary", size="lg")
131
  image_slider = ImageSlider(
132
+ label="Compare Original and Processed", type="pil", interactive=True
 
 
 
133
  )
134
 
 
135
  process_btn.click(
136
+ fn=lambda img,
137
+ denoise,
138
+ steps,
139
+ tile_size,
140
+ downscale,
141
+ upscale,
142
+ color_match,
143
+ controlnet_tile_end,
144
+ controlnet_tile_strength: run(
145
+ img,
146
+ {
147
+ "denoise": denoise,
148
+ "steps": steps,
149
+ "tile_size": tile_size,
150
+ "downscale": downscale,
151
+ "upscale": upscale,
152
+ "color_match": color_match,
153
+ "controlnet_tile_end": controlnet_tile_end,
154
+ "controlnet_tile_strength": controlnet_tile_strength,
155
+ },
156
+ ),
157
+ inputs=[input_image, *params.values()],
158
  outputs=[image_slider],
159
  )
160
 
161
+ examples = [build_example(img) for img in glob.glob("images/inputs/*")]
162
+ gr.Examples(examples=examples, inputs=[input_image, *params.values(), image_slider])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
  if __name__ == "__main__":
165
  demo.queue().launch(debug=True, share=True)