OpenCV-Python中目标颜色检测问题求助
Hey there! Let's troubleshoot your red color detection issue with OpenCV 3.4—this is a super common pitfall, so we'll work through it step by step.
Double-check your color space conversion
OpenCV reads images in BGR format by default, not RGB. When converting to HSV, using the wrong flag will throw off your hue values entirely:hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # Don't use COLOR_RGB2HSV!Mixing up BGR and RGB here is one of the most frequent causes of missing red detections.
Red needs two threshold ranges in HSV
Hue values for red wrap around the HSV color wheel (it spans ~0-10 and 170-180 in OpenCV's 0-179 hue scale). A single min/max range can't cover this—you'll need to create two masks and combine them:# Lower red range (darker/softer reds) lower_red = np.array([0, 120, 70]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv, lower_red, upper_red) # Upper red range (bright/vibrant reds) lower_red2 = np.array([170, 120, 70]) upper_red2 = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) # Combine both masks to catch all red tones final_mask = mask1 | mask2Tweak the saturation (S) and value (V) numbers based on your lighting—start with mid-range values like 120-255 for S and 70-255 for V, then adjust.
Preprocess to reduce noise
Grain or small artifacts in your image can break thresholding. Add a Gaussian blur before converting to HSV to smooth out distractions:blurred = cv2.GaussianBlur(frame, (5, 5), 0) hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)This helps the mask focus on actual red regions instead of tiny, random pixel variations.
Debug thresholds visually with trackbars
Guessing HSV values is hit-or-miss. Build a quick interactive tool to adjust thresholds in real-time:def nothing(x): pass cv2.namedWindow("Threshold Tuner") cv2.createTrackbar("Low H", "Threshold Tuner", 0, 179, nothing) cv2.createTrackbar("Low S", "Threshold Tuner", 0, 255, nothing) cv2.createTrackbar("Low V", "Threshold Tuner", 0, 255, nothing) cv2.createTrackbar("High H", "Threshold Tuner", 179, 179, nothing) cv2.createTrackbar("High S", "Threshold Tuner", 255, 255, nothing) cv2.createTrackbar("High V", "Threshold Tuner", 255, 255, nothing) while True: frame = cv2.imread("your_target_image.jpg") hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # Get current trackbar values l_h = cv2.getTrackbarPos("Low H", "Threshold Tuner") l_s = cv2.getTrackbarPos("Low S", "Threshold Tuner") l_v = cv2.getTrackbarPos("Low V", "Threshold Tuner") h_h = cv2.getTrackbarPos("High H", "Threshold Tuner") h_s = cv2.getTrackbarPos("High S", "Threshold Tuner") h_v = cv2.getTrackbarPos("High V", "Threshold Tuner") lower = np.array([l_h, l_s, l_v]) upper = np.array([h_h, h_s, h_v]) mask = cv2.inRange(hsv, lower, upper) result = cv2.bitwise_and(frame, frame, mask=mask) cv2.imshow("Mask", mask) cv2.imshow("Detected Red", result) if cv2.waitKey(1) == 27: # Press ESC to exit break cv2.destroyAllWindows()Slide the controls until the mask window shows solid white over all red areas—this gives you the exact threshold values you need.
Account for lighting variations
Red looks drastically different under warm indoor light vs. cool outdoor light. If your setup has variable lighting, try normalizing the image's brightness first:# Normalize brightness to stabilize values frame = cv2.normalize(frame, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
内容的提问来源于stack exchange,提问作者Stefan Radonjic

