如何用Python-OpenCV的cv2.inRange检测并定义两种非相邻颜色范围?
Hey there! I get why you might have hit a snag trying to detect red and blue together—since they’re non-adjacent in the HSV spectrum, you can’t use a single continuous range mask. Instead, we need to create separate masks for each color and combine them. Let’s break this down with a working Python-OpenCV implementation using the exact HSV ranges you provided.
Step-by-Step Implementation
1. Import Required Libraries
First, make sure you have numpy and opencv-python installed, then import them:
import cv2 import numpy as np
2. Load Image & Convert to HSV
OpenCV reads images in BGR format by default, so we need to convert it to HSV for reliable color detection:
# Load your image (replace 'input_image.jpg' with your actual image path) img = cv2.imread('input_image.jpg') # Convert BGR to HSV color space hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
3. Create Masks for Red and Blue
Use your predefined HSV ranges to generate binary masks—each mask will have white pixels (255) where the color matches, and black (0) elsewhere:
# Your provided HSV color ranges lower_red = np.array([160, 20, 70]) upper_red = np.array([190, 255, 255]) lower_blue = np.array([101, 50, 38]) upper_blue = np.array([110, 255, 255]) # Generate masks for each color mask_red = cv2.inRange(hsv_img, lower_red, upper_red) mask_blue = cv2.inRange(hsv_img, lower_blue, upper_blue)
4. Combine the Masks
Since we want to detect either red or blue, we use a bitwise OR operation to merge the two masks into a single combined mask:
combined_mask = cv2.bitwise_or(mask_red, mask_blue)
5. (Optional) Clean Up Noise with Morphological Operations
If your mask has small unwanted noise dots, you can apply morphological operations to smooth it out:
# Create a small kernel for noise removal kernel = np.ones((5, 5), np.uint8) # Apply opening (erosion + dilation) to eliminate tiny noise spots clean_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel)
6. Visualize or Extract Detected Regions
You can either overlay the mask on the original image to see detected areas, or extract the color regions directly:
# Option 1: Overlay mask on original image to highlight detected colors result = cv2.bitwise_and(img, img, mask=clean_mask) # Display all windows for comparison cv2.imshow('Original Image', img) cv2.imshow('Combined Mask', clean_mask) cv2.imshow('Detected Red & Blue', result) # Wait for a key press to close all windows cv2.waitKey(0) cv2.destroyAllWindows()
Why Your Previous Attempts Might Have Failed
- Using a single
ifcondition to check pixel values against both ranges is inefficient and error-prone—OpenCV’sinRangeis optimized for bulk pixel operations, and combining masks is the standard approach for multiple non-overlapping color ranges. - If you tried merging the HSV ranges into one continuous interval, you’d end up including unwanted colors between red and blue, which is why separate masks are necessary.
Pro Tips
- If you notice your red detection misses some shades, remember red wraps around the HSV hue circle (0-10 and 160-180 are both valid red ranges). You can add the lower red range (
lower_red2 = np.array([0,20,70]), upper_red2 = np.array([10,255,255])) and merge it with your existing red mask usingcv2.bitwise_or(mask_red, mask_red2). - Adjust the HSV ranges slightly if detection isn’t perfect—lighting conditions drastically affect how colors appear in HSV. You can use an HSV color picker tool to fine-tune values for your specific scenario.
内容的提问来源于stack exchange,提问作者Nhiên Ngô Định




