Ready-to-use React components for miniSAM browser-based image segmentation
npm install minisam-reactReady-to-use React components for miniSAM - browser-based image segmentation using the Segment Anything Model.
- Zero-config setup - Just import and use
- Fully customizable - Style it your way
- Hooks included - For programmatic control
- Tiny bundle - Optimized for production
- TypeScript ready - Full type support
- Automatic masking - Click and segment
``bash`
npm install @minisam/react minisam onnxruntime-webor
yarn add @minisam/react minisam onnxruntime-webor
pnpm add @minisam/react minisam onnxruntime-web
`tsx
import { MiniSamSegmenter } from "@minisam/react";
function App() {
return (
onMaskUpdate={(mask) => console.log("New mask:", mask)}
/>
);
}
`
That's it! The component handles everything automatically:
- Model initialization
- Image loading
- Click handling
- Mask generation
- UI rendering
`tsx`
onMaskUpdate={(mask) => {
// Handle the generated mask
console.log("Mask updated:", mask);
}}
/>
` Processing...tsx`
maskColor="#ff0000"
maskOpacity={0.3}
showClickMarkers={true}
onInitialized={() => console.log("miniSAM ready!")}
onError={(error) => console.error("Error:", error)}
>
{({ isLoading, clicks, reset, undo, setClickMode, extractMask }) => (
onClick={() => {
const mask = extractMask();
// Do something with the mask
}}
>
Extract Mask
{isLoading &&
)}
| Prop | Type | Default | Description |
| ------------------- | ------------------------------------ | ----------- | -------------------------------- |
| image | string \| File \| HTMLImageElement | - | Image source to segment |autoInit
| | boolean | true | Auto-initialize miniSAM on mount |clickMode
| | 'include' \| 'exclude' | 'include' | Default click mode |onMaskUpdate
| | (mask: ImageData \| null) => void | - | Callback when mask changes |onClicksUpdate
| | (clicks: Click[]) => void | - | Callback when clicks change |onImageLoad
| | (image: HTMLImageElement) => void | - | Callback when image loads |onInitialized
| | () => void | - | Callback when miniSAM is ready |onError
| | (error: Error) => void | - | Error handler |className
| | string | - | Container class name |imageClassName
| | string | - | Image canvas class name |maskClassName
| | string | - | Mask canvas class name |showClickMarkers
| | boolean | true | Show click position markers |clickMarkerSize
| | number | 20 | Size of click markers in pixels |maskOpacity
| | number | 0.5 | Mask overlay opacity (0-1) |maskColor
| | string | '#6366f1' | Mask color (hex) |includeClickColor
| | string | '#10b981' | Include click marker color |excludeClickColor
| | string | '#ef4444' | Exclude click marker color |
Access component methods using a ref:
`tsx
const segmenterRef = useRef
// Use ref methods
segmenterRef.current?.reset();
segmenterRef.current?.undo();
const mask = segmenterRef.current?.extractMask();
`
Available methods:
- reset() - Clear all clicks and maskundo()
- - Remove last clickextractMask()
- - Get current mask as ImageDatagetClicks()
- - Get all clicksgetMask()
- - Get current maskgetImage()
- - Get loaded image elementsetClickMode(mode)
- - Change click modesegmentWithClicks(clicks)
- - Segment with custom clicks
For more control, use the useMiniSam hook:
`tsx
import { useMiniSam } from "@minisam/react";
function MyComponent() {
const {
isInitialized,
isLoading,
image,
clicks,
mask,
loadImage,
addClick,
reset,
extractMaskAsBlob,
} = useMiniSam();
const handleImageUpload = async (file: File) => {
await loadImage(file);
};
const handleCanvasClick = async (x: number, y: number) => {
await addClick(x, y, "include");
};
const downloadMask = async () => {
const blob = await extractMaskAsBlob();
if (blob) {
// Download the blob
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "mask.png";
a.click();
}
};
return
$3
`tsx
const minisam = useMiniSam({
autoInit: true,
onInitialized: () => console.log("Ready!"),
onError: (error) => console.error(error),
});
`$3
| Property/Method | Type | Description |
| ----------------------- | -------------------------------------------- | ------------------------------ |
|
isInitialized | boolean | Whether miniSAM is initialized |
| isLoading | boolean | Loading state |
| image | HTMLImageElement \| null | Loaded image |
| clicks | Click[] | Current clicks |
| mask | ImageData \| null | Current mask |
| initialize() | () => Promise | Manual initialization |
| loadImage() | (source) => Promise | Load an image |
| addClick() | (x, y, type?) => Promise | Add a click |
| removeLastClick() | () => Promise | Remove last click |
| reset() | () => void | Clear clicks and mask |
| segment() | () => Promise | Run segmentation |
| segmentWithClicks() | (clicks) => Promise | Segment with custom clicks |
| extractMaskAsCanvas() | () => HTMLCanvasElement \| null | Get mask as canvas |
| extractMaskAsBlob() | (type?, quality?) => Promise | Get mask as blob |Utility Functions
The package includes helpful utilities for working with masks:
`tsx
import {
maskToCanvas,
applyMaskToImage,
trimCanvasToContent,
downloadCanvas,
getMaskBounds,
} from "@minisam/react";// Convert mask to canvas
const canvas = maskToCanvas(mask);
// Apply mask to image and trim
const maskedImage = applyMaskToImage(image, mask, {
trimToContent: true,
padding: 10,
});
// Download the result
downloadCanvas(maskedImage, "extracted-object.png");
// Get mask boundaries
const bounds = getMaskBounds(mask);
console.log(
Mask size: ${bounds.width}x${bounds.height});
`Examples
$3
`tsx
function SimpleSegmenter() {
const [imageUrl, setImageUrl] = useState(""); return (
type="text"
placeholder="Enter image URL"
value={imageUrl}
onChange={(e) => setImageUrl(e.target.value)}
/> {imageUrl && (
image={imageUrl}
onMaskUpdate={(mask) => {
if (mask) {
console.log("Segmentation complete!");
}
}}
/>
)}
);
}
`$3
`tsx
function FileUploadSegmenter() {
const [file, setFile] = useState(null);
const segmenterRef = useRef(null); const handleExtract = async () => {
const mask = segmenterRef.current?.extractMask();
if (mask && file) {
// Process the mask
const canvas = applyMaskToImage(segmenterRef.current.getImage()!, mask, {
trimToContent: true,
});
// Download result
downloadCanvas(canvas,
${file.name}-extracted.png);
}
}; return (
type="file"
accept="image/*"
onChange={(e) => setFile(e.target.files?.[0] || null)}
/> {file && (
<>
>
)}
);
}
`$3
`tsx
function BatchProcessor() {
const { loadImage, segmentWithClicks, extractMaskAsBlob } = useMiniSam(); const processImages = async (files: File[]) => {
const results = [];
for (const file of files) {
// Load image
await loadImage(file);
// Apply predetermined clicks
const mask = await segmentWithClicks([
{ x: 100, y: 100, type: "include" },
{ x: 200, y: 200, type: "include" },
]);
if (mask) {
// Extract as blob
const blob = await extractMaskAsBlob();
results.push({ file: file.name, blob });
}
}
return results;
};
// ... rest of component
}
`Styling
The component uses minimal inline styles by default. You can customize everything using the provided class names:
`css
/ Base container /
.minisam-container {
position: relative;
display: inline-block;
}/ Image canvas /
.minisam-image-canvas {
max-width: 100%;
height: auto;
cursor: crosshair;
}
/ Mask overlay /
.minisam-mask-canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
/ Click markers /
.minisam-click-marker {
position: absolute;
border-radius: 50%;
pointer-events: none;
transform: translate(-50%, -50%);
}
`Performance Tips
1. Preload models: The component automatically initializes on mount. For better UX, initialize early:
`tsx
// In your app root
import { initSegmentation } from "minisam"; // Preload models
initSegmentation().then(() => {
console.log("Models loaded!");
});
``2. Reuse sessions: The component maintains segmentation sessions automatically. Avoid recreating components unnecessarily.