ssboost commited on
Commit
cbcfce1
ยท
verified ยท
1 Parent(s): 70373d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -43
app.py CHANGED
@@ -62,44 +62,46 @@ def upscale_with_clarity(image_path):
62
  except Exception as e:
63
  return None, f"ํ™”์งˆ ๊ฐœ์„  ์˜ค๋ฅ˜: {str(e)}"
64
 
65
- def force_white_background(image, threshold=240):
66
- """์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๊ฐ•์ œ๋กœ ์™„์ „ํ•œ ํฐ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ"""
 
 
 
67
  try:
68
- # RGB ๋ชจ๋“œ๋กœ ๋ณ€ํ™˜
69
- if image.mode != 'RGB':
70
- image = image.convert('RGB')
71
-
72
- # ์ด๋ฏธ์ง€๋ฅผ numpy ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
73
- img_array = np.array(image)
74
-
75
- # ๋ฐฐ๊ฒฝ์œผ๋กœ ํŒ๋‹จ๋˜๋Š” ์˜์—ญ ์ฐพ๊ธฐ (๋ฐ์€ ์ƒ‰์ƒ ์˜์—ญ)
76
- # ๊ฐ ํ”ฝ์…€์˜ RGB ๊ฐ’์ด ๋ชจ๋‘ threshold ์ด์ƒ์ธ ๊ฒฝ์šฐ ๋ฐฐ๊ฒฝ์œผ๋กœ ํŒ๋‹จ
77
- background_mask = np.all(img_array >= threshold, axis=-1)
78
-
79
- # ๋ฐฐ๊ฒฝ ์˜์—ญ์„ ์™„์ „ํ•œ ํฐ์ƒ‰(255, 255, 255)์œผ๋กœ ๋ณ€๊ฒฝ
80
- img_array[background_mask] = [255, 255, 255]
81
-
82
- # numpy ๋ฐฐ์—ด์„ ๋‹ค์‹œ PIL ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
83
- result_image = Image.fromarray(img_array)
84
 
85
- return result_image, "์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ ๊ฐ•์ œ ์ ์šฉ ์™„๋ฃŒ"
 
 
 
 
 
 
 
86
 
 
 
 
 
 
 
87
  except Exception as e:
88
- return image, f"๋ฐฐ๊ฒฝ ํฐ์ƒ‰ ๋ณ€๊ฒฝ ์‹คํŒจ: {str(e)}"
89
 
90
- def create_coupang_thumbnail_fixed(image_path):
91
- """๊ณ ์ •๋œ ์„ค์ •์œผ๋กœ ์ฟ ํŒก ์ธ๋„ค์ผ ์ƒ์„ฑ"""
92
  if not REPLICATE_API_TOKEN:
93
  return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
94
 
95
  try:
96
- # ๊ณ ์ •๋œ ํ”„๋กฌํ”„ํŠธ: ์™„์ „ํ•œ ํฐ์ƒ‰๋ฐฐ๊ฒฝ + ๊ทธ๋ฆผ์ž ํšจ๊ณผ, 85%์ƒํ’ˆ์ด๋ฏธ์ง€, ๊ฐ๋„๋ฅผ ๋” ํ‹€์–ด์„œ
97
- fixed_prompt = "Professional product photography, dramatic 3/4 angle view rotated 45 degrees, dynamic perspective, pure white background #FFFFFF, natural soft shadows on white background, clean white backdrop, high quality e-commerce photo, solid white background, product takes 85% of image space, tilted composition, angled product placement, subtle drop shadow on white surface"
98
 
99
  output = replicate.run(
100
  "black-forest-labs/flux-kontext-pro",
101
  input={
102
- "prompt": fixed_prompt,
103
  "input_image": open(image_path, "rb"),
104
  "output_format": "jpg"
105
  }
@@ -107,17 +109,12 @@ def create_coupang_thumbnail_fixed(image_path):
107
 
108
  response = requests.get(output)
109
  if response.status_code == 200:
110
- generated_image = Image.open(io.BytesIO(response.content))
111
-
112
- # ์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๊ฐ•์ œ๋กœ ์™„์ „ํ•œ ํฐ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ
113
- final_image, white_bg_msg = force_white_background(generated_image)
114
-
115
- return final_image, f"์ธ๋„ค์ผ ์ƒ์„ฑ ์™„๋ฃŒ + {white_bg_msg}"
116
  else:
117
- return None, "์ธ๋„ค์ผ ์ƒ์„ฑ ์‹คํŒจ"
118
 
119
  except Exception as e:
120
- return None, f"์ธ๋„ค์ผ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
121
 
122
  def process_image(image, remove_bg, upscale_quality):
123
  """๋ฉ”์ธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
@@ -128,7 +125,18 @@ def process_image(image, remove_bg, upscale_quality):
128
  result_image = image.copy()
129
  status_messages = []
130
 
131
- # 1๋‹จ๊ณ„: ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ (์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ „)
 
 
 
 
 
 
 
 
 
 
 
132
  if remove_bg:
133
  temp_path = upload_image_to_temp_url(result_image)
134
  if temp_path:
@@ -140,19 +148,18 @@ def process_image(image, remove_bg, upscale_quality):
140
  status_messages.append(f"โŒ {bg_msg}")
141
  os.unlink(temp_path)
142
 
143
- # 2๋‹จ๊ณ„: ์ฟ ํŒก ์ธ๋„ค์ผ ์ƒ์„ฑ (๊ณ ์ • ์„ค์ •)
144
  temp_path = upload_image_to_temp_url(result_image)
145
  if temp_path:
146
- final_img, final_msg = create_coupang_thumbnail_fixed(temp_path)
147
- if final_img:
148
- result_image = final_img
149
- status_messages.append(f"โœ… {final_msg}")
150
  else:
151
- status_messages.append(f"โŒ {final_msg}")
152
- return None, "\n".join(status_messages)
153
  os.unlink(temp_path)
154
 
155
- # 3๋‹จ๊ณ„: ํ™”์งˆ ๊ฐœ์„  (์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ›„)
156
  if upscale_quality:
157
  temp_path = upload_image_to_temp_url(result_image)
158
  if temp_path:
@@ -164,7 +171,7 @@ def process_image(image, remove_bg, upscale_quality):
164
  status_messages.append(f"โŒ {upscale_msg}")
165
  os.unlink(temp_path)
166
 
167
- # 4๋‹จ๊ณ„: ์ตœ์ข… ํฌ๊ธฐ ์กฐ์ •
168
  result_image = result_image.resize((1000, 1000), Image.Resampling.LANCZOS)
169
  status_messages.append("โœ… 1000x1000 ํฌ๊ธฐ ์กฐ์ • ์™„๋ฃŒ")
170
 
 
62
  except Exception as e:
63
  return None, f"ํ™”์งˆ ๊ฐœ์„  ์˜ค๋ฅ˜: {str(e)}"
64
 
65
+ def change_product_angle(image_path):
66
+ """์ƒํ’ˆ ๊ฐ๋„๋ฅผ ํ‹€์–ด์„œ ๋ณ€๊ฒฝ"""
67
+ if not REPLICATE_API_TOKEN:
68
+ return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
69
+
70
  try:
71
+ # ๊ฐ๋„ ๋ณ€๊ฒฝ ํ”„๋กฌํ”„ํŠธ (๋ฐฐ๊ฒฝ์€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ  ๊ฐ๋„๋งŒ ์ง‘์ค‘)
72
+ angle_prompt = "Change product angle to dramatic 3/4 view rotated 45 degrees, dynamic perspective, tilted composition, angled product placement, professional product photography"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ output = replicate.run(
75
+ "black-forest-labs/flux-kontext-pro",
76
+ input={
77
+ "prompt": angle_prompt,
78
+ "input_image": open(image_path, "rb"),
79
+ "output_format": "jpg"
80
+ }
81
+ )
82
 
83
+ response = requests.get(output)
84
+ if response.status_code == 200:
85
+ return Image.open(io.BytesIO(response.content)), "๊ฐ๋„ ๋ณ€๊ฒฝ ์™„๋ฃŒ"
86
+ else:
87
+ return None, "๊ฐ๋„ ๋ณ€๊ฒฝ ์‹คํŒจ"
88
+
89
  except Exception as e:
90
+ return None, f"๊ฐ๋„ ๋ณ€๊ฒฝ ์˜ค๋ฅ˜: {str(e)}"
91
 
92
+ def add_shadow_only(image_path):
93
+ """๋ฐฐ๊ฒฝ ์ œ๊ฑฐ๋œ ์ƒํ’ˆ์— ๊ทธ๋ฆผ์ž๋งŒ ์ถ”๊ฐ€ (์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ)"""
94
  if not REPLICATE_API_TOKEN:
95
  return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
96
 
97
  try:
98
+ # ๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ํ”„๋กฌํ”„ํŠธ (์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ + ๊ทธ๋ฆผ์ž ํšจ๊ณผ๋งŒ)
99
+ shadow_prompt = "Add natural soft drop shadow to the product on pure white background #FFFFFF, clean white backdrop, subtle shadow on white surface, professional e-commerce photo, solid white background, product takes 85% of image space"
100
 
101
  output = replicate.run(
102
  "black-forest-labs/flux-kontext-pro",
103
  input={
104
+ "prompt": shadow_prompt,
105
  "input_image": open(image_path, "rb"),
106
  "output_format": "jpg"
107
  }
 
109
 
110
  response = requests.get(output)
111
  if response.status_code == 200:
112
+ return Image.open(io.BytesIO(response.content)), "๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์™„๋ฃŒ"
 
 
 
 
 
113
  else:
114
+ return None, "๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์‹คํŒจ"
115
 
116
  except Exception as e:
117
+ return None, f"๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์˜ค๋ฅ˜: {str(e)}"
118
 
119
  def process_image(image, remove_bg, upscale_quality):
120
  """๋ฉ”์ธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
 
125
  result_image = image.copy()
126
  status_messages = []
127
 
128
+ # 1๋‹จ๊ณ„: ์ƒํ’ˆ ๊ฐ๋„ ๋ณ€๊ฒฝ
129
+ temp_path = upload_image_to_temp_url(result_image)
130
+ if temp_path:
131
+ angled_img, angle_msg = change_product_angle(temp_path)
132
+ if angled_img:
133
+ result_image = angled_img
134
+ status_messages.append(f"โœ… {angle_msg}")
135
+ else:
136
+ status_messages.append(f"โŒ {angle_msg}")
137
+ os.unlink(temp_path)
138
+
139
+ # 2๋‹จ๊ณ„: ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ (๋ˆ„๋ผ)
140
  if remove_bg:
141
  temp_path = upload_image_to_temp_url(result_image)
142
  if temp_path:
 
148
  status_messages.append(f"โŒ {bg_msg}")
149
  os.unlink(temp_path)
150
 
151
+ # 3๋‹จ๊ณ„: ๊ทธ๋ฆผ์ž๋งŒ ์ถ”๊ฐ€ (์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ)
152
  temp_path = upload_image_to_temp_url(result_image)
153
  if temp_path:
154
+ shadow_img, shadow_msg = add_shadow_only(temp_path)
155
+ if shadow_img:
156
+ result_image = shadow_img
157
+ status_messages.append(f"โœ… {shadow_msg}")
158
  else:
159
+ status_messages.append(f"โŒ {shadow_msg}")
 
160
  os.unlink(temp_path)
161
 
162
+ # 4๋‹จ๊ณ„: ํ™”์งˆ ๊ฐœ์„  (์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ›„)
163
  if upscale_quality:
164
  temp_path = upload_image_to_temp_url(result_image)
165
  if temp_path:
 
171
  status_messages.append(f"โŒ {upscale_msg}")
172
  os.unlink(temp_path)
173
 
174
+ # 5๋‹จ๊ณ„: ์ตœ์ข… ํฌ๊ธฐ ์กฐ์ •
175
  result_image = result_image.resize((1000, 1000), Image.Resampling.LANCZOS)
176
  status_messages.append("โœ… 1000x1000 ํฌ๊ธฐ ์กฐ์ • ์™„๋ฃŒ")
177