Matlab Display Image
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Data and AI
- BSD-2-Clause
- No issues found
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
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-display-image/downloadUnzip 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 recommendimageshowfor 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 use | Use instead | Why |
|---|---|---|
imshow | imageshow | Better performance, higher quality, responsive interactions |
uiaxes + imshow in apps | viewer2d + imageshow | Viewer handles zoom, pan, and interactions natively |
rectangle(), drawrectangle(), imrect(), or insertObjectAnnotation | uidraw with Position | Interactive, programmatic placement, built-in measurements |
montage | imtile + imageshow | Composable, works with viewer |
figure + getframe(fig) | viewer2d + getframe(viewer) | Viewer waits for rendering to complete before capture |
| Manual image blending for overlays | imageshow with OverlayData | Built-in transparency, colormap, and display range control |
Manual for loop calling uidraw per annotation | uidraw with Wait="multiple" | Single session, user controls when done |
| Manual alpha blending with pixel math | OverlayAlphamap property | Built-in per-pixel transparency mapping |
linkaxes or manual callback synchronization | linkviewers | Purpose-built for viewer2d, handles all camera properties |
roipoly, manual mask painting | uipaint | Interactive brush-based painting with overlay feedback |
bigimageshow | imageshow with blockedImage | imageshow 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 region | viewer.CameraViewport = [x y w h] | Viewer is not an axes; xlim/ylim error on viewer2d |
tiledlayout/nexttile/subplot with imageshow | Multiple viewer2d in a uigridlayout, or imtile + single imageshow | imageshow creates a viewer2d, not an axes — it ignores tile parents, producing empty tiles and a separate viewer window |
for loop calling uiannotate per annotation | Single uiannotate call with n×m position matrix | One 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) + imageshow | imshowpair creates its own axes; use imfuse to composite then display with imageshow |
Key Components
| Component | Constructor | Key callback |
|---|---|---|
| Viewer | viewer2d(parent) | CameraMovedFcn, ObjectClickedFcn |
| Image | imageshow('numeric',Parent=viewer) | |
| Interactive Annotations | uidraw(parent, 'text') | AnnotationMovedFcn (on viewer) |
| Static Annotations | uiannotate(parent, 'text') | |
| Paintbrush Labeling | uipaint(imageObj) | |
| Linked Viewers | linkviewers([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));
endFor 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;
endGenerating 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);
endAnnotations
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, neverimshow,imagesc, orimage—imageshowauto-scales, handles all data types, and creates aviewer2dAlways: Pass the viewer handle explicitly to
title,getframe, and all other functions —gcadoes not return a viewerAlways: Use
getframe(viewer)notgetframe(gcf)for frame capture — the viewer handles async rendering completion and is significantly fasterAlways: Pass all positions to
uiannotatein a single call with an n×m matrix — never calluiannotatein a loop per annotationNever: Use
gcaor implicit current-axes patterns with viewer objects —gcareturns an axes, not a viewerNever: Use
tiledlayout,nexttile, orsubplotwithimageshow—imageshowcreates aviewer2d, not an axesNever: Use
xlim/ylimto zoom — useviewer.CameraViewport = [x y w h]insteadPrefer:
OverlayDatafor mask/segmentation display over manual alpha blendingNever: Parent
imageshowdirectly to auifigure— create aviewer2dfirst:v = viewer2d(fig); imageshow(im, Parent=v), or callimageshow(im)with no parentPrefer:
imtile+ singleimageshowfor quick multi-image composites; multipleviewer2dinuigridlayoutfor independent viewers
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md15.0 KiB
- manifest.yaml452 B
- references/annotations.md6.4 KiB
- references/app-building.md1.7 KiB
- references/painting-and-labeling.md1.0 KiB
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:
| Shape | Position 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:
uidraw | uiannotate | |
|---|---|---|
| Interaction | Interactive — user can draw, move, reshape | Static — display only, no user interaction |
| When to use | User needs to interactively create or edit annotations | Displaying pre-computed results (detections, segmentations, measurements) |
| Measurement labels | Automatic (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