Spaces:
Running on Zero
Running on Zero
Claude Sonnet 4.5 Claude Fable 5 commited on
feat: Ocean theme, guide tab, hide lambda from MCP API
Browse files- gr.themes.Ocean() + larger Model3D viewport
- Guide tab: usage steps, prompt tips, correct MCP setup (streamable HTTP
at /gradio_api/mcp/ β the old footer block showed the outdated /sse URL)
- show_api=False on the download-sync lambda so it no longer appears as an
MCP tool (sam3d_objects_mcp__lambda_)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -219,12 +219,10 @@ def reconstruct_objects(image: np.ndarray, prompt: str = "object", progress=gr.P
|
|
| 219 |
return None, None, f"β Error:\n{tb[-1500:]}"
|
| 220 |
|
| 221 |
|
| 222 |
-
with gr.Blocks(title="SAM 3D Objects MCP") as demo:
|
| 223 |
gr.Markdown("""
|
| 224 |
-
# π¦ SAM 3D Objects
|
| 225 |
-
**Image (+ text prompt) β 3D Object (GLB)**
|
| 226 |
-
|
| 227 |
-
SAM3 segments the object you describe, SAM 3D Objects reconstructs it in 3D.
|
| 228 |
""")
|
| 229 |
|
| 230 |
with gr.Tab("Reconstruct"):
|
|
@@ -239,31 +237,66 @@ with gr.Blocks(title="SAM 3D Objects MCP") as demo:
|
|
| 239 |
preview = gr.Image(label="Segmented Object", type="numpy", interactive=False)
|
| 240 |
status = gr.Textbox(label="Status")
|
| 241 |
with gr.Row():
|
| 242 |
-
output_model = gr.Model3D(label="3D Preview")
|
| 243 |
-
|
|
|
|
| 244 |
btn.click(reconstruct_objects, inputs=[input_image, input_prompt],
|
| 245 |
outputs=[output_model, preview, status])
|
| 246 |
-
output_model.change(lambda x: x, inputs=[output_model], outputs=[output_file]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
|
| 248 |
with gr.Tab("Diagnose"):
|
| 249 |
diag_btn = gr.Button("Diagnose GPU & Models")
|
| 250 |
diag_out = gr.Textbox(lines=8, label="Diagnostics")
|
| 251 |
diag_btn.click(diagnose, outputs=[diag_out])
|
| 252 |
|
| 253 |
-
gr.Markdown("""
|
| 254 |
-
---
|
| 255 |
-
### MCP Server
|
| 256 |
-
```json
|
| 257 |
-
{
|
| 258 |
-
"mcpServers": {
|
| 259 |
-
"sam3d-objects": {
|
| 260 |
-
"url": "https://dev-bjoern-sam3d-objects-mcp.hf.space/gradio_api/mcp/sse"
|
| 261 |
-
}
|
| 262 |
-
}
|
| 263 |
-
}
|
| 264 |
-
```
|
| 265 |
-
""")
|
| 266 |
-
|
| 267 |
|
| 268 |
if __name__ == "__main__":
|
| 269 |
demo.launch(mcp_server=True)
|
|
|
|
| 219 |
return None, None, f"β Error:\n{tb[-1500:]}"
|
| 220 |
|
| 221 |
|
| 222 |
+
with gr.Blocks(title="SAM 3D Objects MCP", theme=gr.themes.Ocean()) as demo:
|
| 223 |
gr.Markdown("""
|
| 224 |
+
# π¦ SAM 3D Objects
|
| 225 |
+
**Image (+ text prompt) β 3D Object (GLB)** Β· powered by Meta's SAM3 + SAM 3D Objects Β· usable as MCP server
|
|
|
|
|
|
|
| 226 |
""")
|
| 227 |
|
| 228 |
with gr.Tab("Reconstruct"):
|
|
|
|
| 237 |
preview = gr.Image(label="Segmented Object", type="numpy", interactive=False)
|
| 238 |
status = gr.Textbox(label="Status")
|
| 239 |
with gr.Row():
|
| 240 |
+
output_model = gr.Model3D(label="3D Preview", height=420)
|
| 241 |
+
with gr.Column():
|
| 242 |
+
output_file = gr.File(label="Download")
|
| 243 |
btn.click(reconstruct_objects, inputs=[input_image, input_prompt],
|
| 244 |
outputs=[output_model, preview, status])
|
| 245 |
+
output_model.change(lambda x: x, inputs=[output_model], outputs=[output_file],
|
| 246 |
+
show_api=False)
|
| 247 |
+
|
| 248 |
+
with gr.Tab("Guide"):
|
| 249 |
+
gr.Markdown("""
|
| 250 |
+
## How it works
|
| 251 |
+
|
| 252 |
+
1. **Upload an image** β photos and renders both work; one clearly visible object gives the best result.
|
| 253 |
+
2. **Describe what to reconstruct** β a short noun phrase like `robot`, `the red chair`, `laptop`.
|
| 254 |
+
The default `object` picks the most prominent thing in the image.
|
| 255 |
+
3. **Segment & Reconstruct** β SAM3 finds the best-matching instance (green preview),
|
| 256 |
+
SAM 3D Objects rebuilds it as a vertex-colored GLB mesh you can preview and download.
|
| 257 |
+
|
| 258 |
+
The first request after a restart loads both models and takes ~2 minutes extra; after that
|
| 259 |
+
a reconstruction takes roughly 1β2 minutes.
|
| 260 |
+
|
| 261 |
+
### Prompt tips
|
| 262 |
+
- Short English noun phrases work best: `sofa`, `yellow school bus`, `coffee mug`
|
| 263 |
+
- If several matching objects exist, the highest-confidence one is used
|
| 264 |
+
- Getting the wrong object? Make the prompt more specific (`the left chair` won't help β
|
| 265 |
+
SAM3 matches concepts, not positions β but `wooden chair` will)
|
| 266 |
+
|
| 267 |
+
## Use as MCP server
|
| 268 |
+
|
| 269 |
+
Add to your MCP client (Claude Code, Claude Desktop, Cursor, ...):
|
| 270 |
+
|
| 271 |
+
```json
|
| 272 |
+
{
|
| 273 |
+
"mcpServers": {
|
| 274 |
+
"sam3d-objects": {
|
| 275 |
+
"url": "https://dev-bjoern-sam3d-objects-mcp.hf.space/gradio_api/mcp/"
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
Or with the Claude Code CLI:
|
| 282 |
+
|
| 283 |
+
```bash
|
| 284 |
+
claude mcp add --transport http sam3d-objects https://dev-bjoern-sam3d-objects-mcp.hf.space/gradio_api/mcp/
|
| 285 |
+
```
|
| 286 |
+
|
| 287 |
+
For stdio-only clients (e.g. Claude Desktop) use
|
| 288 |
+
`npx mcp-remote https://dev-bjoern-sam3d-objects-mcp.hf.space/gradio_api/mcp/ --transport streamable-http`.
|
| 289 |
+
|
| 290 |
+
The `reconstruct_objects` tool takes an image (URL or uploaded file) and a text
|
| 291 |
+
prompt and returns the GLB, the segmentation preview and a status line.
|
| 292 |
+
Full API details: the **"Use via API or MCP"** link in the page footer.
|
| 293 |
+
""")
|
| 294 |
|
| 295 |
with gr.Tab("Diagnose"):
|
| 296 |
diag_btn = gr.Button("Diagnose GPU & Models")
|
| 297 |
diag_out = gr.Textbox(lines=8, label="Diagnostics")
|
| 298 |
diag_btn.click(diagnose, outputs=[diag_out])
|
| 299 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
|
| 301 |
if __name__ == "__main__":
|
| 302 |
demo.launch(mcp_server=True)
|