ishworrsubedii commited on
Commit
5e5e999
·
1 Parent(s): 96961ef

feat: add API endpoint for clothing generation without mask; implement functionality within pipeline

Browse files
app.py CHANGED
@@ -19,7 +19,7 @@ from pydantic import BaseModel
19
  import replicate
20
 
21
  pipeline = Pipeline()
22
- app = FastAPI(title="Magical Mirror Web Plugin")
23
 
24
  app.add_middleware(
25
  CORSMiddleware,
@@ -33,9 +33,56 @@ key: str = os.getenv("SUPABASE_KEY")
33
  supabase: Client = create_client(url, key)
34
 
35
 
36
- class ClothingTryOnEntity(BaseModel):
37
- image: str
38
- mask: str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
 
41
  @app.post("/clothingTryOn")
@@ -237,13 +284,6 @@ async def product_data(
237
  raise HTTPException(status_code=500, detail=f"Failed to fetch or process data: {e}")
238
 
239
 
240
- class NecklaceTryOnIDEntity(BaseModel):
241
- necklaceImageId: str
242
- necklaceCategory: str
243
- storename: str
244
- api_token: str
245
-
246
-
247
  async def parse_necklace_try_on_id(necklaceImageId: str = Form(...),
248
  necklaceCategory: str = Form(...),
249
  storename: str = Form(...),
@@ -281,8 +321,8 @@ async def necklace_try_on_id(necklace_try_on_id: NecklaceTryOnIDEntity = Depends
281
 
282
  return JSONResponse(content=error_message, status_code=404)
283
 
284
- result, headetText, mask = await pipeline.necklaceTryOn(image=image, jewellery=jewellery,
285
- storename=necklace_try_on_id.storename)
286
 
287
  inMemFile = BytesIO()
288
  inMemFileMask = BytesIO()
 
19
  import replicate
20
 
21
  pipeline = Pipeline()
22
+ app = FastAPI(title="Magical Mirror Web Plugin", description="API for Magical Mirror Application ", version="1.0")
23
 
24
  app.add_middleware(
25
  CORSMiddleware,
 
33
  supabase: Client = create_client(url, key)
34
 
35
 
36
+ class NecklaceTryOnIDEntity(BaseModel):
37
+ necklaceImageId: str
38
+ necklaceCategory: str
39
+ storename: str
40
+ api_token: str
41
+
42
+
43
+ @app.post("/clothingTryOnV2")
44
+ async def clothing_try_on_v2(image: UploadFile = File(...), clothing_type: str = Form(...)):
45
+ image_bytes = await image.read()
46
+ image = Image.open(BytesIO(image_bytes)).convert("RGB")
47
+
48
+ mask = await pipeline.shoulderPointMaskGeneration_(image=image)
49
+
50
+ mask_img_base_64, act_img_base_64 = BytesIO(), BytesIO()
51
+ mask.save(mask_img_base_64, format="WEBP")
52
+ image.save(act_img_base_64, format="WEBP")
53
+ mask_bytes_ = base64.b64encode(mask_img_base_64.getvalue()).decode("utf-8")
54
+ image_bytes_ = base64.b64encode(act_img_base_64.getvalue()).decode("utf-8")
55
+
56
+ mask_data_uri = f"data:image/webp;base64,{mask_bytes_}"
57
+ image_data_uri = f"data:image/webp;base64,{image_bytes_}"
58
+
59
+ input = {
60
+ "mask": mask_data_uri,
61
+ "image": image_data_uri,
62
+ "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",
63
+ "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",
64
+ "num_inference_steps": 25
65
+ }
66
+
67
+ output = replicate.run(
68
+ "stability-ai/stable-diffusion-inpainting:95b7223104132402a9ae91cc677285bc5eb997834bd2349fa486f53910fd68b3",
69
+ input=input
70
+ )
71
+ image_url = output[0]
72
+
73
+ response = requests.get(image_url)
74
+ result = Image.open(BytesIO(response.content)).resize(image.size)
75
+
76
+ in_mem_file = BytesIO()
77
+ result.save(in_mem_file, format="WEBP", quality=85)
78
+ base_64_output = base64.b64encode(in_mem_file.getvalue()).decode('utf-8')
79
+
80
+ response = {
81
+ "output": f"data:image/WEBP;base64,{base_64_output}",
82
+ 'code': 200
83
+ }
84
+
85
+ return JSONResponse(content=response, status_code=200)
86
 
87
 
88
  @app.post("/clothingTryOn")
 
284
  raise HTTPException(status_code=500, detail=f"Failed to fetch or process data: {e}")
285
 
286
 
 
 
 
 
 
 
 
287
  async def parse_necklace_try_on_id(necklaceImageId: str = Form(...),
288
  necklaceCategory: str = Form(...),
289
  storename: str = Form(...),
 
321
 
322
  return JSONResponse(content=error_message, status_code=404)
323
 
324
+ result, headetText, mask = await pipeline.necklaceTryOn_(image=image, jewellery=jewellery,
325
+ storename=necklace_try_on_id.storename)
326
 
327
  inMemFile = BytesIO()
328
  inMemFileMask = BytesIO()
logs/running_logs.log CHANGED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [2024-10-10 20:52:18,370: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
2
+ [2024-10-10 20:52:18,695: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
3
+ [2024-10-10 20:52:18,695: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
4
+ [2024-10-10 20:56:13,263: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
5
+ [2024-10-10 20:56:13,569: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
6
+ [2024-10-10 20:56:13,569: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
7
+ [2024-10-10 20:56:13,569: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
8
+ [2024-10-10 20:57:20,291: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
9
+ [2024-10-10 20:57:20,597: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
10
+ [2024-10-10 20:57:20,597: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
11
+ [2024-10-10 20:57:20,597: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
12
+ [2024-10-10 21:01:04,285: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
13
+ [2024-10-10 21:01:04,583: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
14
+ [2024-10-10 21:01:04,583: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
15
+ [2024-10-10 21:01:04,583: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
16
+ [2024-10-10 21:02:43,963: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
17
+ [2024-10-10 21:02:44,284: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
18
+ [2024-10-10 21:02:44,284: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
19
+ [2024-10-10 21:02:44,284: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
20
+ [2024-10-10 21:07:16,992: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
21
+ [2024-10-10 21:07:17,246: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
22
+ [2024-10-10 21:07:17,246: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
23
+ [2024-10-10 21:08:15,909: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
24
+ [2024-10-10 21:08:16,206: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
25
+ [2024-10-10 21:08:16,206: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
26
+ [2024-10-10 21:09:24,365: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: detecting pose and landmarks]
27
+ [2024-10-10 21:09:24,665: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: estimating neck points]
28
+ [2024-10-10 21:09:24,665: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
29
+ [2024-10-10 21:09:24,665: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: generating shoulder point mask]
30
+ [2024-10-10 21:09:24,671: INFO: necklaceTryOn: SHOULDER POINT MASK GENERATION :: mask generated successfully]
src/components/necklaceTryOn.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  from cvzone.FaceMeshModule import FaceMeshDetector
2
  from src.utils import addWatermark, returnBytesData
3
  from src.utils.exceptions import CustomException
@@ -251,3 +253,50 @@ class NecklaceTryOn:
251
  except Exception as e:
252
  logger.error(f"{CustomException(e)}:: {storename}")
253
  raise CustomException(e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+
3
  from cvzone.FaceMeshModule import FaceMeshDetector
4
  from src.utils import addWatermark, returnBytesData
5
  from src.utils.exceptions import CustomException
 
253
  except Exception as e:
254
  logger.error(f"{CustomException(e)}:: {storename}")
255
  raise CustomException(e)
256
+
257
+ def shoulderPointMaskGeneration(self, image: Image.Image) -> Image.Image:
258
+ image = np.array(image)
259
+ copy_image = image.copy()
260
+
261
+ logger.info(f"SHOULDER POINT MASK GENERATION :: detecting pose and landmarks")
262
+
263
+ image = self.detector.findPose(image)
264
+ lmList, _ = self.detector.findPosition(image, bboxWithHands=False, draw=False)
265
+
266
+ img, faces = self.meshDetector.findFaceMesh(image, draw=False)
267
+ leftLandmarkIndex = 172
268
+ rightLandmarkIndex = 397
269
+
270
+ leftLandmark, rightLandmark = faces[0][leftLandmarkIndex], faces[0][rightLandmarkIndex]
271
+ landmarksDistance = int(
272
+ ((leftLandmark[0] - rightLandmark[0]) ** 2 + (leftLandmark[1] - rightLandmark[1]) ** 2) ** 0.5)
273
+
274
+ logger.info(f"SHOULDER POINT MASK GENERATION :: estimating neck points")
275
+
276
+ avg_x1 = int(leftLandmark[0] - landmarksDistance * 0.12)
277
+ avg_x2 = int(rightLandmark[0] + landmarksDistance * 0.12)
278
+
279
+ avg_y1 = int(leftLandmark[1] + landmarksDistance * 0.5)
280
+ avg_y2 = int(rightLandmark[1] + landmarksDistance * 0.5)
281
+
282
+ offset = 50
283
+ avg_y1 -= offset
284
+ avg_y2 -= offset
285
+
286
+ logger.info(f"SHOULDER POINT MASK GENERATION :: generating shoulder point mask")
287
+
288
+ logger.info("SHOULDER POINT MASK GENERATION :: generating shoulder point mask")
289
+
290
+ mask = np.zeros_like(image[:, :, 0])
291
+
292
+ mask[avg_y1:, :] = 255
293
+
294
+ pts = np.array([[0, 0], [image.shape[1], 0], [avg_x2, avg_y2], [avg_x1, avg_y1]], np.int32)
295
+ pts = pts.reshape((-1, 1, 2))
296
+ cv2.fillPoly(mask, [pts], 0)
297
+
298
+ black_n_white_mask = np.zeros_like(image[:, :, 0])
299
+ black_n_white_mask[avg_y1:, :] = 255
300
+ logger.info("SHOULDER POINT MASK GENERATION :: mask generated successfully")
301
+
302
+ return Image.fromarray(black_n_white_mask.astype(np.uint8))
src/pipelines/completePipeline.py CHANGED
@@ -7,8 +7,12 @@ class Pipeline:
7
  def __init__(self) -> None:
8
  self.necklaceTryOnObj = NecklaceTryOn()
9
 
10
- async def necklaceTryOn(self, image: Image.Image, jewellery: Image.Image, storename: str) -> list[
11
  Union[Image.Image, str]]:
12
  result, headerText, mask = self.necklaceTryOnObj.necklaceTryOn(image=image, jewellery=jewellery,
13
  storename=storename)
14
  return [result, headerText, mask]
 
 
 
 
 
7
  def __init__(self) -> None:
8
  self.necklaceTryOnObj = NecklaceTryOn()
9
 
10
+ async def necklaceTryOn_(self, image: Image.Image, jewellery: Image.Image, storename: str) -> list[
11
  Union[Image.Image, str]]:
12
  result, headerText, mask = self.necklaceTryOnObj.necklaceTryOn(image=image, jewellery=jewellery,
13
  storename=storename)
14
  return [result, headerText, mask]
15
+
16
+ async def shoulderPointMaskGeneration_(self, image: Image.Image) -> Image.Image:
17
+ mask = self.necklaceTryOnObj.shoulderPointMaskGeneration(image=image)
18
+ return mask