bhatanerohan commited on
Commit
70fa0ce
·
verified ·
1 Parent(s): 0e13096

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -61
app.py CHANGED
@@ -6,6 +6,7 @@ MCP Server + Gradio UI for MCP Hackathon
6
  import os
7
  import io
8
  import json
 
9
  import tempfile
10
  import gradio as gr
11
  from google import genai
@@ -55,7 +56,7 @@ def generate_3d_model(prompt: str) -> str:
55
  prompt: Text description of the object to generate (e.g., "a red sports car", "a wooden chair")
56
 
57
  Returns:
58
- JSON string with paths to generated files
59
  """
60
  if not client:
61
  if not init_gemini():
@@ -78,7 +79,7 @@ def generate_3d_model(prompt: str) -> str:
78
  break
79
 
80
  if initial_image is None:
81
- return json.dumps({"error": "Image generation failed"})
82
 
83
  # STEP 2: Remove background
84
  edit_prompt = "Remove the background completely, make the background transparent. Preserve the object's shadow for realism."
@@ -100,7 +101,7 @@ def generate_3d_model(prompt: str) -> str:
100
  break
101
 
102
  if final_image is None:
103
- return json.dumps({"error": "Background removal failed"})
104
 
105
  # STEP 3: Create grayscale mask
106
  gray = final_image.convert("L")
@@ -108,59 +109,52 @@ def generate_3d_model(prompt: str) -> str:
108
  # STEP 4: Run SAM-3D
109
  ply_bytes, glb_bytes = run_sam3d(final_image, gray)
110
 
111
- # Save all outputs
112
- temp_dir = tempfile.mkdtemp()
113
-
114
- original_path = os.path.join(temp_dir, "original.png")
115
- nobg_path = os.path.join(temp_dir, "transparent.png")
116
- mask_path = os.path.join(temp_dir, "mask.png")
117
- ply_path = os.path.join(temp_dir, "model.ply")
118
-
119
- initial_image.save(original_path)
120
- final_image.save(nobg_path)
121
- gray.save(mask_path)
122
-
123
- with open(ply_path, 'wb') as f:
124
- f.write(ply_bytes)
125
-
126
- glb_path = None
127
- if glb_bytes:
128
- glb_path = os.path.join(temp_dir, "model.glb")
129
- with open(glb_path, 'wb') as f:
130
- f.write(glb_bytes)
131
 
132
  return json.dumps({
133
  "success": True,
134
  "prompt": prompt,
135
- "original_image": original_path,
136
- "transparent_image": nobg_path,
137
- "mask_image": mask_path,
138
- "ply_model": ply_path,
139
- "glb_model": glb_path,
140
- "message": f"Successfully generated 3D model for: {prompt}"
 
 
 
141
  })
142
 
143
  except Exception as e:
144
- return json.dumps({"error": str(e)})
145
-
 
 
146
 
147
- def edit_3d_model(edit_prompt: str, transparent_image_path: str) -> str:
148
  """
149
  Edit an existing 3D model by modifying its transparent image and regenerating.
150
 
151
  Args:
152
  edit_prompt: Description of the edit to apply (e.g., "remove the wings", "change color to blue")
153
- transparent_image_path: Path to the transparent PNG image from a previous generation
154
 
155
  Returns:
156
- JSON string with paths to the new edited files
157
  """
158
  if not client:
159
  if not init_gemini():
160
  return json.dumps({"error": "GEMINI_API_KEY not configured"})
161
 
162
  try:
163
- current_image = Image.open(transparent_image_path)
 
 
164
 
165
  image_part = types.Part.from_bytes(
166
  data=image_to_bytes(current_image),
@@ -182,42 +176,35 @@ def edit_3d_model(edit_prompt: str, transparent_image_path: str) -> str:
182
  break
183
 
184
  if edited_image is None:
185
- return json.dumps({"error": "Edit failed"})
186
 
187
  gray = edited_image.convert("L")
188
  ply_bytes, glb_bytes = run_sam3d(edited_image, gray)
189
 
190
- temp_dir = tempfile.mkdtemp()
191
-
192
- nobg_path = os.path.join(temp_dir, "edited.png")
193
- mask_path = os.path.join(temp_dir, "mask.png")
194
- ply_path = os.path.join(temp_dir, "model.ply")
195
-
196
- edited_image.save(nobg_path)
197
- gray.save(mask_path)
198
-
199
- with open(ply_path, 'wb') as f:
200
- f.write(ply_bytes)
201
-
202
- glb_path = None
203
- if glb_bytes:
204
- glb_path = os.path.join(temp_dir, "model.glb")
205
- with open(glb_path, 'wb') as f:
206
- f.write(glb_bytes)
207
 
208
  return json.dumps({
209
  "success": True,
210
  "edit_prompt": edit_prompt,
211
- "transparent_image": nobg_path,
212
- "mask_image": mask_path,
213
- "ply_model": ply_path,
214
- "glb_model": glb_path,
215
- "message": f"Successfully applied edit: {edit_prompt}"
 
 
 
216
  })
217
 
218
  except Exception as e:
219
- return json.dumps({"error": str(e)})
220
-
 
 
221
 
222
  # ============================================================
223
  # GRADIO UI FUNCTIONS
@@ -422,7 +409,7 @@ edit_tool = gr.Interface(
422
  fn=edit_3d_model,
423
  inputs=[
424
  gr.Textbox(label="Edit Prompt", placeholder="Remove the wings"),
425
- gr.Textbox(label="Transparent Image Path", placeholder="/path/to/transparent.png")
426
  ],
427
  outputs=gr.Textbox(label="Result (JSON)"),
428
  api_name="edit_3d",
 
6
  import os
7
  import io
8
  import json
9
+ import base64
10
  import tempfile
11
  import gradio as gr
12
  from google import genai
 
56
  prompt: Text description of the object to generate (e.g., "a red sports car", "a wooden chair")
57
 
58
  Returns:
59
+ JSON string with base64-encoded files
60
  """
61
  if not client:
62
  if not init_gemini():
 
79
  break
80
 
81
  if initial_image is None:
82
+ return json.dumps({"error": "Image generation failed - no image in response"})
83
 
84
  # STEP 2: Remove background
85
  edit_prompt = "Remove the background completely, make the background transparent. Preserve the object's shadow for realism."
 
101
  break
102
 
103
  if final_image is None:
104
+ return json.dumps({"error": "Background removal failed - no image in response"})
105
 
106
  # STEP 3: Create grayscale mask
107
  gray = final_image.convert("L")
 
109
  # STEP 4: Run SAM-3D
110
  ply_bytes, glb_bytes = run_sam3d(final_image, gray)
111
 
112
+ # STEP 5: Encode outputs as base64 (NO FILE PATHS!)
113
+ original_b64 = base64.b64encode(image_to_bytes(initial_image)).decode()
114
+ transparent_b64 = base64.b64encode(image_to_bytes(final_image)).decode()
115
+ mask_b64 = base64.b64encode(image_to_bytes(gray)).decode()
116
+ ply_b64 = base64.b64encode(ply_bytes).decode()
117
+ glb_b64 = base64.b64encode(glb_bytes).decode() if glb_bytes else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  return json.dumps({
120
  "success": True,
121
  "prompt": prompt,
122
+ "message": f"✅ Successfully generated 3D model for: {prompt}",
123
+ "files": {
124
+ "original_image_base64": original_b64,
125
+ "transparent_image_base64": transparent_b64,
126
+ "mask_image_base64": mask_b64,
127
+ "ply_model_base64": ply_b64,
128
+ "glb_model_base64": glb_b64
129
+ },
130
+ "instructions": "Files are base64-encoded. To save: decode base64 and write to disk."
131
  })
132
 
133
  except Exception as e:
134
+ return json.dumps({
135
+ "error": str(e),
136
+ "error_type": type(e).__name__
137
+ })
138
 
139
+ def edit_3d_model(edit_prompt: str, transparent_image_base64: str) -> str:
140
  """
141
  Edit an existing 3D model by modifying its transparent image and regenerating.
142
 
143
  Args:
144
  edit_prompt: Description of the edit to apply (e.g., "remove the wings", "change color to blue")
145
+ transparent_image_base64: Base64-encoded transparent PNG image from a previous generation
146
 
147
  Returns:
148
+ JSON string with base64-encoded edited files
149
  """
150
  if not client:
151
  if not init_gemini():
152
  return json.dumps({"error": "GEMINI_API_KEY not configured"})
153
 
154
  try:
155
+ # Decode base64 image (instead of reading file path)
156
+ image_bytes = base64.b64decode(transparent_image_base64)
157
+ current_image = Image.open(io.BytesIO(image_bytes))
158
 
159
  image_part = types.Part.from_bytes(
160
  data=image_to_bytes(current_image),
 
176
  break
177
 
178
  if edited_image is None:
179
+ return json.dumps({"error": "Edit failed - no image in response"})
180
 
181
  gray = edited_image.convert("L")
182
  ply_bytes, glb_bytes = run_sam3d(edited_image, gray)
183
 
184
+ # Encode outputs as base64 (NO FILE PATHS!)
185
+ transparent_b64 = base64.b64encode(image_to_bytes(edited_image)).decode()
186
+ mask_b64 = base64.b64encode(image_to_bytes(gray)).decode()
187
+ ply_b64 = base64.b64encode(ply_bytes).decode()
188
+ glb_b64 = base64.b64encode(glb_bytes).decode() if glb_bytes else None
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  return json.dumps({
191
  "success": True,
192
  "edit_prompt": edit_prompt,
193
+ "message": f"✅ Successfully applied edit: {edit_prompt}",
194
+ "files": {
195
+ "transparent_image_base64": transparent_b64,
196
+ "mask_image_base64": mask_b64,
197
+ "ply_model_base64": ply_b64,
198
+ "glb_model_base64": glb_b64
199
+ },
200
+ "instructions": "Files are base64-encoded. To save: decode base64 and write to disk."
201
  })
202
 
203
  except Exception as e:
204
+ return json.dumps({
205
+ "error": str(e),
206
+ "error_type": type(e).__name__
207
+ })
208
 
209
  # ============================================================
210
  # GRADIO UI FUNCTIONS
 
409
  fn=edit_3d_model,
410
  inputs=[
411
  gr.Textbox(label="Edit Prompt", placeholder="Remove the wings"),
412
+ gr.Textbox(label="Transparent Image (base64)", placeholder="Paste base64-encoded PNG from previous generation")
413
  ],
414
  outputs=gr.Textbox(label="Result (JSON)"),
415
  api_name="edit_3d",