dovedovepigeon commited on
Commit
2235ebb
1 Parent(s): fcd6568

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -0
app.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from PIL import Image, ImageDraw
4
+ import io
5
+ import requests
6
+
7
+ openai.organization = os.getenv("API_ORG")
8
+ openai.api_key = os.getenv("API_KEY")
9
+ app_password = os.getenv("APP_PASSWORD")
10
+ app_username = os.getenv("APP_USERNAME")
11
+ canvas_width = 500
12
+ canvas_height = 400
13
+
14
+ html = f"""
15
+ <head>
16
+ <style>
17
+ #selectRect {{
18
+ position: absolute;
19
+ border: 1px dashed red;
20
+ background-color: rgba(255, 0, 0, 0.3);
21
+ }}
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <canvas id="canvas-root", width="{canvas_width}", height="{canvas_height}"></canvas>
26
+ <div id="selectRect"></div>
27
+ </body>
28
+ """
29
+
30
+ scripts = """
31
+ async () => {
32
+ let isSelecting = false;
33
+ let startX, startY, endX, endY;
34
+
35
+ const canvas = document.getElementById('canvas-root');
36
+ const ctx = canvas.getContext('2d');
37
+ const canvasRect = canvas.getBoundingClientRect();
38
+
39
+ const selectRect = document.getElementById('selectRect');
40
+
41
+ const coordinatesElement = document.querySelector('#rectangle textarea');
42
+
43
+ function handleMouseDown(event) {
44
+ startX = event.clientX - canvasRect.left;
45
+ startY = event.clientY - canvasRect.top;
46
+ if (startX >= 0 && startY >= 0 && startX <= canvasRect.width && startY <= canvasRect.height) {
47
+ isSelecting = true;
48
+ }
49
+ }
50
+
51
+ function handleMouseMove(event) {
52
+ if (isSelecting) {
53
+ endX = Math.min(event.clientX - canvasRect.left, canvasRect.width);
54
+ endY = Math.min(event.clientY - canvasRect.top, canvasRect.height);
55
+ endX = Math.max(0, endX);
56
+ endY = Math.max(0, endY);
57
+
58
+ const left = Math.min(startX, endX);
59
+ const top = Math.min(startY, endY);
60
+ const width = Math.abs(endX - startX);
61
+ const height = Math.abs(endY - startY);
62
+
63
+ selectRect.style.left = left + 'px';
64
+ selectRect.style.top = top + 'px';
65
+ selectRect.style.width = width + 'px';
66
+ selectRect.style.height = height + 'px';
67
+
68
+ coordinatesElement.value = `{"left": ${left}, "top": ${top}, "width": ${width}, "height": ${height}}`;
69
+ coordinatesElement.dispatchEvent(new CustomEvent("input"))
70
+ }
71
+ }
72
+
73
+ function handleMouseUp() {
74
+ isSelecting = false;
75
+ }
76
+
77
+ document.addEventListener('mousedown', handleMouseDown);
78
+ document.addEventListener('mousemove', handleMouseMove);
79
+ document.addEventListener('mouseup', handleMouseUp);
80
+ }
81
+ """
82
+
83
+ image_change = """
84
+ async () => {
85
+ const canvas = document.getElementById('canvas-root');
86
+ const ctx= canvas.getContext('2d');
87
+ const canvasRect = canvas.getBoundingClientRect();
88
+ const selectRect = document.getElementById('selectRect');
89
+
90
+ selectRect.style.left = 0;
91
+ selectRect.style.top = 0;
92
+ selectRect.style.width = 0;
93
+ selectRect.style.height = 0;
94
+ ctx.clearRect(0, 0, canvasRect.width, canvasRect.height);
95
+
96
+ var img = document.querySelector('#input_image img');
97
+
98
+ img.onload = function(){
99
+ if ((img.naturalWidth / canvasRect.width) > (img.naturalHeight / canvasRect.height)) {
100
+ width = canvasRect.width;
101
+ height = img.naturalHeight * (width / img.naturalWidth);
102
+ } else {
103
+ height = canvasRect.height;
104
+ width = img.naturalWidth * (height / img.naturalHeight);
105
+ }
106
+ ctx.drawImage(img, 0, 0, width, height);
107
+ }
108
+ }
109
+ """
110
+
111
+ def pil_to_bytes(pil_image, format='PNG'):
112
+ image_bytes = io.BytesIO()
113
+ pil_image.save(image_bytes, format=format)
114
+ return image_bytes.getvalue()
115
+
116
+ def expand2square(image, background_color):
117
+ width, height = image.size
118
+ longest = max(width, height)
119
+ result = Image.new(image.mode, (longest, longest), background_color)
120
+ result.paste(image, (0, 0))
121
+ return result.resize((2048, 2048))
122
+
123
+ def gen_mask(image, left, top, right, bottom):
124
+ mask = Image.new("RGBA", image.size, (0, 0, 0, 255))
125
+ width = image.size[0]
126
+ height = image.size[1]
127
+ draw = ImageDraw.Draw(mask)
128
+ draw.rectangle(
129
+ [(left*width, top*height), (right*width, bottom*height)], fill=(255, 255, 255, 0)
130
+ )
131
+ return mask
132
+
133
+ def create_edit(image, rect, prompt):
134
+ rect = json.loads(rect)
135
+ image.putalpha(alpha=255)
136
+ square_image = expand2square(image, "black")
137
+ left, top, width, height = rect["left"], rect["top"], rect["width"], rect["height"]
138
+ left, top, right, bottom = left / canvas_width, top / canvas_height, (left + width) / canvas_width, (top + height) / canvas_height
139
+
140
+ response = openai.Image.create_edit(
141
+ image=pil_to_bytes(square_image),
142
+ mask=pil_to_bytes(gen_mask(square_image, left, top, right, bottom)),
143
+ prompt=prompt,
144
+ n=1,
145
+ size="512x512"
146
+ )
147
+
148
+ edited_image_url = response['data'][0]['url']
149
+ edited_image = requests.get(edited_image_url)
150
+ edited_image = Image.open(io.BytesIO(edited_image.content))
151
+
152
+ raw_width, raw_height = image.size
153
+ raw_longest = max(raw_width, raw_height)
154
+ crop_width = raw_width * edited_image.size[0] / raw_longest
155
+ crop_height = raw_height * edited_image.size[1] / raw_longest
156
+ croped_edited_image = edited_image.crop((0,0,crop_width, crop_height))
157
+
158
+ return croped_edited_image
159
+
160
+ with gr.Blocks() as demo:
161
+ with gr.Column():
162
+ with gr.Row():
163
+ with gr.Column():
164
+ prompt_text = gr.Textbox(label="Prompt")
165
+ prompt_examples = gr.Examples(
166
+ examples=[
167
+ "White plate.",
168
+ "A cherry on top of the pasta.",
169
+ "Curry.",
170
+ ],
171
+ inputs=[prompt_text],
172
+ outputs=None,
173
+ )
174
+ in_image = gr.Image(label="Input", elem_id="input_image", type="pil")
175
+ image_examples = gr.Examples(
176
+ examples=[
177
+ "./001.png",
178
+ "./002.png",
179
+ "./003.png",
180
+ ],
181
+ inputs=[in_image],
182
+ outputs=None,
183
+ )
184
+ out_image = gr.Image(label="Output")
185
+
186
+ with gr.Column():
187
+ gr.Markdown(
188
+ """
189
+ # Edit領域の指定
190
+ ドラッグで編集対象のマスクの領域を指定してください。
191
+ """)
192
+ input_mic = gr.HTML(html)
193
+ btn = gr.Button(value="Image Edit")
194
+ rect_text = gr.Textbox(elem_id="rectangle", visible=False)
195
+ in_image.change(None, inputs=None, outputs=None, _js=image_change)
196
+ btn.click(create_edit, inputs=[in_image, rect_text, prompt_text], outputs=[out_image])
197
+ demo.load(_js=scripts)
198
+
199
+ demo.launch(share=False, auth=(app_username, app_password))