longshiine commited on
Commit
17d34e6
·
1 Parent(s): 80bf838

feat: 1차 구현 오나료

Browse files

Signed-off-by: longshiine <[email protected]>

app.py CHANGED
@@ -1,6 +1,8 @@
1
  import requests
2
  import gradio as gr
3
  import zipfile
 
 
4
  from PIL import Image
5
  from io import BytesIO
6
  from rembg import remove
@@ -149,30 +151,34 @@ def paste_to_background_type_c(background: Image.Image, product: Image.Image, ma
149
  print(f"Failed to paste product images to background: {e}")
150
  return None
151
 
152
- def create_zip_file(images: list, zip_filename: str = "images.zip") -> bytes:
153
- # 메모리 내에서 ZIP 파일 생성
154
- zip_buffer = BytesIO()
155
-
156
- with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
157
- for i, image in enumerate(images):
158
- # 이미지를 메모리 버퍼에 저장
159
- image_buffer = BytesIO()
160
- image.save(image_buffer, format="PNG")
161
- image_buffer.seek(0)
162
-
163
- # 버퍼 내용을 ZIP 파일에 추가
164
- zipf.writestr(f"image_{i + 1}.png", image_buffer.getvalue())
 
 
165
 
166
- # ZIP 파일 데이터를 반환
167
- zip_buffer.seek(0)
168
- return zip_buffer.getvalue()
169
 
170
  def image_processing_single(background_image: Image.Image, product_image_url: str):
171
  # 각종 설정 값
 
172
  product_image_size = 650 # 배경이 제거된 제품 이미지의 크기
173
  type_b_margin = 15
174
  type_c_margin_1, type_c_margin_2 = 15, 45 # (1=가운데 두개의 마진, 2= 중앙 한개의 top 마진)
175
 
 
 
 
176
  # 이미지 다운로드
177
  original_image = download_image(product_image_url)
178
 
@@ -192,16 +198,30 @@ def image_processing_single(background_image: Image.Image, product_image_url: st
192
 
193
  # 결과 이미지 반환
194
  image_list = [type_a_image, type_b_image, type_c_image]
195
- image_zip_file = create_zip_file(image_list)
196
 
197
- return image_list #, image_zip_file
198
 
199
- def image_processing_multi(background_image: Image.Image, product_image_url_list: list):
200
  # 각종 설정 값
201
  product_image_size = 650 # 배경이 제거된 제품 이미지의 크기
202
  type_b_margin = 15
203
  type_c_margin_1, type_c_margin_2 = 15, 45 # (1=가운데 두개의 마진, 2= 중앙 한개의 top 마진)
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  for idx, product_image_url in enumerate(product_image_url_list):
206
  # 이미지 다운로드
207
  original_image = download_image(product_image_url)
@@ -220,22 +240,67 @@ def image_processing_multi(background_image: Image.Image, product_image_url_list
220
  type_b_image = paste_to_background_type_b(background_image.copy(), resized_image, type_b_margin)
221
  type_c_image = paste_to_background_type_c(background_image.copy(), resized_image, type_c_margin_1, type_c_margin_2)
222
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
225
- with gr.Row():
226
- background_image = gr.Image(label="Background Image", type="pil")
227
- with gr.Tab("Single"):
228
- link = gr.Textbox(label="Image URL")
229
- btn_single = gr.Button("Generate Images")
230
- with gr.Tab("Multi"):
231
- links = gr.File(label="Image URLs (.txt file)")
232
- btn_multi = gr.Button("Generate Images")
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  with gr.Row():
235
  preview = gr.Gallery(label="Generated images", show_label=False, elem_id="gallery", columns=[3], rows=[1], object_fit="contain", height="auto")
236
  output_zip = gr.File(label="Download Result Zip File")
237
 
238
  # evnets
239
- btn_single.click(fn=image_processing_single, inputs=[background_image, link], outputs=[preview], api_name="image_processing")
 
240
 
241
  demo.launch()
 
1
  import requests
2
  import gradio as gr
3
  import zipfile
4
+ import os
5
+ import tempfile
6
  from PIL import Image
7
  from io import BytesIO
8
  from rembg import remove
 
151
  print(f"Failed to paste product images to background: {e}")
152
  return None
153
 
154
+ def create_zip_file(images: list) -> str:
155
+ # 임시 파일 생성
156
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as temp_zip:
157
+ with zipfile.ZipFile(temp_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:
158
+ for i, image in enumerate(images):
159
+ # 이미지를 메모리 버퍼에 저장
160
+ image_buffer = BytesIO()
161
+ image.save(image_buffer, format="PNG")
162
+ image_buffer.seek(0)
163
+
164
+ # 버퍼 내용을 ZIP 파일에 추가
165
+ zipf.writestr(f"image_{i + 1}.png", image_buffer.getvalue())
166
+
167
+ # 임시 파일의 경로를 반환
168
+ temp_zip_path = temp_zip.name
169
 
170
+ return temp_zip_path
 
 
171
 
172
  def image_processing_single(background_image: Image.Image, product_image_url: str):
173
  # 각종 설정 값
174
+ background_image_size = 1024 # 배경 이미지의 크기
175
  product_image_size = 650 # 배경이 제거된 제품 이미지의 크기
176
  type_b_margin = 15
177
  type_c_margin_1, type_c_margin_2 = 15, 45 # (1=가운데 두개의 마진, 2= 중앙 한개의 top 마진)
178
 
179
+ # 배경 이미지 크기 조정
180
+ background_image = background_image.resize((background_image_size, background_image_size))
181
+
182
  # 이미지 다운로드
183
  original_image = download_image(product_image_url)
184
 
 
198
 
199
  # 결과 이미지 반환
200
  image_list = [type_a_image, type_b_image, type_c_image]
201
+ zip_file_path = create_zip_file(image_list)
202
 
203
+ return image_list, zip_file_path
204
 
205
+ def image_processing_batch(background_image: Image.Image, product_image_url_file_path: str):
206
  # 각종 설정 값
207
  product_image_size = 650 # 배경이 제거된 제품 이미지의 크기
208
  type_b_margin = 15
209
  type_c_margin_1, type_c_margin_2 = 15, 45 # (1=가운데 두개의 마진, 2= 중앙 한개의 top 마진)
210
 
211
+ # file to url
212
+ def file_to_list(file_path: str) -> list:
213
+ # 파일을 열고 읽기
214
+ with open(file_path, "r") as f:
215
+ # 파일 내용을 읽어서 줄바꿈(엔터)로 구분된 각 URL을 리스트로 변환
216
+ content = f.read()
217
+ # 줄바꿈으로 URL 분리
218
+ url_list = [url.strip() for url in content.splitlines() if url.strip()]
219
+
220
+ return url_list
221
+
222
+ product_image_url_list = file_to_list(product_image_url_file_path)
223
+
224
+ preview_image_list, image_list = [], []
225
  for idx, product_image_url in enumerate(product_image_url_list):
226
  # 이미지 다운로드
227
  original_image = download_image(product_image_url)
 
240
  type_b_image = paste_to_background_type_b(background_image.copy(), resized_image, type_b_margin)
241
  type_c_image = paste_to_background_type_c(background_image.copy(), resized_image, type_c_margin_1, type_c_margin_2)
242
 
243
+ image_list.append(type_a_image)
244
+ image_list.append(type_b_image)
245
+ image_list.append(type_c_image)
246
+ if idx == 0:
247
+ preview_image_list = [type_a_image, type_b_image, type_c_image]
248
+
249
+ zip_file_path = create_zip_file(image_list)
250
+
251
+ return preview_image_list, zip_file_path
252
+
253
 
254
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
255
+ gr.HTML("""
256
+ <h1>Product Image Generator</h1>
257
+ <p>1. 배경 이미지를 업로드해주세요.<p>
258
+ <p>2-1. Single 모드의 경우, 이미지의 링크를 입력해주세요.<p>
259
+ <p>2-2. Batch 모드의 경우, 이미지 링크들이 포함된 .txt 파일(형식 = 링크1(엔터) 링크2(엔터) ..)을 업로드해주세요.<p>
260
+ <p>3. Generate Images 버튼을 눌러 제품 이미지를 생성해주세요.<p>
261
+ """)
 
262
 
263
+ with gr.Row(elem_classes="input_box"):
264
+ with gr.Column():
265
+ background_image = gr.Image(label="Background Image", type="pil", height=300)
266
+ gr.Examples(
267
+ examples=[["examples/background_1.png"], ["examples/background_2.png"], ["examples/background_3.png"], ["examples/background_4.png"]], # 예제 이미지 경로 리스트
268
+ inputs=background_image, # 예제를 클릭했을 때 해당 이미지가 이 input에 적용됨
269
+ label="예제 배경 이미지")
270
+ with gr.Tab("Single Mode"):
271
+ with gr.Column():
272
+ link = gr.Textbox(label="Image URL")
273
+ gr.Examples(
274
+ examples=["https://url.kr/yx85be", "https://url.kr/if4wxo"],
275
+ inputs=link,
276
+ label="예제 이미지 링크"
277
+ )
278
+ btn_single = gr.Button("Generate Images")
279
+ with gr.Tab("Batch Mode"):
280
+ gr.HTML("<div>링크1(엔터) 링크2(엔터) ... 으로 구성된 .txt 파일을 업로드</div>")
281
+ with gr.Column():
282
+ links = gr.File(label="Image URLs (.txt file)", height=100)
283
+ gr.Examples(
284
+ examples=[["examples/links.txt"]],
285
+ inputs=links,
286
+ label="예제 .txt 파일"
287
+ )
288
+ btn_batch = gr.Button("Generate Images")
289
+
290
+ gr.HTML("""
291
+ <br><br>
292
+ <h1>생성 결과 확인</h1>
293
+ <p>생성은 1개 이미지 당 15~30초 소요되며(배경제거 AI 모듈 처리시간), 결과는 다음과 같이 제공됩니다.</p>
294
+ <p>1. 첫번째 이미지에 대한 프리뷰(3개 타입)</p>
295
+ <p>2. 결과 이미지 전체가 담긴 ZIP 파일(results.zip) 다운로드 링크가 제공됩니다</p>
296
+ """)
297
+
298
  with gr.Row():
299
  preview = gr.Gallery(label="Generated images", show_label=False, elem_id="gallery", columns=[3], rows=[1], object_fit="contain", height="auto")
300
  output_zip = gr.File(label="Download Result Zip File")
301
 
302
  # evnets
303
+ btn_single.click(fn=image_processing_single, inputs=[background_image, link], outputs=[preview, output_zip], api_name="image_processing_single")
304
+ btn_batch.click(fn=image_processing_batch, inputs=[background_image, links], outputs=[preview, output_zip], api_name="image_processing_batch")
305
 
306
  demo.launch()
examples/background_1.png ADDED
examples/background_2.png ADDED
examples/background_3.png ADDED
examples/background_4.png ADDED
links.txt → examples/links.txt RENAMED
@@ -1,10 +1,10 @@
1
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/drb/drb00370/v/67.jpg,
2
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/cgn/cgn01206/l/73.jpg,
3
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/sre/sre01256/l/96.jpg,
4
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/lex/lex19936/v/115.jpg,
5
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/cey/cey66577/v/6.jpg,
6
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nor/nor01844/v/39.jpg,
7
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/swv/swv06072/v/8.jpg,
8
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/age/age00855/v/40.jpg,
9
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nhi/nhi03515/v/41.jpg,
10
- https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nhi/nhi03512/v/49.jpg,
 
1
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/drb/drb00370/v/67.jpg
2
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/cgn/cgn01206/l/73.jpg
3
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/sre/sre01256/l/96.jpg
4
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/lex/lex19936/v/115.jpg
5
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/cey/cey66577/v/6.jpg
6
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nor/nor01844/v/39.jpg
7
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/swv/swv06072/v/8.jpg
8
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/age/age00855/v/40.jpg
9
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nhi/nhi03515/v/41.jpg
10
+ https://cloudinary.images-iherb.com/image/upload/f_auto,q_auto:eco/images/nhi/nhi03512/v/49.jpg