Spaces:
Running
on
T4
Running
on
T4
Commit
·
5452c3d
1
Parent(s):
fc3f561
feat(api): add passthrough flag to return original image unchanged for /inpaint and /inpaint-multipart
Browse files- api/main.py +33 -2
api/main.py
CHANGED
|
@@ -54,6 +54,7 @@ class InpaintRequest(BaseModel):
|
|
| 54 |
image_id: str
|
| 55 |
mask_id: str
|
| 56 |
invert_mask: bool = True # True => selected/painted area is removed
|
|
|
|
| 57 |
|
| 58 |
|
| 59 |
@app.get("/")
|
|
@@ -147,7 +148,10 @@ def inpaint(req: InpaintRequest, _: None = Depends(bearer_auth)) -> Dict[str, st
|
|
| 147 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 148 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 149 |
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
| 151 |
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 152 |
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 153 |
Image.fromarray(result).save(result_path)
|
|
@@ -168,7 +172,10 @@ def inpaint_url(req: InpaintRequest, request: Request, _: None = Depends(bearer_
|
|
| 168 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 169 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 170 |
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
| 172 |
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 173 |
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 174 |
Image.fromarray(result).save(result_path)
|
|
@@ -185,12 +192,36 @@ def inpaint_multipart(
|
|
| 185 |
request: Request = None,
|
| 186 |
invert_mask: bool = True,
|
| 187 |
mask_is_painted: bool = False, # if True, mask file is the painted-on image (e.g., black strokes on original)
|
|
|
|
| 188 |
_: None = Depends(bearer_auth),
|
| 189 |
) -> Dict[str, str]:
|
| 190 |
# Load in-memory
|
| 191 |
img = Image.open(image.file).convert("RGBA")
|
| 192 |
m = Image.open(mask.file).convert("RGBA")
|
| 193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
if mask_is_painted:
|
| 195 |
# Derive mask by differencing painted image vs original
|
| 196 |
img_rgb = cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2RGB)
|
|
|
|
| 54 |
image_id: str
|
| 55 |
mask_id: str
|
| 56 |
invert_mask: bool = True # True => selected/painted area is removed
|
| 57 |
+
passthrough: bool = False # If True, return the original image unchanged
|
| 58 |
|
| 59 |
|
| 60 |
@app.get("/")
|
|
|
|
| 148 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 149 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 150 |
|
| 151 |
+
if req.passthrough:
|
| 152 |
+
result = np.array(img_rgba.convert("RGB"))
|
| 153 |
+
else:
|
| 154 |
+
result = process_inpaint(np.array(img_rgba), mask_rgba, invert_mask=req.invert_mask)
|
| 155 |
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 156 |
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 157 |
Image.fromarray(result).save(result_path)
|
|
|
|
| 172 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 173 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 174 |
|
| 175 |
+
if req.passthrough:
|
| 176 |
+
result = np.array(img_rgba.convert("RGB"))
|
| 177 |
+
else:
|
| 178 |
+
result = process_inpaint(np.array(img_rgba), mask_rgba, invert_mask=req.invert_mask)
|
| 179 |
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 180 |
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 181 |
Image.fromarray(result).save(result_path)
|
|
|
|
| 192 |
request: Request = None,
|
| 193 |
invert_mask: bool = True,
|
| 194 |
mask_is_painted: bool = False, # if True, mask file is the painted-on image (e.g., black strokes on original)
|
| 195 |
+
passthrough: bool = False,
|
| 196 |
_: None = Depends(bearer_auth),
|
| 197 |
) -> Dict[str, str]:
|
| 198 |
# Load in-memory
|
| 199 |
img = Image.open(image.file).convert("RGBA")
|
| 200 |
m = Image.open(mask.file).convert("RGBA")
|
| 201 |
|
| 202 |
+
if passthrough:
|
| 203 |
+
# Just echo the input image, ignore mask
|
| 204 |
+
result = np.array(img.convert("RGB"))
|
| 205 |
+
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 206 |
+
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 207 |
+
Image.fromarray(result).save(result_path)
|
| 208 |
+
|
| 209 |
+
url: Optional[str] = None
|
| 210 |
+
try:
|
| 211 |
+
if request is not None:
|
| 212 |
+
url = str(request.url_for("download_file", filename=result_name))
|
| 213 |
+
except Exception:
|
| 214 |
+
url = None
|
| 215 |
+
|
| 216 |
+
entry: Dict[str, str] = {"result": result_name, "timestamp": datetime.utcnow().isoformat()}
|
| 217 |
+
if url:
|
| 218 |
+
entry["url"] = url
|
| 219 |
+
logs.append(entry)
|
| 220 |
+
resp: Dict[str, str] = {"result": result_name}
|
| 221 |
+
if url:
|
| 222 |
+
resp["url"] = url
|
| 223 |
+
return resp
|
| 224 |
+
|
| 225 |
if mask_is_painted:
|
| 226 |
# Derive mask by differencing painted image vs original
|
| 227 |
img_rgb = cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2RGB)
|