Contenido principal

Deploy Image Segmentation on NVIDIA Jetson Thor Using PyTorchExportedProgram

R2026b
Since R2026b

This example shows how to deploy an image segmentation application on an NVIDIA® Jetson™ AGX Thor™ hardware board by using GPU Coder™ and the MATLAB® Coder™ Support Package for PyTorch® and LiteRT Models. The application uses a DeepLabv3+ network with a MobileNetV3-Large backbone [1] exported from PyTorch® as an ExportedProgram (.pt2). The deployed executable reads video frames, runs inference through the network, and displays the segmentation overlay on a monitor connected to the hardware board.

Prerequisites

To run this example, you must have:

  • An NVIDIA Jetson hardware board. To set up the hardware board, use the Hardware Setup tool.

  • An Ethernet crossover cable to connect the target board and development computer. If you connect the board to a local network, you do not need a cable.

  • A display connected to the hardware board.

  • The exported model file deeplabv3plus_mobilenetv3large.pt2. To generate this file, see the Export the PyTorch Model section.

Export the PyTorch Model

Before deploying, generate the ExportedProgram file that the entry-point function loads. To download the model, install PyTorch version 2.7.1 or newer and torchvision on the host machine, and then run this Python® code. The code downloads the pretrained DeepLabv3+ MobileNetV3-Large model, exports it with a 1-by-3-by-513-by-513 input tensor that matches the expected model input, and saves the result as deeplabv3plus_mobilenetv3large.pt2.

import torch
from torchvision.models.segmentation import deeplabv3_mobilenet_v3_large, DeepLabV3_MobileNet_V3_Large_Weights

model = deeplabv3_mobilenet_v3_large(weights=DeepLabV3_MobileNet_V3_Large_Weights.DEFAULT)
model.eval()

# Export with a 1x3x513x513 input tensor matching the expected model input
example = torch.randn(1, 3, 513, 513, dtype=torch.float32)
ep = torch.export.export(model, (example,))
torch.export.save(ep, "deeplabv3plus_mobilenetv3large.pt2")

Connect to the Jetson and Verify GPU Environment

Create a live hardware connection to the Jetson board by creating a jetson object. Use the coder.checkGpuInstall (GPU Coder) function to verify the GPU code generation environment on the Jetson board.

hwObj = jetson;
### Checking for CUDA availability on the target...
### Checking for 'nvcc' in the target system path...
### Checking for cuDNN library availability on the target...
### Checking for TensorRT library availability on the target...
### Checking for prerequisite libraries is complete.
### Gathering hardware details...
### Checking for third-party library availability on the target...
### Checking for available I2C buses...
### Gathering hardware details is complete.
Board name              : NVIDIA Jetson AGX Thor Developer Kit
CUDA Version            : 13.0
cuDNN Version           : 9.1
TensorRT Version        : 10.13.3
GStreamer Version       : 1.24.2
V4L2 Version            : 1.26.1
SDL Version             : 1.2
OpenCV Version          : 4.8.0
Available Webcams       : Logitech Webcam C930e
Available GPUs          : NVIDIA Thor
Available Digital Pins  : 
envCfg = coder.gpuEnvConfig("jetson");
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
envCfg.HardwareObject = hwObj;
coder.checkGpuInstall(envCfg);

Examine the Entry-Point Function

The entry-point function mEntryPoint uses the loadPyTorchExportedProgram function to load the PyTorch ExportedProgram into MATLAB. The function then passes the network to segmentVideo, which runs the segmentation pipeline. Examine the entry-point function.

type mEntryPoint.m
function mEntryPoint()
%#codegen
% Copyright 2025-2026 The MathWorks, Inc.

deeplabv3plus_mobilenetv3 = loadPyTorchExportedProgram("deeplabv3plus_mobilenetv3large.pt2");

segmentVideo(deeplabv3plus_mobilenetv3);
end

The segmentVideo function reads frames from the video file vipmen.avi located on the target. Before you run the generated application, copy the vipmen.avi file from the current folder to the target. The segmentVideo function processes each frame of the video through the network, and displays the segmentation overlay. For each frame, the function performs these steps:

  1. Preprocessing — Resize the frame to the 513-by-513 input size that the model requires and normalize it by using ImageNet statistics. The readFrame function reads the image in the HWCN layout, where H is height, W is width, C is the number of channels, and N is the number of observations. To use the image with the network, permute the image from the HWCN layout to the NCHW layout.

  2. Inference — Run forward inference on the preprocessed frame by using the invoke function. The output contains per-pixel class scores for 21 semantic classes.

  3. Postprocessing — Permute the output back to HWCN layout, and select the class with the highest score at each pixel. A colormap assigns a unique color to each class, and the labeloverlayHelper function overlays the segmentation on the original image.

  4. Display — On the Jetson, render the segmentation overlay directly on the connected display by using the imageDisplay object. Displaying the output on the hardware board provides real-time visualization without streaming frames back to the host.

type segmentVideo.m
function segmentVideo(net)
%#codegen
% Copyright 2026 The MathWorks, Inc.

hwobj = jetson;
vidLocation = '/home/ubuntu/Videos/vipmen.avi';
videoReadObj = VideoReader(hwobj,vidLocation,'Width',160,'Height',120);
dispObj = imageDisplay(hwobj);

% ImageNet normalization stats
imgMean = reshape(single([0.485, 0.456, 0.406]), [1 1 3]);
imgStd  = reshape(single([0.229, 0.224, 0.225]), [1 1 3]);

% Colormap for 21 classes
num_classes = 21;
palette_base_vals = [2^25 - 1, 2^15 - 1, 2^21 - 1];
class_indices = coder.const((1:num_classes)');
colors_raw = coder.const(double(class_indices) * palette_base_vals);
colors_normalized = coder.const(double(uint8(mod(colors_raw, 255))) / 255.0);

while videoReadObj.hasFrame
    frame = videoReadObj.readFrame();

    img_resized = imresize(frame, [513, 513]);
    img_normalized = (im2single(img_resized) - imgMean) ./ imgStd;
    % HWC -> NCHW for PyTorch
    img_nchw = permute(img_normalized, [4 3 1 2]);

    out = invoke(net, img_nchw);
    % NCHW -> HWC
    out = permute(out, [3 4 2 1]);
    % Per-pixel class with highest score
    [~, classIdx] = max(out, [], 3);

    if coder.target('MATLAB')
        segmented_image = labeloverlay(img_resized, classIdx, 'Colormap', colors_normalized);
    else
        segmented_image = labeloverlayHelper(img_resized, classIdx, 'Colormap', colors_normalized);
    end
    % Transpose for Jetson display layout
    segmented_image_t = cat(3, segmented_image(:,:,1)', ...
        segmented_image(:,:,2)', segmented_image(:,:,3)');
    image(dispObj, segmented_image_t);
end

end

Generate CUDA Code

To generate CUDA® code to deploy to the hardware board, create a GPU code configuration object for the executable build type.

cfg = coder.gpuConfig("exe");

Create a hardware configuration object that targets the Jetson platform.

cfg.Hardware = coder.hardware("NVIDIA Jetson");
cfg.Hardware.BuildDir = "~/remoteBuildDirOGVid";
cfg.GenerateExampleMain = "GenerateCodeAndCompile";

The codegen command generates CUDA code on the host, transfers it to the Jetson, and builds the executable remotely. GPU Coder embeds the network weights from the .pt2 file into the generated code as binary constants.

codegen -config cfg mEntryPoint -report
### Checking for CUDA availability on the target...
### Checking for 'nvcc' in the target system path...
Code generation successful: View report

Deploy the Application on Jetson Thor

Copy the video file vipmen.avi from the current folder to the Jetson workspace.

putFile(hwObj, "vipmen.avi", "/home/ubuntu/Videos/");

Run the application. The application opens a Simple DirectMedia Layer (SDL) window on the Jetson display. The SDL window shows the segmentation overlay on each video frame.

pid = runApplication(hwObj, "mEntryPoint");
### Launching the executable on the target...
Executable launched successfully with process ID 3634049.
Displaying the simple runtime log for the executable...

Note: For the complete log, run the following command in the MATLAB command window:
system(hwobj,'cat /home/ubuntu/remoteBuildDirOGVid/MATLAB_ws/R2026b/home/user/Documents/MATLAB/ExampleManager/user.Bdoc.j3341106.freshExample/coder_ai-ex43278067/mEntryPoint.log')

SDL window on the Jetson display showing a traffic video frame with the semantic segmentation overlay, where each road, vehicle, and background region is tinted with the color assigned to its class.

To stop the application, use the killApplication function.

killApplication(hwObj, "mEntryPoint");

References

[1] Chen, Liang-Chieh, Yukun Zhu, George Papandreou, Florian Schroff, and Hartwig Adam. “Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation.” In Computer Vision – ECCV 2018, edited by Vittorio Ferrari, Martial Hebert, Cristian Sminchisescu, and Yair Weiss. Springer International Publishing, 2018. https://doi.org/10.1007/978-3-030-01234-2_49.

See Also

Functions

Objects