Fabrice-TIERCELIN commited on
Commit
ad6358b
·
verified ·
1 Parent(s): a6a99b6

Click on the landscape 🌄 to upload your image; click on the pen 🖌️ to draw the mask

Browse files
Files changed (1) hide show
  1. app.py +458 -458
app.py CHANGED
@@ -1,459 +1,459 @@
1
- import gradio as gr
2
- import numpy as np
3
- import time
4
- import math
5
- import random
6
- import imageio
7
- import torch
8
- import spaces
9
-
10
- from diffusers import StableDiffusionXLInpaintPipeline
11
- from PIL import Image, ImageFilter, ImageEnhance
12
- import PIL.ImageOps
13
-
14
- max_64_bit_int = 2**63 - 1
15
-
16
- if torch.cuda.is_available():
17
- device = "cuda"
18
- floatType = torch.float16
19
- variant = "fp16"
20
- else:
21
- device = "cpu"
22
- floatType = torch.float32
23
- variant = None
24
-
25
- pipe = StableDiffusionXLInpaintPipeline.from_pretrained("diffusers/stable-diffusion-xl-1.0-inpainting-0.1", torch_dtype = floatType, variant = variant)
26
- pipe = pipe.to(device)
27
-
28
- def update_seed(is_randomize_seed, seed):
29
- if is_randomize_seed:
30
- return random.randint(0, max_64_bit_int)
31
- return seed
32
-
33
- def toggle_debug(is_debug_mode):
34
- return [gr.update(visible = is_debug_mode)] * 2
35
-
36
- def check(
37
- source_img,
38
- prompt,
39
- uploaded_mask,
40
- negative_prompt,
41
- num_inference_steps,
42
- guidance_scale,
43
- image_guidance_scale,
44
- strength,
45
- denoising_steps,
46
- is_randomize_seed,
47
- seed,
48
- debug_mode,
49
- progress = gr.Progress()
50
- ):
51
- if source_img is None:
52
- raise gr.Error("Please provide an image.")
53
-
54
- if prompt is None or prompt == "":
55
- raise gr.Error("Please provide a prompt input.")
56
-
57
- def inpaint(
58
- source_img,
59
- prompt,
60
- uploaded_mask,
61
- negative_prompt,
62
- num_inference_steps,
63
- guidance_scale,
64
- image_guidance_scale,
65
- strength,
66
- denoising_steps,
67
- is_randomize_seed,
68
- seed,
69
- debug_mode,
70
- progress = gr.Progress()
71
- ):
72
- check(
73
- source_img,
74
- prompt,
75
- uploaded_mask,
76
- negative_prompt,
77
- num_inference_steps,
78
- guidance_scale,
79
- image_guidance_scale,
80
- strength,
81
- denoising_steps,
82
- is_randomize_seed,
83
- seed,
84
- debug_mode
85
- )
86
- start = time.time()
87
- progress(0, desc = "Preparing data...")
88
-
89
- if negative_prompt is None:
90
- negative_prompt = ""
91
-
92
- if num_inference_steps is None:
93
- num_inference_steps = 25
94
-
95
- if guidance_scale is None:
96
- guidance_scale = 7
97
-
98
- if image_guidance_scale is None:
99
- image_guidance_scale = 1.1
100
-
101
- if strength is None:
102
- strength = 0.99
103
-
104
- if denoising_steps is None:
105
- denoising_steps = 1000
106
-
107
- if seed is None:
108
- seed = random.randint(0, max_64_bit_int)
109
-
110
- random.seed(seed)
111
- #pipe = pipe.manual_seed(seed)
112
-
113
- input_image = source_img["background"].convert("RGB")
114
-
115
- original_height, original_width, original_channel = np.array(input_image).shape
116
- output_width = original_width
117
- output_height = original_height
118
-
119
- if uploaded_mask is None:
120
- mask_image = source_img["layers"][0].convert("RGB")
121
- else:
122
- mask_image = uploaded_mask.convert("RGB")
123
- mask_image = mask_image.resize((original_width, original_height))
124
-
125
- # Limited to 1 million pixels
126
- if 1024 * 1024 < output_width * output_height:
127
- factor = ((1024 * 1024) / (output_width * output_height))**0.5
128
- process_width = math.floor(output_width * factor)
129
- process_height = math.floor(output_height * factor)
130
-
131
- limitation = " Due to technical limitation, the image have been downscaled and then upscaled.";
132
- else:
133
- process_width = output_width
134
- process_height = output_height
135
-
136
- limitation = "";
137
-
138
- # Width and height must be multiple of 8
139
- if (process_width % 8) != 0 or (process_height % 8) != 0:
140
- if ((process_width - (process_width % 8) + 8) * (process_height - (process_height % 8) + 8)) <= (1024 * 1024):
141
- process_width = process_width - (process_width % 8) + 8
142
- process_height = process_height - (process_height % 8) + 8
143
- elif (process_height % 8) <= (process_width % 8) and ((process_width - (process_width % 8) + 8) * process_height) <= (1024 * 1024):
144
- process_width = process_width - (process_width % 8) + 8
145
- process_height = process_height - (process_height % 8)
146
- elif (process_width % 8) <= (process_height % 8) and (process_width * (process_height - (process_height % 8) + 8)) <= (1024 * 1024):
147
- process_width = process_width - (process_width % 8)
148
- process_height = process_height - (process_height % 8) + 8
149
- else:
150
- process_width = process_width - (process_width % 8)
151
- process_height = process_height - (process_height % 8)
152
-
153
- progress(None, desc = "Processing...")
154
- output_image = inpaint_on_gpu(
155
- seed,
156
- process_width,
157
- process_height,
158
- prompt,
159
- negative_prompt,
160
- input_image,
161
- mask_image,
162
- num_inference_steps,
163
- guidance_scale,
164
- image_guidance_scale,
165
- strength,
166
- denoising_steps
167
- )
168
-
169
- if limitation != "":
170
- output_image = output_image.resize((output_width, output_height))
171
-
172
- if debug_mode == False:
173
- input_image = None
174
- mask_image = None
175
-
176
- end = time.time()
177
- secondes = int(end - start)
178
- minutes = math.floor(secondes / 60)
179
- secondes = secondes - (minutes * 60)
180
- hours = math.floor(minutes / 60)
181
- minutes = minutes - (hours * 60)
182
- return [
183
- output_image,
184
- ("Start again to get a different result. " if is_randomize_seed else "") + "The image has been generated in " + ((str(hours) + " h, ") if hours != 0 else "") + ((str(minutes) + " min, ") if hours != 0 or minutes != 0 else "") + str(secondes) + " sec." + limitation,
185
- input_image,
186
- mask_image
187
- ]
188
-
189
- def inpaint_on_gpu2(
190
- seed,
191
- process_width,
192
- process_height,
193
- prompt,
194
- negative_prompt,
195
- input_image,
196
- mask_image,
197
- num_inference_steps,
198
- guidance_scale,
199
- image_guidance_scale,
200
- strength,
201
- denoising_steps
202
- ):
203
- return input_image
204
-
205
- @spaces.GPU(duration=420)
206
- def inpaint_on_gpu(
207
- seed,
208
- process_width,
209
- process_height,
210
- prompt,
211
- negative_prompt,
212
- input_image,
213
- mask_image,
214
- num_inference_steps,
215
- guidance_scale,
216
- image_guidance_scale,
217
- strength,
218
- denoising_steps
219
- ):
220
- return pipe(
221
- seeds = [seed],
222
- width = process_width,
223
- height = process_height,
224
- prompt = prompt,
225
- negative_prompt = negative_prompt,
226
- image = input_image,
227
- mask_image = mask_image,
228
- num_inference_steps = num_inference_steps,
229
- guidance_scale = guidance_scale,
230
- image_guidance_scale = image_guidance_scale,
231
- strength = strength,
232
- denoising_steps = denoising_steps,
233
- show_progress_bar = True
234
- ).images[0]
235
-
236
- with gr.Blocks() as interface:
237
- gr.HTML(
238
- """
239
- <h1 style="text-align: center;">Inpaint</h1>
240
- <p style="text-align: center;">Modifies one detail of your image, at any resolution, freely, without account, without watermark, without installation, which can be downloaded</p>
241
- <br/>
242
- <br/>
243
- ✨ Powered by <i>SDXL 1.0</i> artificial intellingence. For illustration purpose, not information purpose. The new content is not based on real information but imagination.
244
- <br/>
245
- <ul>
246
- <li>To change the <b>view angle</b> of your image, I recommend to use <i>Zero123</i>,</li>
247
- <li>To <b>upscale</b> your image, I recommend to use <i><a href="https://huggingface.co/spaces/Fabrice-TIERCELIN/SUPIR">SUPIR</a></i>,</li>
248
- <li>To <b>slightly change</b> your image, I recommend to use <i>Image-to-Image SDXL</i>,</li>
249
- <li>If you need to enlarge the <b>viewpoint</b> of your image, I recommend you to use <i>Uncrop</i>,</li>
250
- <li>To remove the <b>background</b> of your image, I recommend to use <i>BRIA</i>,</li>
251
- <li>To make a <b>tile</b> of your image, I recommend to use <i>Make My Image Tile</i>,</li>
252
- <li>To modify <b>anything else</b> on your image, I recommend to use <i>Instruct Pix2Pix</i>.</li>
253
- </ul>
254
- <br/>
255
- """ + ("🏃‍♀️ Estimated time: few minutes. Current device: GPU." if torch.cuda.is_available() else "🐌 Slow process... ~1 hour. Current device: CPU.") + """
256
- Your computer must not enter into standby mode.<br/>You can duplicate this space on a free account, it's designed to work on CPU, GPU and ZeroGPU.<br/>
257
- <a href='https://huggingface.co/spaces/Fabrice-TIERCELIN/Inpaint?duplicate=true'><img src='https://img.shields.io/badge/-Duplicate%20Space-blue?labelColor=white&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOE+lk7FqAkEURY+ltunEgFXS2sZGIbXfEPdLlnxJyDdYB62sbbUKpLbVNhyYFzbrrA74YJlh9r079973psed0cvUD4A+4HoCjsA85X0Dfn/RBLBgBDxnQPfAEJgBY+A9gALA4tcbamSzS4xq4FOQAJgCDwV2CPKV8tZAJcAjMMkUe1vX+U+SMhfAJEHasQIWmXNN3abzDwHUrgcRGmYcgKe0bxrblHEB4E/pndMazNpSZGcsZdBlYJcEL9Afo75molJyM2FxmPgmgPqlWNLGfwZGG6UiyEvLzHYDmoPkDDiNm9JR9uboiONcBXrpY1qmgs21x1QwyZcpvxt9NS09PlsPAAAAAElFTkSuQmCC&logoWidth=14'></a>
258
- <br/>
259
- ⚖️ You can use, modify and share the generated images but not for commercial uses.
260
-
261
- """
262
- )
263
- with gr.Column():
264
- source_img = gr.ImageMask(label = "Your image", type = "pil", brush=gr.Brush(colors=["white"], color_mode="fixed"))
265
- prompt = gr.Textbox(label = "Prompt", info = "Describe the subject, the background and the style of image; 77 token limit", placeholder = "Describe what you want to see in the entire image", lines = 2)
266
- with gr.Accordion("Upload a mask", open = False):
267
- uploaded_mask = gr.Image(label = "Already made mask (black pixels will be preserved, white pixels will be redrawn)", sources = ["upload"], type = "pil")
268
- with gr.Accordion("Advanced options", open = False):
269
- negative_prompt = gr.Textbox(label = "Negative prompt", placeholder = "Describe what you do NOT want to see in the entire image", value = "Ugly, malformed, noise, blur, watermark")
270
- num_inference_steps = gr.Slider(minimum = 10, maximum = 100, value = 25, step = 1, label = "Number of inference steps", info = "lower=faster, higher=image quality")
271
- guidance_scale = gr.Slider(minimum = 1, maximum = 13, value = 7, step = 0.1, label = "Classifier-Free Guidance Scale", info = "lower=image quality, higher=follow the prompt")
272
- image_guidance_scale = gr.Slider(minimum = 1, value = 1.1, step = 0.1, label = "Image Guidance Scale", info = "lower=image quality, higher=follow the image")
273
- strength = gr.Slider(value = 0.99, minimum = 0.01, maximum = 1.0, step = 0.01, label = "Strength", info = "lower=follow the original area, higher=redraw from scratch")
274
- denoising_steps = gr.Number(minimum = 0, value = 1000, step = 1, label = "Denoising", info = "lower=irrelevant result, higher=relevant result")
275
- randomize_seed = gr.Checkbox(label = "\U0001F3B2 Randomize seed", value = True, info = "If checked, result is always different")
276
- seed = gr.Slider(minimum = 0, maximum = max_64_bit_int, step = 1, randomize = True, label = "Seed")
277
- debug_mode = gr.Checkbox(label = "Debug mode", value = False, info = "Show intermediate results")
278
-
279
- submit = gr.Button("🚀 Inpaint", variant = "primary")
280
-
281
- inpainted_image = gr.Image(label = "Inpainted image")
282
- information = gr.HTML()
283
- original_image = gr.Image(label = "Original image", visible = False)
284
- mask_image = gr.Image(label = "Mask image", visible = False)
285
-
286
- submit.click(update_seed, inputs = [
287
- randomize_seed, seed
288
- ], outputs = [
289
- seed
290
- ], queue = False, show_progress = False).then(toggle_debug, debug_mode, [
291
- original_image,
292
- mask_image
293
- ], queue = False, show_progress = False).then(check, inputs = [
294
- source_img,
295
- prompt,
296
- uploaded_mask,
297
- negative_prompt,
298
- num_inference_steps,
299
- guidance_scale,
300
- image_guidance_scale,
301
- strength,
302
- denoising_steps,
303
- randomize_seed,
304
- seed,
305
- debug_mode
306
- ], outputs = [], queue = False, show_progress = False).success(inpaint, inputs = [
307
- source_img,
308
- prompt,
309
- uploaded_mask,
310
- negative_prompt,
311
- num_inference_steps,
312
- guidance_scale,
313
- image_guidance_scale,
314
- strength,
315
- denoising_steps,
316
- randomize_seed,
317
- seed,
318
- debug_mode
319
- ], outputs = [
320
- inpainted_image,
321
- information,
322
- original_image,
323
- mask_image
324
- ], scroll_to_output = True)
325
-
326
- gr.Examples(
327
- fn = inpaint,
328
- inputs = [
329
- source_img,
330
- prompt,
331
- uploaded_mask,
332
- negative_prompt,
333
- num_inference_steps,
334
- guidance_scale,
335
- image_guidance_scale,
336
- strength,
337
- denoising_steps,
338
- randomize_seed,
339
- seed,
340
- debug_mode
341
- ],
342
- outputs = [
343
- inpainted_image,
344
- information,
345
- original_image,
346
- mask_image
347
- ],
348
- examples = [
349
- [
350
- "./Examples/Example1.png",
351
- "A deer, in a forest landscape, ultrarealistic, realistic, photorealistic, 8k",
352
- "./Examples/Mask1.webp",
353
- "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
354
- 25,
355
- 7,
356
- 1.1,
357
- 0.99,
358
- 1000,
359
- False,
360
- 42,
361
- False
362
- ],
363
- [
364
- "./Examples/Example3.jpg",
365
- "An angry old woman, ultrarealistic, realistic, photorealistic, 8k",
366
- "./Examples/Mask3.gif",
367
- "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
368
- 25,
369
- 7,
370
- 1.5,
371
- 0.99,
372
- 1000,
373
- False,
374
- 42,
375
- False
376
- ],
377
- [
378
- "./Examples/Example4.gif",
379
- "A laptop, ultrarealistic, realistic, photorealistic, 8k",
380
- "./Examples/Mask4.bmp",
381
- "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
382
- 25,
383
- 7,
384
- 1.1,
385
- 0.99,
386
- 1000,
387
- False,
388
- 42,
389
- False
390
- ],
391
- [
392
- "./Examples/Example5.bmp",
393
- "A sand castle, ultrarealistic, realistic, photorealistic, 8k",
394
- "./Examples/Mask5.png",
395
- "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
396
- 50,
397
- 7,
398
- 1.5,
399
- 0.5,
400
- 1000,
401
- False,
402
- 42,
403
- False
404
- ],
405
- [
406
- "./Examples/Example2.webp",
407
- "A cat, ultrarealistic, realistic, photorealistic, 8k",
408
- "./Examples/Mask2.png",
409
- "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
410
- 25,
411
- 7,
412
- 1.1,
413
- 0.99,
414
- 1000,
415
- False,
416
- 42,
417
- False
418
- ],
419
- ],
420
- cache_examples = False,
421
- )
422
-
423
- gr.Markdown(
424
- """
425
- ## How to prompt your image
426
-
427
- To easily read your prompt, start with the subject, then describ the pose or action, then secondary elements, then the background, then the graphical style, then the image quality:
428
- ```
429
- A Vietnamese woman, red clothes, walking, smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
430
- ```
431
-
432
- You can use round brackets to increase the importance of a part:
433
- ```
434
- A Vietnamese woman, (red clothes), walking, smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
435
- ```
436
-
437
- You can use several levels of round brackets to even more increase the importance of a part:
438
- ```
439
- A Vietnamese woman, ((red clothes)), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
440
- ```
441
-
442
- You can use number instead of several round brackets:
443
- ```
444
- A Vietnamese woman, (red clothes:1.5), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
445
- ```
446
-
447
- You can do the same thing with square brackets to decrease the importance of a part:
448
- ```
449
- A [Vietnamese] woman, (red clothes:1.5), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
450
- ```
451
-
452
- To easily read your negative prompt, organize it the same way as your prompt (not important for the AI):
453
- ```
454
- man, boy, hat, running, tree, bicycle, forest, drawing, painting, cartoon, 3d, monochrome, blurry, noisy, bokeh
455
- ```
456
- """
457
- )
458
-
459
  interface.queue().launch()
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import time
4
+ import math
5
+ import random
6
+ import imageio
7
+ import torch
8
+ import spaces
9
+
10
+ from diffusers import StableDiffusionXLInpaintPipeline
11
+ from PIL import Image, ImageFilter, ImageEnhance
12
+ import PIL.ImageOps
13
+
14
+ max_64_bit_int = 2**63 - 1
15
+
16
+ if torch.cuda.is_available():
17
+ device = "cuda"
18
+ floatType = torch.float16
19
+ variant = "fp16"
20
+ else:
21
+ device = "cpu"
22
+ floatType = torch.float32
23
+ variant = None
24
+
25
+ pipe = StableDiffusionXLInpaintPipeline.from_pretrained("diffusers/stable-diffusion-xl-1.0-inpainting-0.1", torch_dtype = floatType, variant = variant)
26
+ pipe = pipe.to(device)
27
+
28
+ def update_seed(is_randomize_seed, seed):
29
+ if is_randomize_seed:
30
+ return random.randint(0, max_64_bit_int)
31
+ return seed
32
+
33
+ def toggle_debug(is_debug_mode):
34
+ return [gr.update(visible = is_debug_mode)] * 2
35
+
36
+ def check(
37
+ source_img,
38
+ prompt,
39
+ uploaded_mask,
40
+ negative_prompt,
41
+ num_inference_steps,
42
+ guidance_scale,
43
+ image_guidance_scale,
44
+ strength,
45
+ denoising_steps,
46
+ is_randomize_seed,
47
+ seed,
48
+ debug_mode,
49
+ progress = gr.Progress()
50
+ ):
51
+ if source_img is None:
52
+ raise gr.Error("Please provide an image.")
53
+
54
+ if prompt is None or prompt == "":
55
+ raise gr.Error("Please provide a prompt input.")
56
+
57
+ def inpaint(
58
+ source_img,
59
+ prompt,
60
+ uploaded_mask,
61
+ negative_prompt,
62
+ num_inference_steps,
63
+ guidance_scale,
64
+ image_guidance_scale,
65
+ strength,
66
+ denoising_steps,
67
+ is_randomize_seed,
68
+ seed,
69
+ debug_mode,
70
+ progress = gr.Progress()
71
+ ):
72
+ check(
73
+ source_img,
74
+ prompt,
75
+ uploaded_mask,
76
+ negative_prompt,
77
+ num_inference_steps,
78
+ guidance_scale,
79
+ image_guidance_scale,
80
+ strength,
81
+ denoising_steps,
82
+ is_randomize_seed,
83
+ seed,
84
+ debug_mode
85
+ )
86
+ start = time.time()
87
+ progress(0, desc = "Preparing data...")
88
+
89
+ if negative_prompt is None:
90
+ negative_prompt = ""
91
+
92
+ if num_inference_steps is None:
93
+ num_inference_steps = 25
94
+
95
+ if guidance_scale is None:
96
+ guidance_scale = 7
97
+
98
+ if image_guidance_scale is None:
99
+ image_guidance_scale = 1.1
100
+
101
+ if strength is None:
102
+ strength = 0.99
103
+
104
+ if denoising_steps is None:
105
+ denoising_steps = 1000
106
+
107
+ if seed is None:
108
+ seed = random.randint(0, max_64_bit_int)
109
+
110
+ random.seed(seed)
111
+ #pipe = pipe.manual_seed(seed)
112
+
113
+ input_image = source_img["background"].convert("RGB")
114
+
115
+ original_height, original_width, original_channel = np.array(input_image).shape
116
+ output_width = original_width
117
+ output_height = original_height
118
+
119
+ if uploaded_mask is None:
120
+ mask_image = source_img["layers"][0].convert("RGB")
121
+ else:
122
+ mask_image = uploaded_mask.convert("RGB")
123
+ mask_image = mask_image.resize((original_width, original_height))
124
+
125
+ # Limited to 1 million pixels
126
+ if 1024 * 1024 < output_width * output_height:
127
+ factor = ((1024 * 1024) / (output_width * output_height))**0.5
128
+ process_width = math.floor(output_width * factor)
129
+ process_height = math.floor(output_height * factor)
130
+
131
+ limitation = " Due to technical limitation, the image have been downscaled and then upscaled.";
132
+ else:
133
+ process_width = output_width
134
+ process_height = output_height
135
+
136
+ limitation = "";
137
+
138
+ # Width and height must be multiple of 8
139
+ if (process_width % 8) != 0 or (process_height % 8) != 0:
140
+ if ((process_width - (process_width % 8) + 8) * (process_height - (process_height % 8) + 8)) <= (1024 * 1024):
141
+ process_width = process_width - (process_width % 8) + 8
142
+ process_height = process_height - (process_height % 8) + 8
143
+ elif (process_height % 8) <= (process_width % 8) and ((process_width - (process_width % 8) + 8) * process_height) <= (1024 * 1024):
144
+ process_width = process_width - (process_width % 8) + 8
145
+ process_height = process_height - (process_height % 8)
146
+ elif (process_width % 8) <= (process_height % 8) and (process_width * (process_height - (process_height % 8) + 8)) <= (1024 * 1024):
147
+ process_width = process_width - (process_width % 8)
148
+ process_height = process_height - (process_height % 8) + 8
149
+ else:
150
+ process_width = process_width - (process_width % 8)
151
+ process_height = process_height - (process_height % 8)
152
+
153
+ progress(None, desc = "Processing...")
154
+ output_image = inpaint_on_gpu(
155
+ seed,
156
+ process_width,
157
+ process_height,
158
+ prompt,
159
+ negative_prompt,
160
+ input_image,
161
+ mask_image,
162
+ num_inference_steps,
163
+ guidance_scale,
164
+ image_guidance_scale,
165
+ strength,
166
+ denoising_steps
167
+ )
168
+
169
+ if limitation != "":
170
+ output_image = output_image.resize((output_width, output_height))
171
+
172
+ if debug_mode == False:
173
+ input_image = None
174
+ mask_image = None
175
+
176
+ end = time.time()
177
+ secondes = int(end - start)
178
+ minutes = math.floor(secondes / 60)
179
+ secondes = secondes - (minutes * 60)
180
+ hours = math.floor(minutes / 60)
181
+ minutes = minutes - (hours * 60)
182
+ return [
183
+ output_image,
184
+ ("Start again to get a different result. " if is_randomize_seed else "") + "The image has been generated in " + ((str(hours) + " h, ") if hours != 0 else "") + ((str(minutes) + " min, ") if hours != 0 or minutes != 0 else "") + str(secondes) + " sec." + limitation,
185
+ input_image,
186
+ mask_image
187
+ ]
188
+
189
+ def inpaint_on_gpu2(
190
+ seed,
191
+ process_width,
192
+ process_height,
193
+ prompt,
194
+ negative_prompt,
195
+ input_image,
196
+ mask_image,
197
+ num_inference_steps,
198
+ guidance_scale,
199
+ image_guidance_scale,
200
+ strength,
201
+ denoising_steps
202
+ ):
203
+ return input_image
204
+
205
+ @spaces.GPU(duration=420)
206
+ def inpaint_on_gpu(
207
+ seed,
208
+ process_width,
209
+ process_height,
210
+ prompt,
211
+ negative_prompt,
212
+ input_image,
213
+ mask_image,
214
+ num_inference_steps,
215
+ guidance_scale,
216
+ image_guidance_scale,
217
+ strength,
218
+ denoising_steps
219
+ ):
220
+ return pipe(
221
+ seeds = [seed],
222
+ width = process_width,
223
+ height = process_height,
224
+ prompt = prompt,
225
+ negative_prompt = negative_prompt,
226
+ image = input_image,
227
+ mask_image = mask_image,
228
+ num_inference_steps = num_inference_steps,
229
+ guidance_scale = guidance_scale,
230
+ image_guidance_scale = image_guidance_scale,
231
+ strength = strength,
232
+ denoising_steps = denoising_steps,
233
+ show_progress_bar = True
234
+ ).images[0]
235
+
236
+ with gr.Blocks() as interface:
237
+ gr.HTML(
238
+ """
239
+ <h1 style="text-align: center;">Inpaint</h1>
240
+ <p style="text-align: center;">Modifies one detail of your image, at any resolution, freely, without account, without watermark, without installation, which can be downloaded</p>
241
+ <br/>
242
+ <br/>
243
+ ✨ Powered by <i>SDXL 1.0</i> artificial intellingence. For illustration purpose, not information purpose. The new content is not based on real information but imagination.
244
+ <br/>
245
+ <ul>
246
+ <li>To change the <b>view angle</b> of your image, I recommend to use <i>Zero123</i>,</li>
247
+ <li>To <b>upscale</b> your image, I recommend to use <i><a href="https://huggingface.co/spaces/Fabrice-TIERCELIN/SUPIR">SUPIR</a></i>,</li>
248
+ <li>To <b>slightly change</b> your image, I recommend to use <i>Image-to-Image SDXL</i>,</li>
249
+ <li>If you need to enlarge the <b>viewpoint</b> of your image, I recommend you to use <i>Uncrop</i>,</li>
250
+ <li>To remove the <b>background</b> of your image, I recommend to use <i>BRIA</i>,</li>
251
+ <li>To make a <b>tile</b> of your image, I recommend to use <i>Make My Image Tile</i>,</li>
252
+ <li>To modify <b>anything else</b> on your image, I recommend to use <i>Instruct Pix2Pix</i>.</li>
253
+ </ul>
254
+ <br/>
255
+ """ + ("🏃‍♀️ Estimated time: few minutes. Current device: GPU." if torch.cuda.is_available() else "🐌 Slow process... ~1 hour. Current device: CPU.") + """
256
+ Your computer must not enter into standby mode.<br/>You can duplicate this space on a free account, it's designed to work on CPU, GPU and ZeroGPU.<br/>
257
+ <a href='https://huggingface.co/spaces/Fabrice-TIERCELIN/Inpaint?duplicate=true'><img src='https://img.shields.io/badge/-Duplicate%20Space-blue?labelColor=white&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOE+lk7FqAkEURY+ltunEgFXS2sZGIbXfEPdLlnxJyDdYB62sbbUKpLbVNhyYFzbrrA74YJlh9r079973psed0cvUD4A+4HoCjsA85X0Dfn/RBLBgBDxnQPfAEJgBY+A9gALA4tcbamSzS4xq4FOQAJgCDwV2CPKV8tZAJcAjMMkUe1vX+U+SMhfAJEHasQIWmXNN3abzDwHUrgcRGmYcgKe0bxrblHEB4E/pndMazNpSZGcsZdBlYJcEL9Afo75molJyM2FxmPgmgPqlWNLGfwZGG6UiyEvLzHYDmoPkDDiNm9JR9uboiONcBXrpY1qmgs21x1QwyZcpvxt9NS09PlsPAAAAAElFTkSuQmCC&logoWidth=14'></a>
258
+ <br/>
259
+ ⚖️ You can use, modify and share the generated images but not for commercial uses.
260
+
261
+ """
262
+ )
263
+ with gr.Column():
264
+ source_img = gr.ImageMask(label = "Your image (click on the landscape 🌄 to upload your image; click on the pen 🖌️ to draw the mask)", type = "pil", brush=gr.Brush(colors=["white"], color_mode="fixed"))
265
+ prompt = gr.Textbox(label = "Prompt", info = "Describe the subject, the background and the style of image; 77 token limit", placeholder = "Describe what you want to see in the entire image", lines = 2)
266
+ with gr.Accordion("Upload a mask", open = False):
267
+ uploaded_mask = gr.Image(label = "Already made mask (black pixels will be preserved, white pixels will be redrawn)", sources = ["upload"], type = "pil")
268
+ with gr.Accordion("Advanced options", open = False):
269
+ negative_prompt = gr.Textbox(label = "Negative prompt", placeholder = "Describe what you do NOT want to see in the entire image", value = "Ugly, malformed, noise, blur, watermark")
270
+ num_inference_steps = gr.Slider(minimum = 10, maximum = 100, value = 25, step = 1, label = "Number of inference steps", info = "lower=faster, higher=image quality")
271
+ guidance_scale = gr.Slider(minimum = 1, maximum = 13, value = 7, step = 0.1, label = "Classifier-Free Guidance Scale", info = "lower=image quality, higher=follow the prompt")
272
+ image_guidance_scale = gr.Slider(minimum = 1, value = 1.1, step = 0.1, label = "Image Guidance Scale", info = "lower=image quality, higher=follow the image")
273
+ strength = gr.Slider(value = 0.99, minimum = 0.01, maximum = 1.0, step = 0.01, label = "Strength", info = "lower=follow the original area, higher=redraw from scratch")
274
+ denoising_steps = gr.Number(minimum = 0, value = 1000, step = 1, label = "Denoising", info = "lower=irrelevant result, higher=relevant result")
275
+ randomize_seed = gr.Checkbox(label = "\U0001F3B2 Randomize seed", value = True, info = "If checked, result is always different")
276
+ seed = gr.Slider(minimum = 0, maximum = max_64_bit_int, step = 1, randomize = True, label = "Seed")
277
+ debug_mode = gr.Checkbox(label = "Debug mode", value = False, info = "Show intermediate results")
278
+
279
+ submit = gr.Button("🚀 Inpaint", variant = "primary")
280
+
281
+ inpainted_image = gr.Image(label = "Inpainted image")
282
+ information = gr.HTML()
283
+ original_image = gr.Image(label = "Original image", visible = False)
284
+ mask_image = gr.Image(label = "Mask image", visible = False)
285
+
286
+ submit.click(update_seed, inputs = [
287
+ randomize_seed, seed
288
+ ], outputs = [
289
+ seed
290
+ ], queue = False, show_progress = False).then(toggle_debug, debug_mode, [
291
+ original_image,
292
+ mask_image
293
+ ], queue = False, show_progress = False).then(check, inputs = [
294
+ source_img,
295
+ prompt,
296
+ uploaded_mask,
297
+ negative_prompt,
298
+ num_inference_steps,
299
+ guidance_scale,
300
+ image_guidance_scale,
301
+ strength,
302
+ denoising_steps,
303
+ randomize_seed,
304
+ seed,
305
+ debug_mode
306
+ ], outputs = [], queue = False, show_progress = False).success(inpaint, inputs = [
307
+ source_img,
308
+ prompt,
309
+ uploaded_mask,
310
+ negative_prompt,
311
+ num_inference_steps,
312
+ guidance_scale,
313
+ image_guidance_scale,
314
+ strength,
315
+ denoising_steps,
316
+ randomize_seed,
317
+ seed,
318
+ debug_mode
319
+ ], outputs = [
320
+ inpainted_image,
321
+ information,
322
+ original_image,
323
+ mask_image
324
+ ], scroll_to_output = True)
325
+
326
+ gr.Examples(
327
+ fn = inpaint,
328
+ inputs = [
329
+ source_img,
330
+ prompt,
331
+ uploaded_mask,
332
+ negative_prompt,
333
+ num_inference_steps,
334
+ guidance_scale,
335
+ image_guidance_scale,
336
+ strength,
337
+ denoising_steps,
338
+ randomize_seed,
339
+ seed,
340
+ debug_mode
341
+ ],
342
+ outputs = [
343
+ inpainted_image,
344
+ information,
345
+ original_image,
346
+ mask_image
347
+ ],
348
+ examples = [
349
+ [
350
+ "./Examples/Example1.png",
351
+ "A deer, in a forest landscape, ultrarealistic, realistic, photorealistic, 8k",
352
+ "./Examples/Mask1.webp",
353
+ "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
354
+ 25,
355
+ 7,
356
+ 1.1,
357
+ 0.99,
358
+ 1000,
359
+ False,
360
+ 42,
361
+ False
362
+ ],
363
+ [
364
+ "./Examples/Example3.jpg",
365
+ "An angry old woman, ultrarealistic, realistic, photorealistic, 8k",
366
+ "./Examples/Mask3.gif",
367
+ "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
368
+ 25,
369
+ 7,
370
+ 1.5,
371
+ 0.99,
372
+ 1000,
373
+ False,
374
+ 42,
375
+ False
376
+ ],
377
+ [
378
+ "./Examples/Example4.gif",
379
+ "A laptop, ultrarealistic, realistic, photorealistic, 8k",
380
+ "./Examples/Mask4.bmp",
381
+ "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
382
+ 25,
383
+ 7,
384
+ 1.1,
385
+ 0.99,
386
+ 1000,
387
+ False,
388
+ 42,
389
+ False
390
+ ],
391
+ [
392
+ "./Examples/Example5.bmp",
393
+ "A sand castle, ultrarealistic, realistic, photorealistic, 8k",
394
+ "./Examples/Mask5.png",
395
+ "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
396
+ 50,
397
+ 7,
398
+ 1.5,
399
+ 0.5,
400
+ 1000,
401
+ False,
402
+ 42,
403
+ False
404
+ ],
405
+ [
406
+ "./Examples/Example2.webp",
407
+ "A cat, ultrarealistic, realistic, photorealistic, 8k",
408
+ "./Examples/Mask2.png",
409
+ "Ugly, malformed, painting, drawing, cartoon, anime, 3d, noise, blur, watermark",
410
+ 25,
411
+ 7,
412
+ 1.1,
413
+ 0.99,
414
+ 1000,
415
+ False,
416
+ 42,
417
+ False
418
+ ],
419
+ ],
420
+ cache_examples = False,
421
+ )
422
+
423
+ gr.Markdown(
424
+ """
425
+ ## How to prompt your image
426
+
427
+ To easily read your prompt, start with the subject, then describ the pose or action, then secondary elements, then the background, then the graphical style, then the image quality:
428
+ ```
429
+ A Vietnamese woman, red clothes, walking, smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
430
+ ```
431
+
432
+ You can use round brackets to increase the importance of a part:
433
+ ```
434
+ A Vietnamese woman, (red clothes), walking, smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
435
+ ```
436
+
437
+ You can use several levels of round brackets to even more increase the importance of a part:
438
+ ```
439
+ A Vietnamese woman, ((red clothes)), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
440
+ ```
441
+
442
+ You can use number instead of several round brackets:
443
+ ```
444
+ A Vietnamese woman, (red clothes:1.5), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
445
+ ```
446
+
447
+ You can do the same thing with square brackets to decrease the importance of a part:
448
+ ```
449
+ A [Vietnamese] woman, (red clothes:1.5), (walking), smilling, in the street, a car on the left, in a modern city, photorealistic, 8k
450
+ ```
451
+
452
+ To easily read your negative prompt, organize it the same way as your prompt (not important for the AI):
453
+ ```
454
+ man, boy, hat, running, tree, bicycle, forest, drawing, painting, cartoon, 3d, monochrome, blurry, noisy, bokeh
455
+ ```
456
+ """
457
+ )
458
+
459
  interface.queue().launch()