Surface Rendering Medical Segmentations
To render a segmentation as a 3D surface, we need to:
- Load the Segmentation volume (e.g. a
.seg.nrrdfile) into MATLAB - Create a 3D surface from one of the segmentations in that volume
- Render the 3D surface
Slicer Segmentation Files
In this example, we load a Slicer segmentation volume as a medicalVolume.
| Load Segmentation Volume | |
|---|---|
We also load the metadata from the volume.
| Load Segmentation Metadata | |
|---|---|
segT =
3×4 table
SegName Layer LabelValue Color
______________ _____ __________ _____________________________
"right kidney" 1 1 0.56471 0.93333 0.56471
"left kidney" 1 2 0 0.59216 0.80784
"aorta" 1 3 0.84706 0.39608 0.3098
As you can see, there are three different segmentations in this volume.
Render a Selected Segment
If you want to specify the segment to render, you must first index out the segment from the segmentation volume and then render it. The function mmGetMedicalVolumeSegment simplifies this process:
| Get right kidney Segment | |
|---|---|
segS =
struct with fields:
segName: 'right kidney'
mask: [465×276×390 logical]
color: [0.56471 0.93333 0.56471]
tform: [1×1 affinetform3d]
spacing: [1.027 1.027 1.027]
volume: 99574
mmGetMedicalVolumeSegment returns a structure that includes a logical mask of the specified segmentation (the mask field) and some basic metadata on the segment.
Measuring the Segment Volume
Notice that the volume field is 99574. This is not a physical volume — it is the number of voxels in the mask. To convert it into real-world units, we use the same approach we used to measure the taste bud image stack: multiply the number of voxels by the volume of a single voxel.
The voxel dimensions are stored in the spacing field (in millimeters), so the volume of one voxel is the product of its three sides:
| Convert voxel count to milliliters | |
|---|---|
So the segmented right kidney is about 108 mL — a reasonable size for an adult kidney. Checking that a measurement falls within a plausible anatomical range is a quick way to catch mistakes, such as forgetting to account for voxel spacing or segmenting the wrong structure.
Why does SpatialUnits say "unknown"?
When you load a .nrrd file, medicalVolume often reports SpatialUnits: "unknown" because the units are not written into the file. 3D Slicer always works in millimeters, so you can safely treat the spacing of Slicer datasets as mm.
Challenge: What are the volumes of the left kidney and the aorta?
Volumes of all segments
Render the Segment
Now we have the segmentation we want as its own volume (segS.mask). Next, we need to create a surface from this volume (using isosurface) and then render the surface (using patch). The course function mmPlotMask2Surface performs both of these steps in one function call.
| Render Kidney Surface | |
|---|---|
mmPlotMask2Surfacereturns a handle to the surface render (hp). Notice here we input the mask of the kidney (segS.mask) as the first input. We also input the transformation,segS.tform, using thetransformname-value argument. This transforms the segmentation into anatomical space (millimeter space).

Rendering with viewer3d
You can also render a segment in a viewer3d scene using images.ui.graphics.Surface, as follows:
hvr = viewer3d("BackgroundColor",'white','BackgroundGradient','off'); % create viewer
surf1 = images.ui.graphics.Surface(hvr,... % viewer handle
Color=segS.color, ... % face color of render
Data=segS.mask, ... % input mask
Alpha = 0.75, ... % set transparency
Wireframe="off",... % turn off wireframe
Transformation=segS.tform); % transform into real world space

In this example, the function
images.ui.graphics.Surfacecreates the surface and renders it in one step. The resulting render is a little more blocky than themmPlotMask2Surfacerender, but can be more easily combined withvolshowvisualization methods.
Render all Segments
We can render all segmentations in a segmentation volume with one function call using the course function mmPlotAllSeg:
mmPlotAllSeguses theisosurfacefunction to create the 3D surface and then thepatchfunction to render the surface. For volumes with more than one segmentation, it repeats the process for each segmentation. As you can see below, we get one surface render for each segmentation in the volume.

Surface render of kidneys and aorta using colors set in Slicer. The default transparency is set to 0.5.