Colour masking with python VPI on Jetson Orin Nano

nvidia-l4t-core 36.4.4-20250616085344
Cuda v.12.6
JP 6.2 

I have successfully implemented colour masking in python CV2:

    lower_green = np.array([40, 51, 153])
    upper_green = np.array([75, 255, 255])

    # 4. Create a mask for green color
    mask = cv2.inRange(hsv, lower_green, upper_green)

… but want to try and do this with python vpi module.

I’ve tried to do it like this:

import sys
import vpi

import numpy as np
from PIL import Image
from argparse import ArgumentParser

# 2. Parse command line parameters
# -----------------------------------------------------------------------------
parser = ArgumentParser()
parser.add_argument('input',
                    help='Image to be used as input')
args = parser.parse_args()

# 3. Load input image and convert to HSV
# -----------------------------------------------------------------------------
try:
    # Load the image into a NumPy array first (RGB format by default)
    rgb_numpy_image = np.asarray(Image.open(args.input))
except IOError:
    sys.exit("Input file not found")
except Exception as e:
    sys.exit(f"Error with input file: {e}")

# Convert the RGB NumPy array to a Pillow Image, then convert to HSV
hsv_image = Image.fromarray(rgb_numpy_image).convert("HSV")
hsv_numpy_image = np.asarray(hsv_image)

# Create the single multi-channel HSV VPI image (used for masking)
# We use .copy() to ensure the array is contiguous, and this is the main input image
hsv_vpi = vpi.asimage(hsv_numpy_image.copy())

# Define the color bounds for masking (Example: Green)
# H (0-179), S (0-255), V (0-255)
lower_green_np = np.array([35, 70, 30], dtype=np.uint8) 
upper_green_np = np.array([85, 255, 255], dtype=np.uint8)

# Convert bounds to VPI images: Must reshape 1D array to a 2D single-row image (1, 3)
lower_green_vpi = vpi.asimage(lower_green_np.reshape(1, -1))
upper_green_vpi = vpi.asimage(upper_green_np.reshape(1, -1))

# Create an empty VPI image for the output mask (1-channel, U8 format)
mask_vpi = vpi.Image(hsv_vpi.size, vpi.Format.U8) 


# 4. Generate the Color Mask on the GPU
# -----------------------------------------------------------------------------
with vpi.Backend.CUDA:
    
    # 2. Create the binary mask from the original HSV image (hsv_vpi)
    # FINAL FIX: Try vpi.band_threshold(), the function explicitly designed for multi-channel range checking.
    color_mask = vpi.threshold(hsv_vpi, lower_green_vpi, upper_green_vpi, out=mask_vpi)
    
    # The final output is the mask image
    output_mask = color_mask

# 5. Lock the mask result and save the single-channel image
# -----------------------------------------------------------------------------
# Lock the single-channel mask image for CPU access
with output_mask.rlock_cpu() as mask_np:

    # The mask is a 2D NumPy array. Save it directly.
    # Pixels in the color range will be 255 (white), others 0 (black).
    Image.fromarray(mask_np).save('tutorial_color_mask.png')

print("Binary color mask successfully generated and saved as 'tutorial_color_mask.png'")

… but it continually fails due to this section:
color_mask = vpi.threshold(hsv_vpi, lower_green_vpi, upper_green_vpi, out=mask_vpi)
… where all permutations of the word ‘threshold’ fail.
What is the correct solution for this task?
No LLM answers please.
Many thanks.

Hi,

Just want to check your target first.
The color masking you means is you want to find the pixel within an image that the green value belong to certain range, is that correct?

We have an algorithm that can locate min/max pixel.
Have you checked that?

Thanks.

Nope, it’s not max / min, it should be something like ‘threshold’ for a mask. I’m kind of surprised that a standard function does not exist for it as i its a very basic step in tradition computer vision. CV2 does it ok on CPUs. I put a whole load of timers into my code and found it took too long to load this frame into the GPU so even trying to perform a blur function on GPU was pointless 😞

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.