Image segmentation — which pixels belong to which object?
Two complementary entry points cover different use cases:
segment/2— promptable segmentation via SAM 2. Click a point or draw a box and get back a precise mask for that object. Great for "cut out this foreground" or "mask this product".segment_panoptic/2— class-labeled segmentation via DETR-panoptic. Every region in the image gets a class label (person,car,sky,road…). Great for "what's in this image and where?"
Quick start
# Mask the object at the centre of the image
iex> image = Image.open!("photo.jpg")
iex> %{mask: mask, score: _} = Image.Segmentation.segment(image)
# Mask the object at a specific point
iex> %{mask: mask} = Image.Segmentation.segment(image, prompt: {:point, 320, 240})
# Class-label every region
iex> segments = Image.Segmentation.segment_panoptic(image)
iex> Enum.map(segments, & &1.label)
["person", "car", "road", "sky"]Composing results with an image
# Make the masked object the only visible content (alpha mask)
iex> cutout = Image.Segmentation.apply_mask(image, mask)
# Colour-coded overlay of all segments
iex> overlay = Image.Segmentation.compose_overlay(image, segments)Default models
Promptable —
SharpAI/sam2-hiera-tiny-onnx(SAM 2 Tiny, Apache 2.0, encoder ~128 MB + decoder ~20 MB). Downloaded on first call viaImageVision.ModelCache.Class-labeled —
Xenova/detr-resnet-50-panoptic(DETR ResNet-50, Apache 2.0, ~172 MB). 250 COCO panoptic classes covering everyday things and stuff.
Both can be overridden via options — see segment/2 and
segment_panoptic/2 for details.
Optional dependency
This module is only available when
Ortex is configured in your
application's mix.exs.
Summary
Functions
Applies a mask as the alpha channel of an image.
Overlays colour-coded segment masks on an image.
Segments an object in an image using SAM 2.
Segments and labels every region in an image using DETR-panoptic.
Types
@type mask_result() :: %{score: float(), mask: Vix.Vips.Image.t()}
A mask returned by segment/2.
:score— SAM IoU prediction score.:mask— single-bandVix.Vips.Image.t/0in original image dimensions; white pixels are the segmented object.
@type segment() :: %{label: String.t(), score: float(), mask: Vix.Vips.Image.t()}
A segmented region returned by segment_panoptic/2.
:label— COCO panoptic class name, e.g."person"or"road".:score— confidence score in[0.0, 1.0].:mask— single-bandVix.Vips.Image.t/0; white (255) pixels belong to this segment, black (0) do not.
Functions
@spec apply_mask(Vix.Vips.Image.t(), Vix.Vips.Image.t()) :: {:ok, Vix.Vips.Image.t()} | {:error, Image.error()}
Applies a mask as the alpha channel of an image.
White pixels in the mask become fully opaque; black pixels become fully transparent. The result is an RGBA image suitable for compositing or exporting with transparency.
Arguments
imageis anyVix.Vips.Image.t/0.maskis a single-bandVix.Vips.Image.t/0of the same dimensions, such as the:maskfield ofmask_result/0orsegment/0.
Returns
{:ok, image}— an RGBAVix.Vips.Image.t/0, or{:error, reason}.
Examples
iex> image = Image.open!("./test/support/images/puppy.webp")
iex> %{mask: mask} = Image.Segmentation.segment(image)
iex> {:ok, cutout} = Image.Segmentation.apply_mask(image, mask)
iex> Image.bands(cutout)
4
@spec compose_overlay(Vix.Vips.Image.t(), [segment() | mask_result()], Keyword.t()) :: Vix.Vips.Image.t()
Overlays colour-coded segment masks on an image.
Each segment gets a distinct colour. Useful for visualising the
output of segment_panoptic/2.
Arguments
imageis anyVix.Vips.Image.t/0.segmentsis the list returned bysegment_panoptic/2, or any list of maps with:maskand:labelkeys.optionsis a keyword list of options.
Options
:alpha— opacity of the overlay as a float in[0.0, 1.0]. The default is0.5.
Returns
- The annotated
Vix.Vips.Image.t/0.
Examples
iex> image = Image.open!("./test/support/images/puppy.webp")
iex> segments = Image.Segmentation.segment_panoptic(image)
iex> overlay = Image.Segmentation.compose_overlay(image, segments)
iex> match?(%Vix.Vips.Image{}, overlay)
true
@spec segment(Vix.Vips.Image.t(), Keyword.t()) :: mask_result() | [mask_result()]
Segments an object in an image using SAM 2.
Accepts an optional point or box prompt to select which object to segment. With no prompt, the centre of the image is used.
Arguments
imageis anyVix.Vips.Image.t/0.optionsis a keyword list of options.
Options
:promptselects what to segment::auto— segment the object at the image centre (default).{:point, x, y}— segment the object at pixel(x, y).{:box, x, y, w, h}— segment the object inside the box.- A list of
{:point, x, y}tuples for multi-point prompting.
:multimask— whentrue, returns all three SAM candidate masks as a list sorted by descending score. Whenfalse(default), returns only the best mask as a singlemask_result/0.:min_score— minimum IoU score to return when:multimaskistrue. The default is0.0.:repo— HuggingFace repo for the SAM 2 ONNX models. Default is"SharpAI/sam2-hiera-tiny-onnx".:encoder_file— encoder ONNX filename within the repo. Default is"encoder.onnx".:decoder_file— decoder ONNX filename within the repo. Default is"decoder.onnx".
Returns
A
mask_result/0map when:multimaskisfalse.A list of
mask_result/0maps sorted by descending:scorewhen:multimaskistrue.
Examples
iex> image = Image.open!("./test/support/images/puppy.webp")
iex> %{score: score, mask: mask} = Image.Segmentation.segment(image)
iex> score > 0.0
true
iex> match?(%Vix.Vips.Image{}, mask)
true
@spec segment_panoptic(Vix.Vips.Image.t(), Keyword.t()) :: [segment()]
Segments and labels every region in an image using DETR-panoptic.
Returns one segment per detected object or region, each with a
class label, confidence score, and a binary mask. Covers 250 COCO
panoptic categories including everyday objects (person, car,
dog) and background regions (sky, road, grass).
Arguments
imageis anyVix.Vips.Image.t/0.optionsis a keyword list of options.
Options
:min_score— minimum confidence score to include a segment. The default is0.5.:repo— HuggingFace repo for the ONNX model. Default is"Xenova/detr-resnet-50-panoptic".:model_file— ONNX filename within the repo. Default is"onnx/model.onnx". Use"onnx/model_quantized.onnx"(~44 MB) for a much smaller model with some accuracy loss.
Returns
- A list of
segment/0maps sorted by descending:score. May be empty if no segment meets:min_score.
Examples
iex> image = Image.open!("./test/support/images/puppy.webp")
iex> segments = Image.Segmentation.segment_panoptic(image)
iex> is_list(segments)
true
iex> Enum.all?(segments, &match?(%{label: _, score: _, mask: _}, &1))
true