RETURN_TO_LOGS
SYS_DOCS: ONLINE
Artificial Intelligence / Computer Vision

Edge AI Pipelines: Real-Time Computer Vision with CUDA and YOLOv8

Aditya Pandit Sonwane
May 28, 2026
5 min read

1. Introduction

Edge platforms deployed on autonomous ground vehicles (AGVs) must operate under strict latency limits. When utilizing stereo visual inputs for obstacle mapping, processing high-definition frames on the CPU creates a significant bottleneck.

This post details my configuration of a GPU-accelerated perception system running YOLOv8 optimized with NVIDIA's TensorRT compiler on an NVIDIA Jetson module.

[SYS_TRANSITION]

2. TensorRT Model Compilation

To convert a PyTorch .pt model into an optimized TensorRT engine file (.engine), we perform INT8 calibration. This process scales model weights to run on hardware tensor cores, reducing power consumption and inference latency without sacrificing accuracy.

The model is compiled using the following setup script command:

bash
yolo export model=yolov8n.pt format=engine half=true device=0 workspace=4

This compiles the network to half-precision floating-point (FP16), optimizing thread mapping on the Jetson Orin Nano hardware.

[SYS_TRANSITION]

3. CUDA-Accelerated Preprocessing (Python API)

Before passing camera frames to the object detector, images must be resized, normalized, and converted to float channels. Performing this preprocessing on the CPU blocks the pipeline. Here is the implementation using cv2.cuda to upload frames directly to GPU memory:

python
import cv2
import numpy as np

class CUDAPreprocessor:
    def __init__(self, target_width=640, target_height=640):
        self.w = target_width
        self.h = target_height
        # Allocate CUDA Streams for concurrent processing
        self.stream = cv2.cuda.Stream()

    def process_frame(self, frame_cpu):
        # 1. Upload frame to GPU (Host to Device transfer)
        gpu_frame = cv2.cuda_GpuMat()
        gpu_frame.upload(frame_cpu, stream=self.stream)
        
        # 2. Convert Color to RGB (model standard)
        gpu_rgb = cv2.cuda.cvtColor(gpu_frame, cv2.COLOR_BGR2RGB, stream=self.stream)
        
        # 3. Resize using bilinear interpolation
        gpu_resized = cv2.cuda.resize(gpu_rgb, (self.w, self.h), stream=self.stream)
        
        # 4. Convert to float and scale to [0.0, 1.0]
        gpu_float = cv2.cuda_GpuMat(gpu_resized.size(), cv2.CV_32FC3)
        gpu_resized.convertTo(cv2.CV_32FC3, 1.0 / 255.0, gpu_float, stream=self.stream)
        
        # Synchronize stream before extracting GPU buffer
        self.stream.waitForCompletion()
        
        return gpu_float

By keeping frames in GPU memory from the capture buffer to the inference engine, we eliminated standard memory copies (Host-to-Device bottlenecks), resulting in a frame rate increase from 18 FPS to 45 FPS.

[SYS_TRANSITION]

4. Performance Benchmarks

Below is the comparative execution timeline mapping latency across different processing pipelines:

text
[PIPELINE CONFIG]                     [LATENCY MS]
CPU OpenCV + YOLOv8 PyTorch           ████████████████████ 55ms
CPU OpenCV + YOLOv8 ONNX              ██████████████ 38ms
CUDA Preprocess + YOLOv8 TensorRT     ████ 11ms
[SYS_TRANSITION]

5. Summary & Next Steps

Offloading pixel-level transforms and neural inferences to the Jetson's GPU frees up the ARM processor cores to handle higher-level tasks, such as ROS2 coordinate transforms and local path updates. In future iterations, we plan to implement stereo-depth calculations inside the CUDA stream to build spatial obstacle maps on the fly.

Aditya Pandit Sonwane
Aditya Pandit Sonwane

Systems & Robotics Engineer. Developing autonomous mobile platforms, configuring ROS2 EKF nodes, writing real-time CUDA perception pipelines, and embedded microcontrollers logic.