Spaces:
Build error
Build error
Commit
·
b2cae2c
1
Parent(s):
a2c5029
refactor: supabase image fetch
Browse files- src/api/nto_api.py +15 -22
src/api/nto_api.py
CHANGED
|
@@ -619,7 +619,9 @@ async def necklace_try_on_with_points(necklace_try_on_id: NecklaceTryOnIDEntity
|
|
| 619 |
@nto_cto_router.post("/clothingAndNecklaceTryOn")
|
| 620 |
async def clothing_and_necklace_try_on(
|
| 621 |
image: UploadFile = File(...),
|
| 622 |
-
|
|
|
|
|
|
|
| 623 |
clothing_type: str = Form(...)
|
| 624 |
):
|
| 625 |
logger.info("-" * 50)
|
|
@@ -632,70 +634,61 @@ async def clothing_and_necklace_try_on(
|
|
| 632 |
return f"data:image/webp;base64,{base64.b64encode(buffer.getvalue()).decode('utf-8')}"
|
| 633 |
|
| 634 |
try:
|
| 635 |
-
|
| 636 |
-
person_bytes, necklace_bytes = await asyncio.gather(
|
| 637 |
-
image.read(),
|
| 638 |
-
necklace.read()
|
| 639 |
-
)
|
| 640 |
-
|
| 641 |
-
# Convert bytes to PIL Images
|
| 642 |
person_image = Image.open(BytesIO(person_bytes)).convert("RGB").resize((512, 512))
|
| 643 |
-
|
|
|
|
|
|
|
|
|
|
| 644 |
logger.info(">>> IMAGES LOADED SUCCESSFULLY <<<")
|
| 645 |
|
| 646 |
-
# Generate mask and get shoulder points in one go
|
| 647 |
mask, left_point, right_point = await pipeline.shoulderPointMaskGeneration_(image=person_image)
|
| 648 |
logger.info(">>> MASK AND POINTS GENERATION COMPLETED <<<")
|
| 649 |
|
| 650 |
-
# Prepare base64 encodings concurrently
|
| 651 |
mask_data_uri, image_data_uri = await asyncio.gather(
|
| 652 |
asyncio.to_thread(image_to_base64, mask),
|
| 653 |
asyncio.to_thread(image_to_base64, person_image)
|
| 654 |
)
|
| 655 |
|
| 656 |
-
# Run CTO
|
| 657 |
cto_output = replicate_run_cto({
|
| 658 |
"mask": mask_data_uri,
|
| 659 |
"image": image_data_uri,
|
| 660 |
"prompt": f"Dull {clothing_type}, non-reflective clothing, properly worn, natural setting, elegant, natural look, neckline without jewellery, simple, perfect eyes, perfect face, perfect body, high quality, realistic, photorealistic, high resolution,traditional full sleeve blouse",
|
| 661 |
"negative_prompt": "necklaces, jewellery, jewelry, necklace, neckpiece, garland, chain, neck wear, jewelled neck, jeweled neck, necklace on neck, jewellery on neck, accessories, watermark, text, changed background, wider body, narrower body, bad proportions, extra limbs, mutated hands, changed sizes, altered proportions, unnatural body proportions, blury, ugly",
|
| 662 |
-
"num_inference_steps": 20
|
| 663 |
})
|
| 664 |
|
| 665 |
if not cto_output or not isinstance(cto_output, (list, tuple)) or not cto_output[0]:
|
| 666 |
raise ValueError("Invalid output from clothing try-on")
|
| 667 |
|
| 668 |
-
# Download CTO result
|
| 669 |
async with aiohttp.ClientSession() as session:
|
| 670 |
async with session.get(str(cto_output[0])) as response:
|
| 671 |
if response.status != 200:
|
| 672 |
raise HTTPException(status_code=response.status, detail="Failed to fetch CTO output")
|
| 673 |
cto_result_bytes = await response.read()
|
| 674 |
|
| 675 |
-
# Process CTO result and perform NTO with points
|
| 676 |
with BytesIO(cto_result_bytes) as buf:
|
| 677 |
cto_result_image = Image.open(buf).convert("RGB")
|
| 678 |
|
| 679 |
-
# Use necklaceTryOnWithPoints directly with the points we already have
|
| 680 |
result, headerText, _ = await pipeline.necklaceTryOnWithPoints_(
|
| 681 |
image=cto_result_image,
|
| 682 |
jewellery=necklace_image,
|
| 683 |
left_shoulder=left_point,
|
| 684 |
right_shoulder=right_point,
|
| 685 |
-
storename=
|
| 686 |
)
|
| 687 |
-
result.show()
|
| 688 |
|
| 689 |
if result is None:
|
| 690 |
raise ValueError("Failed to process necklace try-on")
|
| 691 |
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
|
|
|
| 695 |
|
| 696 |
response = {
|
| 697 |
"code": 200,
|
| 698 |
-
"output":
|
| 699 |
"inference_time": round((time.time() - start_time), 2)
|
| 700 |
}
|
| 701 |
|
|
|
|
| 619 |
@nto_cto_router.post("/clothingAndNecklaceTryOn")
|
| 620 |
async def clothing_and_necklace_try_on(
|
| 621 |
image: UploadFile = File(...),
|
| 622 |
+
necklaceImageId: str = Form(...),
|
| 623 |
+
necklaceCategory: str = Form(...),
|
| 624 |
+
storename: str = Form(...),
|
| 625 |
clothing_type: str = Form(...)
|
| 626 |
):
|
| 627 |
logger.info("-" * 50)
|
|
|
|
| 634 |
return f"data:image/webp;base64,{base64.b64encode(buffer.getvalue()).decode('utf-8')}"
|
| 635 |
|
| 636 |
try:
|
| 637 |
+
person_bytes = await image.read()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 638 |
person_image = Image.open(BytesIO(person_bytes)).convert("RGB").resize((512, 512))
|
| 639 |
+
|
| 640 |
+
jewellery_url = f"https://lvuhhlrkcuexzqtsbqyu.supabase.co/storage/v1/object/public/Stores/{storename}/{necklaceCategory}/image/{necklaceImageId}.png"
|
| 641 |
+
necklace_image = Image.open(returnBytesData(url=jewellery_url)).convert("RGBA")
|
| 642 |
+
|
| 643 |
logger.info(">>> IMAGES LOADED SUCCESSFULLY <<<")
|
| 644 |
|
|
|
|
| 645 |
mask, left_point, right_point = await pipeline.shoulderPointMaskGeneration_(image=person_image)
|
| 646 |
logger.info(">>> MASK AND POINTS GENERATION COMPLETED <<<")
|
| 647 |
|
|
|
|
| 648 |
mask_data_uri, image_data_uri = await asyncio.gather(
|
| 649 |
asyncio.to_thread(image_to_base64, mask),
|
| 650 |
asyncio.to_thread(image_to_base64, person_image)
|
| 651 |
)
|
| 652 |
|
|
|
|
| 653 |
cto_output = replicate_run_cto({
|
| 654 |
"mask": mask_data_uri,
|
| 655 |
"image": image_data_uri,
|
| 656 |
"prompt": f"Dull {clothing_type}, non-reflective clothing, properly worn, natural setting, elegant, natural look, neckline without jewellery, simple, perfect eyes, perfect face, perfect body, high quality, realistic, photorealistic, high resolution,traditional full sleeve blouse",
|
| 657 |
"negative_prompt": "necklaces, jewellery, jewelry, necklace, neckpiece, garland, chain, neck wear, jewelled neck, jeweled neck, necklace on neck, jewellery on neck, accessories, watermark, text, changed background, wider body, narrower body, bad proportions, extra limbs, mutated hands, changed sizes, altered proportions, unnatural body proportions, blury, ugly",
|
| 658 |
+
"num_inference_steps": 20
|
| 659 |
})
|
| 660 |
|
| 661 |
if not cto_output or not isinstance(cto_output, (list, tuple)) or not cto_output[0]:
|
| 662 |
raise ValueError("Invalid output from clothing try-on")
|
| 663 |
|
|
|
|
| 664 |
async with aiohttp.ClientSession() as session:
|
| 665 |
async with session.get(str(cto_output[0])) as response:
|
| 666 |
if response.status != 200:
|
| 667 |
raise HTTPException(status_code=response.status, detail="Failed to fetch CTO output")
|
| 668 |
cto_result_bytes = await response.read()
|
| 669 |
|
|
|
|
| 670 |
with BytesIO(cto_result_bytes) as buf:
|
| 671 |
cto_result_image = Image.open(buf).convert("RGB")
|
| 672 |
|
|
|
|
| 673 |
result, headerText, _ = await pipeline.necklaceTryOnWithPoints_(
|
| 674 |
image=cto_result_image,
|
| 675 |
jewellery=necklace_image,
|
| 676 |
left_shoulder=left_point,
|
| 677 |
right_shoulder=right_point,
|
| 678 |
+
storename=storename
|
| 679 |
)
|
|
|
|
| 680 |
|
| 681 |
if result is None:
|
| 682 |
raise ValueError("Failed to process necklace try-on")
|
| 683 |
|
| 684 |
+
result_url = await supabase_upload_and_return_url(prefix="clothing_necklace_try_on", image=result)
|
| 685 |
+
|
| 686 |
+
if not result_url:
|
| 687 |
+
raise ValueError("Failed to upload result image")
|
| 688 |
|
| 689 |
response = {
|
| 690 |
"code": 200,
|
| 691 |
+
"output": result_url,
|
| 692 |
"inference_time": round((time.time() - start_time), 2)
|
| 693 |
}
|
| 694 |
|