Johdw commited on
Commit
fb97fcf
·
verified ·
1 Parent(s): 908c448

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +64 -52
main.py CHANGED
@@ -32,56 +32,62 @@ def load_model():
32
  AI_MODEL["predictor"] = SamPredictor(sam)
33
  print("✅ High-Quality AI Model is now loaded.")
34
 
35
- # === CORE PROCESSING FUNCTIONS (DIRECTLY FROM YOUR WORKING COLAB) ===
36
 
37
  def generate_ultimate_mask(image: Image.Image):
38
- print( "Generating Mask image . . . ." );
39
- """Generates the high-quality mask FOR THE SUIT ONLY, ignoring the shirt and pin."""
40
  sam_predictor = AI_MODEL["predictor"]; np = AI_MODEL["numpy"]
41
  image_np = np.array(image.convert('RGB')); sam_predictor.set_image(image_np); h, w, _ = image_np.shape
42
  input_points = np.array([[w*0.30,h*0.50],[w*0.70,h*0.50],[w*0.50,h*0.40],[w*0.65,h*0.32]])
43
  input_labels = np.array([1, 1, 0, 0])
44
  masks, _, _ = sam_predictor.predict(point_coords=input_points, point_labels=input_labels, multimask_output=False)
 
45
  return Image.fromarray(masks[0]).convert('L').filter(ImageFilter.GaussianBlur(2))
46
 
47
- def create_the_final_result(fabric: Image.Image, person: Image.Image, mask: Image.Image):
48
- """THE FINAL, GUARANTEED, PIXEL-PERFECT COMPOSITING FUNCTION."""
49
- # 1. Tile the fabric (Base Layer with perfect color).
50
- print( "# 1. Tile the fabric (Base Layer with perfect color)." );
51
- base_size=int(person.width/4); sw=max(1,int(base_size*0.65)); fw,fh=fabric.size
52
- sh=max(1,int(fh*(sw/fw))) if fw>0 else 0; s=fabric.resize((sw,sh),Image.Resampling.LANCZOS)
53
- tiled_fabric=Image.new('RGB',person.size)
54
- for i in range(0,person.width,sw):
55
- for j in range(0,person.height,sh): tiled_fabric.paste(s,(i,j))
56
-
57
- # 2. Create the Form & Shading Layer.
58
- print( " # 2. Create the Form & Shading Layer." );
59
- form_map=ImageOps.autocontrast(ImageOps.grayscale(person),cutoff=2).convert('RGB')
60
- shaped_fabric=ImageChops.soft_light(tiled_fabric,form_map)
61
 
62
- # 3. Create the Detail & Contrast Layer.
63
- print( " # 3. Create the Detail & Contrast Layer. " );
64
- grayscale_person_details=ImageOps.grayscale(person)
65
- shadow_map=ImageOps.autocontrast(grayscale_person_details,cutoff=(5,95)).convert('RGB')
66
- highlight_map=ImageOps.invert(ImageOps.autocontrast(grayscale_person_details,cutoff=(95,99))).convert('RGB')
67
 
68
- # 4. Apply the Detail Layers with Opacity.
69
- print( " # 4. Apply the Detail Layers with Opacity." );
70
- shadowed_layer=ImageChops.multiply(shaped_fabric,shadow_map)
71
- final_shadows=Image.blend(shaped_fabric,shadowed_layer,alpha=0.25)
72
- highlighted_layer=ImageChops.screen(final_shadows,highlight_map)
73
- final_lit=Image.blend(final_shadows,highlighted_layer,alpha=0.1)
 
 
 
 
 
 
 
 
 
74
 
75
- # 5. Composite the final result.
76
- print( " # 5. Composite the final result." );
77
- final_image=person.copy(); final_image.paste(final_lit,(0,0),mask=mask)
78
- return final_image
 
79
 
80
  def load_image_from_base64(s: str, m: str = 'RGB'):
81
- print( "Load image from base64" );
82
- if "," not in s: return None
83
- try: return Image.open(io.BytesIO(base64.b64decode(s.split(",")[1]))).convert(m)
84
- except: return None
 
 
 
 
85
 
86
  # === API ENDPOINTS (CORRECT AND GUARANTEED) ===
87
 
@@ -95,35 +101,41 @@ class ApiInput(BaseModel):
95
 
96
  @app.post("/generate")
97
  async def api_generate(request: Request, inputs: ApiInput):
98
- print( "---------------------------------Starting---------------------------------" );
99
- load_model()
 
100
  API_KEY = os.environ.get("API_KEY")
101
- if request.headers.get("x-api-key") != API_KEY: raise HTTPException(status_code=401, detail="Unauthorized")
 
 
102
 
 
103
  person = load_image_from_base64(inputs.person_base64)
104
  fabric = load_image_from_base64(inputs.fabric_base64)
105
- if person is None or fabric is None: raise HTTPException(status_code=400, detail="Could not decode base64.")
 
106
 
107
- #person_resized = person.resize((1024, 1024), Image.Resampling.LANCZOS)
108
- person_resized = person
109
 
110
  if inputs.mask_base64:
 
111
  mask = load_image_from_base64(inputs.mask_base64, mode='L')
112
  if mask is None: raise HTTPException(status_code=400, detail="Could not decode mask base64.")
113
- # mask = mask.resize((1024, 1024), Image.Resampling.LANCZOS)
114
  else:
 
115
  mask = generate_ultimate_mask(person_resized)
116
 
117
- final_result = create_the_final_result(fabric, person_resized, mask)
118
 
119
  def to_base64(img):
120
- # Resize for a consistent output size
121
- # img = img.resize((512, 512), Image.Resampling.LANCZOS)
122
  buf = io.BytesIO(); img.save(buf, format="PNG"); return f"data:image/png;base64,{base64.b64encode(buf.getvalue()).decode('utf-8')}"
123
-
124
- response_data = {
125
- "result_image": to_base64(final_result),
126
- "mask_image": to_base64(mask)
127
- }
128
- print( "---------------------------------Completed---------------------------------" );
129
  return response_data
 
32
  AI_MODEL["predictor"] = SamPredictor(sam)
33
  print("✅ High-Quality AI Model is now loaded.")
34
 
35
+ # === CORE PROCESSING FUNCTIONS (DIRECTLY FROM YOUR PERFECTED COLAB) ===
36
 
37
  def generate_ultimate_mask(image: Image.Image):
38
+ """Generates the high-quality mask FOR THE SUIT ONLY."""
39
+ print(" - DEBUG: Entering generate_ultimate_mask function...")
40
  sam_predictor = AI_MODEL["predictor"]; np = AI_MODEL["numpy"]
41
  image_np = np.array(image.convert('RGB')); sam_predictor.set_image(image_np); h, w, _ = image_np.shape
42
  input_points = np.array([[w*0.30,h*0.50],[w*0.70,h*0.50],[w*0.50,h*0.40],[w*0.65,h*0.32]])
43
  input_labels = np.array([1, 1, 0, 0])
44
  masks, _, _ = sam_predictor.predict(point_coords=input_points, point_labels=input_labels, multimask_output=False)
45
+ print(" - DEBUG: Mask generation complete.")
46
  return Image.fromarray(masks[0]).convert('L').filter(ImageFilter.GaussianBlur(2))
47
 
48
+ def create_pixel_perfect_results(fabric: Image.Image, person: Image.Image, mask: Image.Image):
49
+ """The definitive, multi-layer professional compositing workflow."""
50
+ print(" - DEBUG: Entering create_pixel_perfect_results function...")
51
+ results = {}
52
+
53
+ print(" - DEBUG: Creating shadow and highlight maps...")
54
+ grayscale_person = ImageOps.grayscale(person)
55
+ shadow_map = ImageOps.autocontrast(grayscale_person, cutoff=(10, 99)).convert('RGB')
56
+ highlight_map = ImageOps.invert(ImageOps.autocontrast(grayscale_person, cutoff=(90, 99))).convert('RGB')
 
 
 
 
 
57
 
58
+ scales = {"classic": 0.75, "fine": 0.4, "bold": 1.2}
 
 
 
 
59
 
60
+ for style, sf in scales.items():
61
+ print(f" - DEBUG: Generating '{style}' image...")
62
+ base_size = int(person.width / 4); sw = max(1, int(base_size * sf)); fw, fh = fabric.size
63
+ sh = max(1, int(fh * (sw / fw))) if fw > 0 else 0
64
+ s = fabric.resize((sw, sh), Image.Resampling.LANCZOS); tiled_fabric = Image.new('RGB', person.size)
65
+ for i in range(0, person.width, sw):
66
+ for j in range(0, person.height, sh): tiled_fabric.paste(s, (i, j))
67
+
68
+ shadowed_layer = ImageChops.multiply(tiled_fabric, shadow_map)
69
+ shadowed_fabric = Image.blend(tiled_fabric, shadowed_layer, alpha=0.65)
70
+ highlighted_layer = ImageChops.screen(shadowed_fabric, highlight_map)
71
+ lit_fabric = Image.blend(shadowed_fabric, highlighted_layer, alpha=0.35)
72
+
73
+ final_image = person.copy(); final_image.paste(lit_fabric, (0, 0), mask=mask)
74
+ results[f"{style}_image"] = final_image
75
 
76
+ print(" - DEBUG: Generating 'realistic' (creative) image...")
77
+ light_map_rgb = ImageOps.autocontrast(ImageOps.grayscale(person).convert('RGB'), cutoff=2)
78
+ results["realistic_image"] = ImageChops.soft_light(results["classic_image"], light_map_rgb)
79
+ print(" - DEBUG: All image generation complete.")
80
+ return results
81
 
82
  def load_image_from_base64(s: str, m: str = 'RGB'):
83
+ """Decodes Base64 to a PIL Image. Fast and reliable."""
84
+ if not s or "," not in s: return None
85
+ try:
86
+ img_data = base64.b64decode(s.split(",")[1])
87
+ return Image.open(io.BytesIO(img_data)).convert(m)
88
+ except Exception as e:
89
+ print(f" - ❌ ERROR: Failed to decode base64 string. Error: {e}")
90
+ return None
91
 
92
  # === API ENDPOINTS (CORRECT AND GUARANTEED) ===
93
 
 
101
 
102
  @app.post("/generate")
103
  async def api_generate(request: Request, inputs: ApiInput):
104
+ print("\n--- Received API request for /generate ---")
105
+ load_model() # This is the magic. All heavy lifting happens here, only once.
106
+
107
  API_KEY = os.environ.get("API_KEY")
108
+ if request.headers.get("x-api-key") != API_KEY:
109
+ print(" - ❌ ERROR: Unauthorized. Invalid API Key provided.")
110
+ raise HTTPException(status_code=401, detail="Unauthorized")
111
 
112
+ print(" - DEBUG: Loading images from Base64...")
113
  person = load_image_from_base64(inputs.person_base64)
114
  fabric = load_image_from_base64(inputs.fabric_base64)
115
+ if person is None or fabric is None:
116
+ raise HTTPException(status_code=400, detail="Could not decode person or fabric base64 string.")
117
 
118
+ print(" - DEBUG: Resizing person image...")
119
+ person_resized = person.resize((1024, 1024), Image.Resampling.LANCZOS)
120
 
121
  if inputs.mask_base64:
122
+ print(" - DEBUG: Loading provided mask from Base64...")
123
  mask = load_image_from_base64(inputs.mask_base64, mode='L')
124
  if mask is None: raise HTTPException(status_code=400, detail="Could not decode mask base64.")
125
+ mask = mask.resize((1024, 1024), Image.Resampling.LANCZOS)
126
  else:
127
+ print(" - DEBUG: No mask provided, generating one automatically...")
128
  mask = generate_ultimate_mask(person_resized)
129
 
130
+ result_images = create_pixel_perfect_results(fabric, person_resized, mask)
131
 
132
  def to_base64(img):
133
+ img = img.resize((512, 512), Image.Resampling.LANCZOS)
 
134
  buf = io.BytesIO(); img.save(buf, format="PNG"); return f"data:image/png;base64,{base64.b64encode(buf.getvalue()).decode('utf-8')}"
135
+
136
+ print(" - DEBUG: Encoding final images to Base64...")
137
+ response_data = {key: to_base64(img) for key, img in result_images.items()}
138
+ response_data["mask_image"] = to_base64(mask)
139
+
140
+ print("--- ✅ Request successful. Sending response. ---")
141
  return response_data