tntgroup commited on
Commit
1ee3e6d
·
1 Parent(s): e5715db

mask tự động giữ nguyên vùng SP/người, chỉ edit background

Browse files
backend/app/api/listing.py CHANGED
@@ -294,7 +294,10 @@ def _run_generation(sid, image_prompts):
294
  output_path = os.path.join(s["dir"], f"{p['type']}_{sid}.png")
295
 
296
  if is_openai:
297
- generate_image_openai(base_prompt, output_path, model, ref_img, quality, api_key=custom_image_key or custom_key)
 
 
 
298
  else:
299
  cf_label = cf_account.get("custom", False) and "CF custom" or f"CF #{cf_account_tried + 1}"
300
  s["last_status"] = {"level": "info", "message": f" → dùng {cf_label}", "time": time.time()}
@@ -339,7 +342,7 @@ def _run_generation(sid, image_prompts):
339
  continue
340
  try:
341
  fb_path = os.path.join(s["dir"], f"{p['type']}_{sid}_fallback.png")
342
- generate_image_openai(base_prompt, fb_path, model, ref_img, quality, api_key=custom_image_key or custom_key)
343
  s["results"].append({
344
  "type": p["type"], "label": p.get("label", p["type"]),
345
  "prompt": base_prompt, "images": [fb_path], "status": "success",
@@ -481,7 +484,7 @@ async def edit_image(
481
  modified_prompt = f"{orig_prompt}\n\n{preserve}\n\nYêu cầu chỉnh sửa: {modification}"
482
  custom_key = s.get("api_key")
483
  custom_image_key = s.get("image_api_key")
484
- generate_image_openai(modified_prompt, edit_path, model, product_ref, "low", api_key=custom_image_key or custom_key)
485
  else:
486
  modified_prompt = f"{orig_prompt}\n\n{preserve}\n\nYêu cầu chỉnh sửa: {modification}" if not ref_path else modification
487
  cf_account_id = s.get("cf_account_id") or None
 
294
  output_path = os.path.join(s["dir"], f"{p['type']}_{sid}.png")
295
 
296
  if is_openai:
297
+ mask_mode = "auto"
298
+ if ref_type == "scene":
299
+ mask_mode = "invert"
300
+ generate_image_openai(base_prompt, output_path, model, ref_img, quality, api_key=custom_image_key or custom_key, mask_mode=mask_mode)
301
  else:
302
  cf_label = cf_account.get("custom", False) and "CF custom" or f"CF #{cf_account_tried + 1}"
303
  s["last_status"] = {"level": "info", "message": f" → dùng {cf_label}", "time": time.time()}
 
342
  continue
343
  try:
344
  fb_path = os.path.join(s["dir"], f"{p['type']}_{sid}_fallback.png")
345
+ generate_image_openai(base_prompt, fb_path, model, ref_img, quality, api_key=custom_image_key or custom_key, mask_mode=mask_mode)
346
  s["results"].append({
347
  "type": p["type"], "label": p.get("label", p["type"]),
348
  "prompt": base_prompt, "images": [fb_path], "status": "success",
 
484
  modified_prompt = f"{orig_prompt}\n\n{preserve}\n\nYêu cầu chỉnh sửa: {modification}"
485
  custom_key = s.get("api_key")
486
  custom_image_key = s.get("image_api_key")
487
+ generate_image_openai(modified_prompt, edit_path, model, product_ref, "low", api_key=custom_image_key or custom_key, mask_mode="auto")
488
  else:
489
  modified_prompt = f"{orig_prompt}\n\n{preserve}\n\nYêu cầu chỉnh sửa: {modification}" if not ref_path else modification
490
  cf_account_id = s.get("cf_account_id") or None
backend/app/services/listing/generator.py CHANGED
@@ -2,7 +2,21 @@ import base64
2
  import io
3
  import os
4
  import requests
5
- from PIL import Image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
 
8
  CF_ACCOUNTS = [
@@ -116,7 +130,7 @@ def generate_image_flux(prompt, output_path, input_path=None, negative_prompt=No
116
  raise RuntimeError(f"Flux API error: {resp.status_code} {resp.text[:500]}")
117
 
118
 
119
- def generate_image_openai(prompt, output_path, model, input_path=None, quality="high", api_key=None):
120
  import requests as req
121
  from ...config import settings
122
  api_key = api_key or settings.OPENAI_IMAGE_API_KEY or settings.OPENAI_API_KEY
@@ -132,13 +146,24 @@ def generate_image_openai(prompt, output_path, model, input_path=None, quality="
132
  resp_json = None
133
  if input_path and os.path.exists(input_path):
134
  pil_img = Image.open(input_path).convert("RGBA")
135
- buf = io.BytesIO()
136
- pil_img.save(buf, format="PNG")
137
- buf.seek(0)
 
 
 
 
 
 
 
 
 
 
 
138
  r = req.post(
139
  "https://api.openai.com/v1/images/edits",
140
  headers=headers,
141
- files={"image": ("input.png", buf, "image/png")},
142
  data=body,
143
  timeout=300,
144
  )
@@ -146,7 +171,7 @@ def generate_image_openai(prompt, output_path, model, input_path=None, quality="
146
  resp_json = r.json()
147
  else:
148
  err_msg = f"Edits endpoint failed: HTTP {r.status_code} {r.text[:500]}"
149
- print(f"[generator] {err_msg}") # log the actual error
150
  raise RuntimeError(err_msg)
151
 
152
  if resp_json is None:
 
2
  import io
3
  import os
4
  import requests
5
+ from PIL import Image, ImageFilter
6
+
7
+
8
+ def _make_mask(img, invert=False):
9
+ gray = img.convert("L")
10
+ threshold = 200
11
+ mask = gray.point(lambda p: 0 if p > threshold else 255)
12
+ if invert:
13
+ mask = mask.point(lambda p: 255 - p)
14
+ mask = mask.filter(ImageFilter.MaxFilter(7))
15
+ mask = mask.filter(ImageFilter.GaussianBlur(radius=3))
16
+ ext = mask.getextrema()
17
+ if ext == (255, 255) or ext == (0, 0):
18
+ return None
19
+ return mask.convert("L")
20
 
21
 
22
  CF_ACCOUNTS = [
 
130
  raise RuntimeError(f"Flux API error: {resp.status_code} {resp.text[:500]}")
131
 
132
 
133
+ def generate_image_openai(prompt, output_path, model, input_path=None, quality="high", api_key=None, mask_mode="auto"):
134
  import requests as req
135
  from ...config import settings
136
  api_key = api_key or settings.OPENAI_IMAGE_API_KEY or settings.OPENAI_API_KEY
 
146
  resp_json = None
147
  if input_path and os.path.exists(input_path):
148
  pil_img = Image.open(input_path).convert("RGBA")
149
+ img_buf = io.BytesIO()
150
+ pil_img.save(img_buf, format="PNG")
151
+ img_buf.seek(0)
152
+
153
+ files = {"image": ("input.png", img_buf, "image/png")}
154
+
155
+ if mask_mode != "none":
156
+ mask = _make_mask(pil_img, invert=(mask_mode == "invert"))
157
+ if mask is not None:
158
+ mask_buf = io.BytesIO()
159
+ mask.save(mask_buf, format="PNG")
160
+ mask_buf.seek(0)
161
+ files["mask"] = ("mask.png", mask_buf, "image/png")
162
+
163
  r = req.post(
164
  "https://api.openai.com/v1/images/edits",
165
  headers=headers,
166
+ files=files,
167
  data=body,
168
  timeout=300,
169
  )
 
171
  resp_json = r.json()
172
  else:
173
  err_msg = f"Edits endpoint failed: HTTP {r.status_code} {r.text[:500]}"
174
+ print(f"[generator] {err_msg}")
175
  raise RuntimeError(err_msg)
176
 
177
  if resp_json is None: