Add SAM Smart Select and AI Inpaint tools to miniPaint

New features:
- Smart Select tool: Click to select objects using SAM (Segment Anything)
- AI Inpaint tool: Edit selected regions with text prompts

Changes:
- frontend/src/js/tools/smart_select.js: SAM-powered selection tool
- frontend/src/js/tools/ai_inpaint.js: AI inpainting with prompt dialog
- frontend/src/js/services/api.js: API service for backend communication
- frontend/src/js/config.js: Register new tools
- frontend/src/css/layout.css: Tool icon styles
- frontend/images/icons/: SVG icons for new tools
- backend/app/routers/tools.py: New base64 API endpoints
- frontend/Dockerfile: Updated for miniPaint build
- frontend/nginx.conf: Added /api prefix proxy
This commit is contained in:
Claude
2026-01-26 17:34:20 +00:00
parent d009a2c0f0
commit bf83ecc8ad
10 changed files with 816 additions and 5 deletions
+88
View File
@@ -0,0 +1,88 @@
/**
* API Service for communicating with the FastAPI backend
* Handles SAM selection and AI inpainting requests
*/
class ApiService {
constructor() {
// Backend API base URL - adjust for your deployment
this.baseUrl = window.API_BASE_URL || '/api';
}
/**
* Call SAM (Segment Anything Model) for smart selection
* @param {string} imageData - Base64 encoded image data
* @param {number} pointX - X coordinate of click point
* @param {number} pointY - Y coordinate of click point
* @returns {Promise<{mask: ImageData, polygon: Array}>}
*/
async smartSelect(imageData, pointX, pointY) {
const response = await fetch(`${this.baseUrl}/tools/smart-select-base64`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: imageData,
point_x: pointX,
point_y: pointY,
}),
});
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: 'Unknown error' }));
throw new Error(error.detail || `SAM request failed: ${response.status}`);
}
return response.json();
}
/**
* Call AI inpainting to edit a selected region
* @param {string} imageData - Base64 encoded image data
* @param {string} maskData - Base64 encoded mask data (white = area to edit)
* @param {string} prompt - Text prompt describing desired edit
* @param {Object} options - Additional options
* @returns {Promise<{result: string}>} - Base64 encoded result image
*/
async inpaint(imageData, maskData, prompt, options = {}) {
const response = await fetch(`${this.baseUrl}/tools/inpaint`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: imageData,
mask: maskData,
prompt: prompt,
negative_prompt: options.negativePrompt || '',
strength: options.strength || 0.8,
guidance_scale: options.guidanceScale || 7.5,
}),
});
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: 'Unknown error' }));
throw new Error(error.detail || `Inpaint request failed: ${response.status}`);
}
return response.json();
}
/**
* Health check for the backend
* @returns {Promise<boolean>}
*/
async healthCheck() {
try {
const response = await fetch(`${this.baseUrl}/health`);
return response.ok;
} catch {
return false;
}
}
}
// Singleton instance
const apiService = new ApiService();
export default apiService;