Spaces:
Runtime error
Runtime error
Commit
·
50a83a4
1
Parent(s):
ca1f90f
Atualização
Browse files- app.py +110 -33
- fonts/arial.ttf +0 -0
- templates/template1.png +0 -0
- templates/template2.png +0 -0
app.py
CHANGED
@@ -1,12 +1,11 @@
|
|
|
|
1 |
import io
|
2 |
from io import BytesIO
|
3 |
-
|
4 |
import gradio as gr
|
5 |
import requests
|
6 |
import torch
|
7 |
from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation
|
8 |
-
from
|
9 |
-
from PIL import Image, ImageOps
|
10 |
import PIL
|
11 |
import replicate
|
12 |
import os
|
@@ -18,11 +17,18 @@ device = torch.device(device_name)
|
|
18 |
processor = CLIPSegProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
|
19 |
model_clip = CLIPSegForImageSegmentation.from_pretrained("CIDAS/clipseg-rd64-refined").to(device)
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
model = replicate.models.get(model_name)
|
25 |
-
version = model.versions.get("f9bb0632bfdceb83196e85521b9b55895f8ff3d1d3b487fd1973210c0eb30bec")
|
26 |
|
27 |
|
28 |
def numpy_to_pil(images):
|
@@ -31,7 +37,6 @@ def numpy_to_pil(images):
|
|
31 |
images = (images * 255).round().astype("uint8")
|
32 |
|
33 |
if images.shape[-1] == 1:
|
34 |
-
# special case for grayscale (single channel) images
|
35 |
pil_images = [Image.fromarray(image.squeeze(), mode="L") for image in images]
|
36 |
else:
|
37 |
pil_images = [Image.fromarray(image) for image in images]
|
@@ -48,50 +53,48 @@ def get_mask(text, image):
|
|
48 |
mask = torch.sigmoid(outputs.logits).cpu().detach().unsqueeze(-1).numpy()
|
49 |
|
50 |
mask_pil = numpy_to_pil(mask)[0].resize(image.size)
|
51 |
-
#mask_pil.show()
|
52 |
return mask_pil
|
53 |
|
54 |
|
55 |
def image_to_byte_array(image: Image) -> bytes:
|
56 |
-
# BytesIO is a file-like buffer stored in memory
|
57 |
imgByteArr = io.BytesIO()
|
58 |
-
# image.save expects a file-like as a argument
|
59 |
image.save(imgByteArr, format='PNG')
|
60 |
-
# Turn the BytesIO object back into a bytes object
|
61 |
#imgByteArr = imgByteArr.getvalue()
|
62 |
return imgByteArr
|
63 |
|
64 |
|
65 |
-
def
|
66 |
-
|
|
|
|
|
|
|
|
|
67 |
image = image.convert("RGB").resize((512, 512))
|
68 |
-
mask_image =
|
69 |
mask_image = ImageOps.invert(mask_image)
|
70 |
-
|
71 |
-
# io.BufferedReader(image_to_byte_array(image))
|
72 |
inputs = {
|
73 |
# Input prompt
|
74 |
'prompt': prompt,
|
75 |
|
|
|
|
|
|
|
76 |
# Inital image to generate variations of. Supproting images size with
|
77 |
# 512x512
|
78 |
'image': image_to_byte_array(image),
|
79 |
|
80 |
# Black and white image to use as mask for inpainting over the image
|
81 |
-
# provided.
|
82 |
'mask': image_to_byte_array(mask_image),
|
83 |
|
84 |
-
# Prompt strength when using init image. 1.0 corresponds to full
|
85 |
-
# destruction of information in init image
|
86 |
-
'prompt_strength': 0.8,
|
87 |
-
|
88 |
# Number of images to output. Higher number of outputs may OOM.
|
89 |
# Range: 1 to 8
|
90 |
'num_outputs': 1,
|
91 |
|
92 |
# Number of denoising steps
|
93 |
# Range: 1 to 500
|
94 |
-
'num_inference_steps':
|
95 |
|
96 |
# Scale for classifier-free guidance
|
97 |
# Range: 1 to 20
|
@@ -112,31 +115,105 @@ def predict(prompt, negative_prompt, image, obj2mask):
|
|
112 |
return (img_final)
|
113 |
|
114 |
|
115 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
generator = torch.Generator()
|
117 |
generator.manual_seed(int(52362))
|
118 |
|
119 |
image = numpy_to_pil(image_numpy)[0].convert("RGB").resize((512, 512))
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
123 |
|
124 |
with gr.Blocks() as demo:
|
125 |
with gr.Row():
|
126 |
with gr.Column():
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
130 |
intput_img = gr.Image()
|
131 |
run = gr.Button(value="Generate")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
with gr.Column():
|
133 |
-
|
134 |
|
135 |
run.click(
|
136 |
inference,
|
137 |
-
inputs=[
|
138 |
-
],
|
139 |
-
outputs=output_img,
|
140 |
)
|
141 |
|
142 |
demo.queue(concurrency_count=1)
|
|
|
1 |
+
import asyncio
|
2 |
import io
|
3 |
from io import BytesIO
|
|
|
4 |
import gradio as gr
|
5 |
import requests
|
6 |
import torch
|
7 |
from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation
|
8 |
+
from PIL import Image, ImageOps, ImageDraw, ImageFont
|
|
|
9 |
import PIL
|
10 |
import replicate
|
11 |
import os
|
|
|
17 |
processor = CLIPSegProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
|
18 |
model_clip = CLIPSegForImageSegmentation.from_pretrained("CIDAS/clipseg-rd64-refined").to(device)
|
19 |
|
20 |
+
os.environ['REPLICATE_API_TOKEN'] = 'cbd8d6421f3037d482bd7d6ec8e7368350e3aaab'
|
21 |
+
model = replicate.models.get("stability-ai/stable-diffusion-inpainting")
|
22 |
+
version = model.versions.get("c28b92a7ecd66eee4aefcd8a94eb9e7f6c3805d5f06038165407fb5cb355ba67")
|
23 |
+
|
24 |
+
sf_prompt_1 = "old bridge, mountain, grass"
|
25 |
+
sf_neg_prompt_1 = ""
|
26 |
+
|
27 |
+
sf_prompt_2 = "sunflowers, old bridge, mountain, grass"
|
28 |
+
sf_neg_prompt_2 = "animal"
|
29 |
|
30 |
+
template1 = Image.open("templates/template1.png").resize((512, 512))
|
31 |
+
template2 = Image.open("templates/template2.png").resize((512, 512))
|
|
|
|
|
32 |
|
33 |
|
34 |
def numpy_to_pil(images):
|
|
|
37 |
images = (images * 255).round().astype("uint8")
|
38 |
|
39 |
if images.shape[-1] == 1:
|
|
|
40 |
pil_images = [Image.fromarray(image.squeeze(), mode="L") for image in images]
|
41 |
else:
|
42 |
pil_images = [Image.fromarray(image) for image in images]
|
|
|
53 |
mask = torch.sigmoid(outputs.logits).cpu().detach().unsqueeze(-1).numpy()
|
54 |
|
55 |
mask_pil = numpy_to_pil(mask)[0].resize(image.size)
|
|
|
56 |
return mask_pil
|
57 |
|
58 |
|
59 |
def image_to_byte_array(image: Image) -> bytes:
|
|
|
60 |
imgByteArr = io.BytesIO()
|
|
|
61 |
image.save(imgByteArr, format='PNG')
|
|
|
62 |
#imgByteArr = imgByteArr.getvalue()
|
63 |
return imgByteArr
|
64 |
|
65 |
|
66 |
+
def add_template(image, template):
|
67 |
+
image.paste(template, (0, 0), mask=template)
|
68 |
+
return image
|
69 |
+
|
70 |
+
|
71 |
+
async def predict(prompt, negative_prompt, image, mask_img):
|
72 |
image = image.convert("RGB").resize((512, 512))
|
73 |
+
mask_image = mask_img.convert("RGB").resize((512, 512))
|
74 |
mask_image = ImageOps.invert(mask_image)
|
75 |
+
|
|
|
76 |
inputs = {
|
77 |
# Input prompt
|
78 |
'prompt': prompt,
|
79 |
|
80 |
+
# Specify things to not see in the output
|
81 |
+
'negative_prompt': negative_prompt,
|
82 |
+
|
83 |
# Inital image to generate variations of. Supproting images size with
|
84 |
# 512x512
|
85 |
'image': image_to_byte_array(image),
|
86 |
|
87 |
# Black and white image to use as mask for inpainting over the image
|
88 |
+
# provided. White pixels are inpainted and black pixels are preserved
|
89 |
'mask': image_to_byte_array(mask_image),
|
90 |
|
|
|
|
|
|
|
|
|
91 |
# Number of images to output. Higher number of outputs may OOM.
|
92 |
# Range: 1 to 8
|
93 |
'num_outputs': 1,
|
94 |
|
95 |
# Number of denoising steps
|
96 |
# Range: 1 to 500
|
97 |
+
'num_inference_steps': 25,
|
98 |
|
99 |
# Scale for classifier-free guidance
|
100 |
# Range: 1 to 20
|
|
|
115 |
return (img_final)
|
116 |
|
117 |
|
118 |
+
async def predicts(sf_prompt_1, sf_neg_prompt_1, sf_prompt_2, sf_neg_prompt_2, image, image_numpy, mask_img):
|
119 |
+
testing_local = True
|
120 |
+
if testing_local:
|
121 |
+
img1 = Image.fromarray(image_numpy).convert("RGB").resize((512, 512))
|
122 |
+
img2 = Image.fromarray(image_numpy).convert("RGB").resize((512, 512))
|
123 |
+
return img1, img2
|
124 |
+
|
125 |
+
task1 = asyncio.create_task(predict(sf_prompt_1, sf_neg_prompt_1, image, mask_img))
|
126 |
+
await asyncio.sleep(5)
|
127 |
+
task2 = asyncio.create_task(predict(sf_prompt_2, sf_neg_prompt_2, image, mask_img))
|
128 |
+
|
129 |
+
await task1
|
130 |
+
await task2
|
131 |
+
|
132 |
+
img1 = task1.result()
|
133 |
+
img2 = task2.result()
|
134 |
+
|
135 |
+
return img1, img2
|
136 |
+
|
137 |
+
|
138 |
+
def draw_text(img, template_coords, text1, text2):
|
139 |
+
font1 = ImageFont.truetype(font="fonts/arial.ttf", size=18)
|
140 |
+
font2 = ImageFont.truetype(font="fonts/arial.ttf", size=14)
|
141 |
+
|
142 |
+
x1 = template_coords['x1']
|
143 |
+
y1 = template_coords['y1']
|
144 |
+
x2 = template_coords['x2']
|
145 |
+
y2 = template_coords['y2']
|
146 |
+
|
147 |
+
draw = ImageDraw.Draw(img)
|
148 |
+
draw.text((x1, y1), text1, fill=(255, 0, 0), font=font1)
|
149 |
+
draw.text((x2, y2), text2, fill=(255, 0, 0), font=font2)
|
150 |
+
|
151 |
+
|
152 |
+
def inference(obj2mask, image_numpy, txt_1, txt_2):
|
153 |
generator = torch.Generator()
|
154 |
generator.manual_seed(int(52362))
|
155 |
|
156 |
image = numpy_to_pil(image_numpy)[0].convert("RGB").resize((512, 512))
|
157 |
+
|
158 |
+
mask_img = get_mask(obj2mask, image)
|
159 |
+
|
160 |
+
img1, img2 = asyncio.run(predicts(sf_prompt_1, sf_neg_prompt_1, sf_prompt_2, sf_neg_prompt_2, image, image_numpy, mask_img))
|
161 |
+
|
162 |
+
img1_1 = add_template(img1.copy(), template1.copy())
|
163 |
+
img1_2 = add_template(img1.copy(), template2.copy())
|
164 |
+
|
165 |
+
img2_1 = add_template(img2.copy(), template1.copy())
|
166 |
+
img2_2 = add_template(img2.copy(), template2.copy())
|
167 |
+
|
168 |
+
template1_coords = {
|
169 |
+
'x1': 5,
|
170 |
+
'y1': 300,
|
171 |
+
'x2': 15,
|
172 |
+
'y2': 400
|
173 |
+
}
|
174 |
+
|
175 |
+
template2_coords = {
|
176 |
+
'x1': 5,
|
177 |
+
'y1': 300,
|
178 |
+
'x2': 15,
|
179 |
+
'y2': 400
|
180 |
+
}
|
181 |
+
|
182 |
+
draw_text(img1_1, template1_coords, txt_1, txt_2)
|
183 |
+
draw_text(img1_2, template2_coords, txt_1, txt_2)
|
184 |
+
draw_text(img2_1, template1_coords, txt_1, txt_2)
|
185 |
+
draw_text(img2_2, template2_coords, txt_1, txt_2)
|
186 |
+
|
187 |
+
return [img1_1, img1_2, img2_1, img2_2]
|
188 |
|
189 |
|
190 |
with gr.Blocks() as demo:
|
191 |
with gr.Row():
|
192 |
with gr.Column():
|
193 |
+
txt_1 = gr.Textbox(label="Texto principal da propaganda", value="Promoção Imperdível")
|
194 |
+
txt_2 = gr.Textbox(label="Texto secundário da propaganda", value="Até 50% para alguns produtos")
|
195 |
+
|
196 |
+
mask = gr.Textbox(label="Descrição da imagem", value="shoe")
|
197 |
intput_img = gr.Image()
|
198 |
run = gr.Button(value="Generate")
|
199 |
+
with gr.Row():
|
200 |
+
with gr.Column():
|
201 |
+
output_img1_1 = gr.Image()
|
202 |
+
|
203 |
+
with gr.Column():
|
204 |
+
output_img1_2 = gr.Image()
|
205 |
+
|
206 |
+
with gr.Row():
|
207 |
+
with gr.Column():
|
208 |
+
output_img2_1 = gr.Image()
|
209 |
+
|
210 |
with gr.Column():
|
211 |
+
output_img2_2 = gr.Image()
|
212 |
|
213 |
run.click(
|
214 |
inference,
|
215 |
+
inputs=[mask, intput_img, txt_1, txt_2],
|
216 |
+
outputs=[output_img1_1, output_img1_2, output_img2_1, output_img2_2],
|
|
|
217 |
)
|
218 |
|
219 |
demo.queue(concurrency_count=1)
|
fonts/arial.ttf
ADDED
Binary file (917 kB). View file
|
|
templates/template1.png
ADDED
![]() |
templates/template2.png
ADDED
![]() |