Generated banner for Matlab Display Image
Generated logo for Matlab Display Image

Matlab Display Image

MathWorksOfficialCreated by MathWorks

  • Skill
  • Tool integration
  • Data and AI
  • BSD-2-Clause
  • No issues found

From the author

Display images and annotations for image processing, computer vision, and visual inspection. Use when displaying images with imageshow, creating image viewers with viewer2d, adding Regions of Interest (ROI) or annotations, overlaying masks or segmentations, streaming video frames, or building apps with image display.
— the description by MathWorks

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a set of functions and patterns for displaying images and annotations within MATLAB. It centers on the use of imageshow and viewer2d to handle image rendering, overlay data, and interactive elements. It provides specific guidance on avoiding legacy axes-based functions in favor of the viewer2d object, which supports native zoom, pan, and annotation capabilities. The skill covers standard image display, multi-image layouts, streaming data, and programmatic interaction.

What it does

  • Displays images using the imageshow function
  • Creates interactive image viewers with viewer2d
  • Adds interactive annotations via uidraw
  • Displays static batch annotations using uiannotate
  • Overlays masks and segmentation data on images
  • Synchronizes multiple viewers with linkviewers

When to use it

  • When building GUIs or apps requiring image display
  • When plotting ROIs, shapes, or annotations on images
  • When displaying labeled image data or segmentation overlays
  • When streaming video frames or updating image data dynamically
  • When comparing multiple images side-by-side

Advantages

  • Provides built-in support for zoom, pan, and interaction
  • Supports native overlay management for masks and segmentations
  • Enables efficient handling of large, file-backed images
  • Offers consistent patterns for app building and streaming
  • Includes dedicated tools for both interactive and batch annotations

Usage examples

“How do I display an image in a new viewer?”
Use the command obj = imageshow(im); to display the image and return the image object.
“How can I add a title to my image viewer?”
Pass the viewer object directly to the title function: title(viewer, 'My Image Title');.
“How do I zoom into a specific region of an image?”
Set the CameraViewport property on the viewer object: viewer.CameraViewport = [x y width height];.
“How do I display multiple images for comparison?”
Use linkviewers([v1, v2]) to synchronize pan and zoom across multiple viewer2d instances.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/matlab/matlab-display-image/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip matlab-display-image.zip -d .agents/skills

Documentation by MathWorks

Image Display

Display images with imageshow rather than imshow for more performant, higher quality image display with more responsive interactions for images of all sizes.

When to Use

  • User asks to create a GUI, app, dashboard, or interactive tool for image display

  • User wants ROIs, annotations, or other lines and shapes plotted on top of the image

  • User wants to display labeled image data or other overlay imagery on top of an image

When NOT to Use

  • User does not have the Image Processing Toolbox (just use imshow, but recommend imageshow for better performance)

  • User is displaying a small, static icon in an app (just use uiimage)

Note: Do NOT use bigimageshow. It is a legacy function. Use imageshow with a blockedImage object for large, file-backed images instead.

Legacy Patterns to Avoid

Do NOT useUse insteadWhy
imshowimageshowBetter performance, higher quality, responsive interactions
uiaxes + imshow in appsviewer2d + imageshowViewer handles zoom, pan, and interactions natively
rectangle(), drawrectangle(), imrect(), or insertObjectAnnotationuidraw with PositionInteractive, programmatic placement, built-in measurements
montageimtile + imageshowComposable, works with viewer
figure + getframe(fig)viewer2d + getframe(viewer)Viewer waits for rendering to complete before capture
Manual image blending for overlaysimageshow with OverlayDataBuilt-in transparency, colormap, and display range control
Manual for loop calling uidraw per annotationuidraw with Wait="multiple"Single session, user controls when done
Manual alpha blending with pixel mathOverlayAlphamap propertyBuilt-in per-pixel transparency mapping
linkaxes or manual callback synchronizationlinkviewersPurpose-built for viewer2d, handles all camera properties
roipoly, manual mask paintinguipaintInteractive brush-based painting with overlay feedback
bigimageshowimageshow with blockedImageimageshow handles blocked images directly, bigimageshow is legacy
title("text") or title(gca,"text")title(viewer,"text")gca does not return the viewer; pass the viewer object directly
xlim/ylim to zoom into a regionviewer.CameraViewport = [x y w h]Viewer is not an axes; xlim/ylim error on viewer2d
tiledlayout/nexttile/subplot with imageshowMultiple viewer2d in a uigridlayout, or imtile + single imageshowimageshow creates a viewer2d, not an axes — it ignores tile parents, producing empty tiles and a separate viewer window
for loop calling uiannotate per annotationSingle uiannotate call with n×m position matrixOne instanced object — orders of magnitude faster than per-annotation calls
imagesc(data)imageshow(data)imageshow handles scaling and colormapping automatically via DisplayRangeMode
imshowpair(A, B)imfuse(A, B) + imageshowimshowpair creates its own axes; use imfuse to composite then display with imageshow

Key Components

ComponentConstructorKey callback
Viewerviewer2d(parent)CameraMovedFcn, ObjectClickedFcn
Imageimageshow('numeric',Parent=viewer)
Interactive Annotationsuidraw(parent, 'text')AnnotationMovedFcn (on viewer)
Static Annotationsuiannotate(parent, 'text')
Paintbrush Labelinguipaint(imageObj)
Linked Viewerslinkviewers([v1, v2])

Patterns

Standard Image Display

Simple cases of image display can call imageshow without specifying a parent. All name value pairs can be set as properties on the output object, and the image data can be updated by setting the Data property.

obj = imageshow(im);

To add a title to the viewer, pass the viewer object directly to title. Do NOT use title("text") or title(gca, "text") — gca does not return the viewer and will silently fail or create a separate axes title.

obj = imageshow(im);
viewer = obj.Parent;
title(viewer, "My Image");

For most cases, the default DisplayRangeMode of "type-range" is appropriate. Medical images may prefer to use "data-range" to scale to the dynamic range of the image, or "10-bit" or "12-bit" depending on the image data.

obj = imageshow(im, DisplayRangeMode="data-range");

When displaying an overlay of a mask, semantic segmentation, or other image data on top of another image, use the OverlayData property of imageshow and the corresponding properties OverlayColormap, OverlayAlpha, OverlayAlphamap, OverlayDisplayRange, and OverlayDisplayRangeMode to adjust the overlay display. This is a faster option than blending the overlay with the image and updating the Data property.

obj = imageshow(im, OverlayData=mask);

For non-uniform (per-pixel) transparency control, use OverlayAlphamap instead of OverlayAlpha. This maps overlay data values to transparency levels. Accepts "linear", "quadratic", "cubic", or a custom n-element column vector.

obj = imageshow(im, OverlayData=heatmap);
obj.OverlayAlphamap = "quadratic";

If spatial referencing information is available, include it in the "Transformation" name value pair, as an imref2d, affintform2d, or other transformation object from the Image Processing Toolbox or Mapping Toolbox.

obj = imageshow(im, Transformation=tform);

Manual display range — set DisplayRange directly when DisplayRangeMode="manual" or override the automatic range:

% Window/level for a 16-bit medical image
obj = imageshow(ctSlice, DisplayRange=[40 400]);

Custom colormap — use the Colormap property for grayscale or indexed images:

obj = imageshow(grayImage, Colormap=turbo(256));
Displaying Multiple Images

Do NOT use tiledlayout, nexttile, or subplot with imageshow. imageshow creates a viewer2d, not an axes object — it cannot be parented into layout tiles. Calling imageshow inside a nexttile loop produces empty tiles and separate viewer windows.

Option 1: imtile for a quick composite — best for side-by-side review with no per-image interaction:

tiled = imtile({slice1, slice2, slice3}, GridSize=[1 3]);
imageshow(tiled);

Option 2: Multiple viewer2d in a uigridlayout — best when each image needs independent zoom/pan/annotations:

fig = uifigure(Name="Slice Review", Position=[100 100 1200 400]);
gl = uigridlayout(fig, [1 3]);
for i = 1:3
    v = viewer2d(gl);
    v.Layout.Row = 1;
    v.Layout.Column = i;
    imageshow(slices{i}, Parent=v, DisplayRange=[-1000 400]);
    title(v, sprintf("Slice %d", i));
end

For two-image comparisons, use imfuse and pass the result to a single imageshow instead of imshowpair.

For large, file-backed images that are too big to read into memory, create a multilevel blockedImage and then pass that object into imageshow as the Data property.

bim = blockedImage("tumor_091.tif");
imageshow(bim);
Streaming Images and Videos

When updating the display, reuse objects whenever possible. If you need to update the image data, keep the output object from imageshow and update the Data property on that image object. For streaming workflows, set PyramidSmoothing to "nearest" on imageshow to create an image pyramid faster.

% Inline — short logic
viewer = viewer2d();
title(viewer,"Streaming Image Data");
obj = imageshow([],Parent=viewer,PyramidSmoothing="nearest");

for idx = 1:100
    obj.Data = im;
    drawnow;
end
Generating Animations

When generating animations or capturing frames, always pass the viewer2d object to getframe — never getframe(fig) or getframe(gcf). In R2026a+, getframe(viewer) waits until all pending rendering updates have completed before capturing, which guarantees each frame is fully rendered and is significantly faster than figure-level capture. Using getframe on the figure instead captures immediately, producing blank or partially rendered frames. The viewer is the parent of the Image object output from imageshow.

% Inline — short logic
viewer = viewer2d();
obj = imageshow([],Parent=viewer,PyramidSmoothing="nearest");

nFrames = 100;
out = cell(1, nFrames);

for idx = 1:nFrames
    obj.Data = im;
    out{idx} = getframe(viewer);
end
Annotations

Use uidraw for interactive annotations (user draws/edits, supports Wait="multiple" for batch sessions) and uiannotate for static batch annotations (detections, boundaries, bounding boxes — any count). Decision rule: if positions come from an algorithm, use uiannotate; if the user needs to draw or edit, use uidraw. Always pass all positions to uiannotate in a single call with an n×m matrix — never loop. See references/annotations.md for full API, shape formats, and examples.

% WRONG — do NOT loop:
for i = 1:size(bboxes,1)
    uiannotate(viewer, "rectangle", bboxes(i,:), Color="red");
end

% RIGHT — single call with the full matrix:
uiannotate(viewer, "rectangle", bboxes, Color="red");
Responding to User Interactivity

Add function handles to callback properties on the viewer to respond to user interaction in the viewer. CameraMovedFcn allows a response after the camera is moved. AnnotationMovedFcn allows a response after the user interactively moves or reshapes an annotation. ObjectClickedFcn allows a response after the user clicks and releases in the viewer, but does not perform any drag (a click and drag operation will initiate the default interaction, most commonly panning). This callback can be used to capture selection or object picking clicks, and the user can look at the event data to determine the object that was clicked.

im = imread("peppers.png");
obj = imageshow(im);
viewer = obj.Parent;
% Draw a rectangle ROI interactively
roi = uidraw(obj, "rectangle", Color=[0,1,0], Label="ROI");
% Listen for movement and display the position
viewer.AnnotationMovedFcn = @(~,evt) fprintf("ROI Position: [%.1f, %.1f, %.1f, %.1f]\n", evt.Position);
Interactive Painting and Labeling

Use uipaint(imageObj) for pixel-level interactive labeling — returns a binary mask. Supports BrushSize and OverlayValue for multi-class labeling. See references/painting-and-labeling.md for single-class and multi-class examples.

Linked Viewers for Comparison

When displaying multiple images for side-by-side comparison (before/after, multi-modal, multi-band), use linkviewers to synchronize pan and zoom across viewer2d objects. When the user pans or zooms in one viewer, all linked viewers follow automatically.

v1 = viewer2d(parent1);
v2 = viewer2d(parent2);
imageshow(im1, Parent=v1);
imageshow(im2, Parent=v2);
linkviewers([v1, v2]);

To unlink viewers later:

linkviewers([v1, v2], "off");
Programmatic Zoom with CameraViewport

To programmatically zoom into or navigate to a specific region of an image, set CameraViewport on the viewer. This is the viewer2d equivalent of xlim/ylim for axes — but xlim and ylim error on a viewer2d (it is not an axes). Always use CameraViewport instead.

CameraViewport accepts a [x y width height] vector or a Rectangle object. It zooms the viewer so that the specified rectangle fills the display. Reading CameraViewport returns a Rectangle object whose .Position is the currently visible region.

fig = uifigure;
gl = uigridlayout(fig, [1 1]);
v = viewer2d(gl);
imageshow(im, Parent=v);
drawnow;  % allow camera to initialize
v.CameraViewport = [250 100 150 120];

Note: The viewer camera initializes asynchronously after imageshow loads data. Setting CameraViewport before initialization completes will error. Use an explicit uifigure → uigridlayout → viewer2d hierarchy and call drawnow before setting CameraViewport. If you still get errors, add pause(1) after drawnow to wait for initialization.

Reset to full image: v.CameraViewport = [0.5 0.5 size(im,2) size(im,1)];. Read visible region: vp = v.CameraViewport; disp(vp.Position);

Use CameraMovedFcn to respond when the user interactively pans or zooms:

v.CameraMovedFcn = @(~,~) disp("Visible: " + mat2str(v.CameraViewport.Position, 3));
App Building

Use viewer2d(parent) parented to a uigridlayout — not uiaxes with imshow. Create the Image eagerly with empty data (imageshow([], Parent=viewer)), then update obj.Data when data loads. See references/app-building.md for the full classdef template.

viewer2d is NOT an axes — always pass explicit handles

A viewer2d is not a MATLAB axes object. gca never returns a viewer2d, and axes-based functions (xlim, ylim, axis, subplot, tiledlayout) do not work on viewers. Always pass the viewer object explicitly to title, getframe, and any function that operates on the display — never rely on gca or implicit current-axes behavior.

% WRONG — gca does not return the viewer:
title("Bell Peppers")
title(gca, "Bell Peppers")

% RIGHT — pass the viewer explicitly:
title(viewer, "Bell Peppers")
getframe(viewer)

Conventions

  • Always: Use imageshow, never imshow, imagesc, or image — imageshow auto-scales, handles all data types, and creates a viewer2d

  • Always: Pass the viewer handle explicitly to title, getframe, and all other functions — gca does not return a viewer

  • Always: Use getframe(viewer) not getframe(gcf) for frame capture — the viewer handles async rendering completion and is significantly faster

  • Always: Pass all positions to uiannotate in a single call with an n×m matrix — never call uiannotate in a loop per annotation

  • Never: Use gca or implicit current-axes patterns with viewer objects — gca returns an axes, not a viewer

  • Never: Use tiledlayout, nexttile, or subplot with imageshow — imageshow creates a viewer2d, not an axes

  • Never: Use xlim/ylim to zoom — use viewer.CameraViewport = [x y w h] instead

  • Prefer: OverlayData for mask/segmentation display over manual alpha blending

  • Never: Parent imageshow directly to a uifigure — create a viewer2d first: v = viewer2d(fig); imageshow(im, Parent=v), or call imageshow(im) with no parent

  • Prefer: imtile + single imageshow for quick multi-image composites; multiple viewer2d in uigridlayout for independent viewers


Copyright 2026 The MathWorks, Inc.


Files

references/annotations.md

Image Annotations

Interactive Annotations with uidraw

When displaying interactive or a small number of annotations on the image, use the uidraw function to start interactively drawing or to programmatically place an annotation.

Supported shapes for uidraw:

ShapePosition format
"point"[x y]
"line"[x1 y1; x2 y2]
"circle"[x y z radius]
"ellipse"[x y semiAxisA semiAxisB rotationAngle]
"rectangle"[x y width height]
"polygon"[x1 y1; x2 y2; ...; xN yN]
"polyline"[x1 y1; x2 y2; ...; xN yN]
"freehand"[x1 y1; x2 y2; ...; xN yN]
"angle"[x1 y1; xVertex yVertex; x2 y2]

uidraw is ideal for cases with interactive annotations or static annotations. Calling uidraw without specifying the Position argument will begin interactive drawing. When the Label name value is not specified, the Label property on roi is set to string.empty(), which the object will interpret to display a standard measurement for the annotation type (e.g., the line will display a distance). When the viewer's SpatialUnits property is set to define the world units of the pixel, the annotations will include that unit in the measurement display.

When the user needs to draw many annotations in one continuous session (batch labeling, counting), use Wait="multiple" so the drawing tool stays active until the user explicitly accepts. This avoids re-invoking uidraw for each annotation and returns an array of ROI objects.

obj = imageshow(im);
rois = uidraw(obj, "circle", Wait="multiple", Color=[1,0,0]);
% rois is an array of all circles drawn in the session
% Circle Position is [x y z radius]; also accessible via .Center and .Radius
positions = vertcat(rois.Position);
obj = imageshow(im);
roi = uidraw(obj,"circle",Color=[1,0,0],Label="Region of Interest");

After placement, you can manually make the roi static and not allow any additional user interaction by setting Interactions to "none" on the output object.

obj = imageshow(im);
viewer = obj.Parent;
viewer.SpatialUnits = "m";
roi = uidraw(obj,"line",Color=[0,1,0]);
set(roi,"Interactions","none");
obj = imageshow(im);
roi = uidraw(obj,"rectangle",Position=[20,20,50,60],Color=[0,0,1],Label="Region of Interest");

Adjust the look and feel of the annotation if it is too thin by setting the HighVisibility, HighVisibilityColor, and HighVisibilityAlpha properties.

% Array of positions defining regions
pos = [20,20,50,60; 50,80,100,40];
obj = imageshow(im);
roi = uidraw(obj,"rectangle",Position=pos,Color=[1,0,0]);
set(roi,"HighVisibility","on");
set(roi,"HighVisibilityColor",[0,0,1]);

For metrology workflows using the Visual Inspection Toolbox, use uicaliper to measure multiple edge-based distances in the image.

obj = imageshow(im);
roi = uicaliper(obj);

Static Annotations with uiannotate

When displaying thousands to millions of non-interactive annotations — detection results, segmentation boundaries, bounding boxes, vector fields — use uiannotate instead of uidraw. uiannotate is optimized for rendering large annotation counts in a single call.

Always use uiannotate for static batch annotations. Do not check the MATLAB version or fall back to uidraw, OverlayData, or other workarounds — uiannotate is available in the current environment.

Choosing between uidraw and uiannotate:

uidrawuiannotate
InteractionInteractive — user can draw, move, reshapeStatic — display only, no user interaction
When to useUser needs to interactively create or edit annotationsDisplaying pre-computed results (detections, segmentations, measurements)
Measurement labelsAutomatic (distance, area, angle)No
Unique shapes"angle", "freehand", "polygon""arrow", "plus", "cuboid", "cylinder", "ellipsoid", "sphere"
Shared shapes"point", "line", "circle", "ellipse", "rectangle", "polyline"Same

Decision rule: If the annotation positions come from an algorithm (detector, segmenter, measurement tool) and the user does not need to move or reshape them, use uiannotate — even for a small number of annotations. Use uidraw only when the user needs to interactively draw or edit annotations. For batch detection results (bounding boxes, circles, centroids), always use uiannotate.

roi = uiannotate(viewer, shape, position)
roi = uiannotate(viewer, shape, position, Name=Value)

The first argument is the Viewer or the Image/Volume object (output of imageshow or volshow). Position is an n-row matrix where each row defines one annotation.

CRITICAL: Always pass all positions in a single uiannotate call. This creates one instanced graphics object on the client and is orders of magnitude faster than calling uiannotate in a loop. Pass the entire n×m position matrix — never loop over rows.

% WRONG — do NOT loop:
for i = 1:size(bboxes,1)
    uiannotate(viewer, "rectangle", bboxes(i,:), Color="red");
end

% RIGHT — single call with the full matrix:
uiannotate(viewer, "rectangle", bboxes, Color="red");

Name-value arguments: Color (RGB triplet, color name, or n×3 matrix for per-annotation colors), Alpha (scalar opacity 0–1), Visible ("on"/"off").

Display detection bounding boxes:

I = imread("rice.png");
bw = imbinarize(I);
props = regionprops(bw, "BoundingBox");
position = vertcat(props.BoundingBox);
viewer = imageshow(I);
roi = uiannotate(viewer, "rectangle", position);

Display detected circles with per-annotation colors:

I = imread("coins.png");
[centers, radii] = imfindcircles(I, [15 40], Sensitivity=0.9);
colors = lines(numel(radii));
viewer = imageshow(I);
roi = uiannotate(viewer, "circle", [centers radii], Color=colors);
roi.FaceAlpha = 0.3;

Display segmentation boundaries as polylines — use [NaN NaN] rows to separate multiple shapes in one call:

RGB = imread("pillsetc.png");
bw = imbinarize(im2gray(RGB));
B = bwboundaries(bw, "noholes");
positionArray = [];
for k = 1:numel(B)
    boundary = B{k};
    positionArray = [positionArray; boundary(:,[2 1]); NaN NaN];
end
viewer = imageshow(RGB);
roi = uiannotate(viewer, "polyline", positionArray);

Copyright 2026 The MathWorks, Inc.


Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
MathWorks
Publisher
MathWorks (Official)
Source
matlab/matlab-agentic-toolkit · skills-catalog/image-processing-and-computer-vision/matlab-display-image · commit 2a7f215
Licence
BSD 2-Clause License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.md)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by MathWorks.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-display-image.zip