ishworrsubedii commited on
Commit
130fb6c
·
1 Parent(s): 5a186b4

add: necklace try on points

Browse files
app.py CHANGED
@@ -31,7 +31,7 @@ app.add_middleware(
31
  )
32
  url: str = os.getenv("SUPABASE_URL")
33
  key: str = os.getenv("SUPABASE_KEY")
34
- supabase: Client = create_client(url, key)
35
  bucket = supabase.storage.from_("JewelMirrorOutputs")
36
 
37
 
@@ -411,3 +411,52 @@ async def canvas_points(necklace_try_on_id: NecklaceTryOnIDEntity = Depends(pars
411
 
412
  else:
413
  return JSONResponse(content=response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  )
32
  url: str = os.getenv("SUPABASE_URL")
33
  key: str = os.getenv("SUPABASE_KEY")
34
+ supabase: Client = create_client(supabase_key=key, supabase_url=url)
35
  bucket = supabase.storage.from_("JewelMirrorOutputs")
36
 
37
 
 
411
 
412
  else:
413
  return JSONResponse(content=response)
414
+
415
+
416
+ @app.post("/necklaceTryOnWithPoints")
417
+ async def necklace_try_on_with_points(necklace_try_on_id: NecklaceTryOnIDEntity = Depends(parse_necklace_try_on_id),
418
+ image: UploadFile = File(...),
419
+ left_x: int = Form(...),
420
+ left_y: int = Form(...),
421
+ right_x: int = Form(...),
422
+ right_y: int = Form(...)):
423
+ imageBytes = await image.read()
424
+
425
+ jewellery_url = f"https://lvuhhlrkcuexzqtsbqyu.supabase.co/storage/v1/object/public/Stores/{necklace_try_on_id.storename}/{necklace_try_on_id.necklaceCategory}/image/{necklace_try_on_id.necklaceImageId}.png"
426
+
427
+ try:
428
+ image, jewellery = Image.open(BytesIO(imageBytes)), Image.open(returnBytesData(url=jewellery_url))
429
+
430
+ except:
431
+ error_message = {
432
+ "error": "The requested resource (Image, necklace category, or store) is not available. Please verify the availability and try again."
433
+ }
434
+
435
+ return JSONResponse(content=error_message, status_code=404)
436
+
437
+ result, headerText, mask = await pipeline.necklaceTryOnWithPoints_(
438
+ image=image, jewellery=jewellery, left_shoulder=(left_x, left_y), right_shoulder=(right_x, right_y),
439
+ storename=necklace_try_on_id.storename
440
+ )
441
+
442
+ inMemFile = BytesIO()
443
+ inMemFileMask = BytesIO()
444
+ result.save(inMemFile, format="WEBP", quality=85)
445
+ mask.save(inMemFileMask, format="WEBP", quality=85)
446
+ outputBytes = inMemFile.getvalue()
447
+ maskBytes = inMemFileMask.getvalue()
448
+ response = {
449
+ "output": f"data:image/WEBP;base64,{base64.b64encode(outputBytes).decode('utf-8')}",
450
+ "mask": f"data:image/WEBP;base64,{base64.b64encode(maskBytes).decode('utf-8')}"
451
+ }
452
+
453
+ creditResponse = deductAndTrackCredit(storename=necklace_try_on_id.storename, endpoint="/necklaceTryOnID")
454
+ if creditResponse == "No Credits Available":
455
+ response = {
456
+ "error": "No Credits Remaining"
457
+ }
458
+
459
+ return JSONResponse(content=response)
460
+
461
+ else:
462
+ return JSONResponse(content=response)
src/components/necklaceTryOn.py CHANGED
@@ -343,3 +343,64 @@ class NecklaceTryOn:
343
  except Exception as e:
344
  logger.error(f"{CustomException(e)}:: {storename}")
345
  raise CustomException(e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  except Exception as e:
344
  logger.error(f"{CustomException(e)}:: {storename}")
345
  raise CustomException(e)
346
+
347
+ def necklaceTryOnWithPoints(self, image: Image.Image, jewellery: Image.Image, storename: str,
348
+ left_point: tuple[int, int], right_point: tuple[int, int]) -> list[
349
+ Union[Image.Image, str]]:
350
+ try:
351
+ logger.info(f">>> NECKLACE TRY ON WITH POINTS STARTED :: {storename} <<<")
352
+
353
+ image = np.array(image.convert("RGB"))
354
+ # .resize((3000, 3000)))
355
+ copy_image = image.copy()
356
+ jewellery = np.array(jewellery.convert("RGBA"))
357
+
358
+ logger.info(f"NECKLACE TRY ON :: scaling the necklace image based on given points :: {storename}")
359
+
360
+ avg_x1 = left_point[0]
361
+ avg_x2 = right_point[0]
362
+ avg_y1 = left_point[1]
363
+ avg_y2 = right_point[1]
364
+
365
+ angle = math.ceil(self.detector.findAngle((avg_x2, avg_y2), (avg_x1, avg_y1), (avg_x2, avg_y1))[0])
366
+ if avg_y2 >= avg_y1:
367
+ angle *= -1
368
+
369
+ xdist = avg_x2 - avg_x1
370
+ origImgRatio = xdist / jewellery.shape[1]
371
+ ydist = jewellery.shape[0] * origImgRatio
372
+
373
+ logger.info(f"NECKLACE TRY ON :: adding offset based on the necklace shape :: {storename}")
374
+ image_gray = cv2.cvtColor(jewellery, cv2.COLOR_BGRA2GRAY)
375
+ offset = int(0.8 * xdist * (np.argmax(image_gray[0, :] != 255) / jewellery.shape[1]))
376
+
377
+ jewellery = cv2.resize(jewellery, (int(xdist), int(ydist)), interpolation=cv2.INTER_AREA)
378
+ jewellery = cvzone.rotateImage(jewellery, angle)
379
+ y_coordinate = avg_y1 - offset
380
+ available_space = copy_image.shape[0] - y_coordinate
381
+ extra = jewellery.shape[0] - available_space
382
+
383
+ headerText = "To see more of the necklace, please step back slightly." if extra > 0 else "success"
384
+
385
+ logger.info(f"NECKLACE TRY ON :: generating output with given points :: {storename}")
386
+ result = cvzone.overlayPNG(copy_image, jewellery, (avg_x1, y_coordinate))
387
+ image = Image.fromarray(result.astype(np.uint8))
388
+
389
+ if storename not in self.logo_cache:
390
+ self.logo_cache[storename] = Image.open(
391
+ returnBytesData(url=self.necklaceTryOnConfig.logoURL.format(storename)))
392
+ result = addWatermark(background=image, logo=self.logo_cache[storename])
393
+
394
+ # Create binary mask
395
+ blackedNecklace = np.zeros_like(copy_image)
396
+ cvzone.overlayPNG(blackedNecklace, jewellery, (avg_x1, y_coordinate))
397
+ binaryMask = cv2.cvtColor(blackedNecklace.astype(np.uint8), cv2.COLOR_BGR2GRAY)
398
+ binaryMask = (binaryMask > 5).astype(np.uint8) * 255
399
+ mask = Image.fromarray(binaryMask).convert("RGB")
400
+
401
+ gc.collect()
402
+ return [result, headerText, mask]
403
+
404
+ except Exception as e:
405
+ logger.error(f"{CustomException(e)}:: {storename}")
406
+ raise CustomException(e)
src/pipelines/completePipeline.py CHANGED
@@ -20,3 +20,11 @@ class Pipeline:
20
  async def canvasPoint(self, image: Image.Image, jewellery: Image.Image, storename: str) -> dict:
21
  points = self.necklaceTryOnObj.canvasPoints(image=image, jewellery=jewellery, storename=storename)
22
  return points
 
 
 
 
 
 
 
 
 
20
  async def canvasPoint(self, image: Image.Image, jewellery: Image.Image, storename: str) -> dict:
21
  points = self.necklaceTryOnObj.canvasPoints(image=image, jewellery=jewellery, storename=storename)
22
  return points
23
+
24
+ async def necklaceTryOnWithPoints_(self, image: Image.Image, jewellery: Image.Image, left_shoulder: tuple[int, int],
25
+ right_shoulder: tuple[int, int], storename: str) -> list[Union[Image.Image, str]]:
26
+ result, headerText, mask = self.necklaceTryOnObj.necklaceTryOnWithPoints(image=image, jewellery=jewellery,
27
+ left_point=left_shoulder,
28
+ right_point=right_shoulder,
29
+ storename=storename)
30
+ return [result, headerText, mask]