Spaces:
Running
Running

Enhance mask handling in image processing: resize and validate dimensions, update demo link, and correct copyright year in footer
311bfbf
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Magic Eraser API Documentation</title> | |
<style> | |
body { | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | |
line-height: 1.6; | |
color: #333; | |
max-width: 1100px; | |
margin: 0 auto; | |
padding: 20px; | |
} | |
header { | |
border-bottom: 1px solid #eee; | |
padding-bottom: 20px; | |
margin-bottom: 30px; | |
} | |
h1 { | |
color: #2c3e50; | |
} | |
h2 { | |
color: #3498db; | |
margin-top: 40px; | |
} | |
h3 { | |
color: #2980b9; | |
} | |
pre { | |
background-color: #f5f7f9; | |
border-radius: 5px; | |
padding: 15px; | |
overflow-x: auto; | |
} | |
code { | |
font-family: 'Courier New', Courier, monospace; | |
} | |
.endpoint { | |
background-color: #f8f9fa; | |
border-left: 4px solid #3498db; | |
padding: 15px; | |
margin-bottom: 20px; | |
} | |
.method { | |
display: inline-block; | |
padding: 3px 6px; | |
border-radius: 4px; | |
color: white; | |
font-size: 14px; | |
margin-right: 10px; | |
} | |
.get { | |
background-color: #3498db; | |
} | |
.post { | |
background-color: #2ecc71; | |
} | |
table { | |
border-collapse: collapse; | |
width: 100%; | |
} | |
th, td { | |
text-align: left; | |
padding: 12px; | |
border-bottom: 1px solid #ddd; | |
} | |
th { | |
background-color: #f2f2f2; | |
} | |
.container { | |
margin-top: 20px; | |
} | |
.demo-section { | |
margin-top: 40px; | |
padding: 20px; | |
background-color: #f9f9f9; | |
border-radius: 8px; | |
} | |
.btn { | |
display: inline-block; | |
padding: 10px 15px; | |
background-color: #3498db; | |
color: white; | |
text-decoration: none; | |
border-radius: 4px; | |
border: none; | |
cursor: pointer; | |
} | |
.btn:hover { | |
background-color: #2980b9; | |
} | |
</style> | |
</head> | |
<body> | |
<header> | |
<h1>📷 Magic Eraser API</h1> | |
<p>An AI-powered REST API for removing unwanted objects from images and performing content-aware resizing.</p> | |
<p>Check out the InnoAI Space for the streamline demo frontend: <a href="https://huggingface.co/spaces/innoai/Magic-Eraser-Pub" target="_blank">Magic Eraser Demo</a></p> | |
</header> | |
<section> | |
<h2>Features</h2> | |
<ul> | |
<li><strong>Object Removal</strong>: Remove unwanted objects from images with advanced AI inpainting</li> | |
<li><strong>Seam Carving</strong>: Content-aware image resizing and object removal</li> | |
<li><strong>Simple Integration</strong>: Easy-to-use REST API endpoints</li> | |
</ul> | |
</section> | |
<section> | |
<h2>API Endpoints</h2> | |
<div class="endpoint"> | |
<h3><span class="method get">GET</span> /</h3> | |
<p>Health check endpoint. Returns a status message if the API is running.</p> | |
<h4>Response</h4> | |
<pre><code>{ | |
"status": "API is running" | |
}</code></pre> | |
</div> | |
<div class="endpoint"> | |
<h3><span class="method post">POST</span> /api/inpaint</h3> | |
<p>Removes objects from images and fills in the background using AI.</p> | |
<h4>Request Body</h4> | |
<pre><code>{ | |
"image": "data:image/png;base64,<base64-encoded-image>", | |
"mask": "data:image/png;base64,<base64-encoded-mask>" | |
}</code></pre> | |
<table> | |
<tr> | |
<th>Parameter</th> | |
<th>Type</th> | |
<th>Description</th> | |
</tr> | |
<tr> | |
<td>image</td> | |
<td>string</td> | |
<td>Base64-encoded image with data URL prefix</td> | |
</tr> | |
<tr> | |
<td>mask</td> | |
<td>string</td> | |
<td>Base64-encoded mask where transparent areas (alpha=0) indicate what to remove</td> | |
</tr> | |
</table> | |
<h4>Response</h4> | |
<pre><code>{ | |
"result": "data:image/png;base64,<base64-encoded-result>" | |
}</code></pre> | |
</div> | |
<div class="endpoint"> | |
<h3><span class="method post">POST</span> /api/seam-carve</h3> | |
<p>Content-aware resizing or object removal using the seam carving algorithm.</p> | |
<h4>Request Body</h4> | |
<pre><code>{ | |
"image": "data:image/png;base64,<base64-encoded-image>", | |
"mask": "data:image/png;base64,<base64-encoded-mask>", | |
"vs": 50, | |
"hs": 30, | |
"mode": "resize" | |
}</code></pre> | |
<table> | |
<tr> | |
<th>Parameter</th> | |
<th>Type</th> | |
<th>Description</th> | |
</tr> | |
<tr> | |
<td>image</td> | |
<td>string</td> | |
<td>Base64-encoded image with data URL prefix</td> | |
</tr> | |
<tr> | |
<td>mask</td> | |
<td>string</td> | |
<td>Base64-encoded mask (optional for resize mode, required for remove mode)</td> | |
</tr> | |
<tr> | |
<td>vs</td> | |
<td>integer</td> | |
<td>Number of vertical seams to add/remove (positive = add, negative = remove)</td> | |
</tr> | |
<tr> | |
<td>hs</td> | |
<td>integer</td> | |
<td>Number of horizontal seams to add/remove (positive = add, negative = remove)</td> | |
</tr> | |
<tr> | |
<td>mode</td> | |
<td>string</td> | |
<td>Either "resize" (change dimensions) or "remove" (remove objects)</td> | |
</tr> | |
</table> | |
<h4>Response</h4> | |
<pre><code>{ | |
"result": "data:image/png;base64,<base64-encoded-result>" | |
}</code></pre> | |
</div> | |
</section> | |
<section> | |
<h2>JavaScript Example</h2> | |
<p>Here's how to use the API in a JavaScript application:</p> | |
<h3>Inpainting Example</h3> | |
<pre><code>async function removeObject(imageBase64, maskBase64) { | |
const response = await fetch('{{ api_url }}/api/inpaint', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
image: imageBase64, | |
mask: maskBase64, | |
}), | |
}); | |
const data = await response.json(); | |
return data.result; // base64 encoded result image | |
}</code></pre> | |
<h3>Seam Carving Example</h3> | |
<pre><code>async function resizeImage(imageBase64, maskBase64) { | |
const response = await fetch('{{ api_url }}/api/seam-carve', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
image: imageBase64, | |
mask: maskBase64, | |
vs: -50, // Remove 50 vertical seams (make narrower) | |
hs: 30, // Add 30 horizontal seams (make taller) | |
mode: 'resize', // or 'remove' to remove objects | |
}), | |
}); | |
const data = await response.json(); | |
return data.result; | |
}</code></pre> | |
</section> | |
<section> | |
<h2>Setting Up a Drawing Canvas</h2> | |
<p>To integrate with our API, you'll need a way for users to draw masks over images. Here's a simple HTML5 Canvas example:</p> | |
<pre><code>function setupCanvas(imageUrl) { | |
// Create canvas elements | |
const imageCanvas = document.createElement('canvas'); | |
const maskCanvas = document.createElement('canvas'); | |
const container = document.getElementById('canvas-container'); | |
container.appendChild(imageCanvas); | |
container.appendChild(maskCanvas); | |
// Load image | |
const img = new Image(); | |
img.onload = function() { | |
// Set canvas dimensions | |
imageCanvas.width = maskCanvas.width = img.width; | |
imageCanvas.height = maskCanvas.height = img.height; | |
// Draw image on image canvas | |
const imgCtx = imageCanvas.getContext('2d'); | |
imgCtx.drawImage(img, 0, 0); | |
// Setup mask canvas for drawing | |
const maskCtx = maskCanvas.getContext('2d'); | |
maskCtx.fillStyle = 'rgba(255, 0, 0, 0.5)'; | |
// Drawing state | |
let isDrawing = false; | |
// Mouse/touch event handlers | |
maskCanvas.addEventListener('mousedown', startDrawing); | |
maskCanvas.addEventListener('mousemove', draw); | |
maskCanvas.addEventListener('mouseup', stopDrawing); | |
maskCanvas.addEventListener('mouseleave', stopDrawing); | |
function startDrawing(e) { | |
isDrawing = true; | |
draw(e); | |
} | |
function draw(e) { | |
if (!isDrawing) return; | |
const rect = maskCanvas.getBoundingClientRect(); | |
const x = e.clientX - rect.left; | |
const y = e.clientY - rect.top; | |
maskCtx.beginPath(); | |
maskCtx.arc(x, y, 15, 0, Math.PI * 2); | |
maskCtx.fill(); | |
} | |
function stopDrawing() { | |
isDrawing = false; | |
} | |
}; | |
img.src = imageUrl; | |
}</code></pre> | |
</section> | |
<section class="demo-section"> | |
<h2>Try It Out</h2> | |
<p>Visit InnoAI interactive demo frontend:</p> | |
<a href="https://huggingface.co/spaces/innoai/Magic" class="btn" target="_blank">Open Demo Frontend</a> | |
<p><small>Demo frontend connects to this API for processing images.</small></p> | |
</section> | |
<footer> | |
<p><small>© 2025 Magic Eraser API. MIT License.</small></p> | |
</footer> | |
</body> | |
</html> | |