如何使用threshold方法自适应分离图像中任意深浅的红色区域
红色自适应分离方案
核心思路
- 放弃纯BGR单通道处理逻辑,改用HSV颜色空间定位红色:红色的色相(H)通道取值范围固定,不受亮度、饱和度影响,对微弱红色的识别精度远高于单通道灰度阈值
- 改用红通道差值计算强化红色特征:通过红通道与蓝绿通道的差值放大红色区域和背景的差异,避免单一通道阈值受光照、对比度影响的问题
- 阈值处理后增加形态学后处理过滤噪点,提升掩膜质量
优化后可运行代码
import cv2 import numpy as np def adaptive_red_extract(img): # 方法1:HSV阈值法 适配绝大多数场景 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 红色色相区间分为两段 lower_red1 = np.array([0, 20, 10]) upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 20, 10]) upper_red2 = np.array([180, 255, 255]) mask1 = cv2.inRange(hsv, lower_red1, upper_red1) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) mask = mask1 | mask2 # 动态调整饱和度阈值适配低红色含量图像 # 统计非零像素占比,占比过低则降低S阈值 red_ratio = np.count_nonzero(mask) / (img.shape[0] * img.shape[1]) if red_ratio < 0.005: # 红色占比低于0.5%时放宽阈值 lower_red1[1] = 5 lower_red2[1] = 5 mask1 = cv2.inRange(hsv, lower_red1, upper_red1) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) mask = mask1 | mask2 # 形态学去噪 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=1) # 提取红色区域 red = cv2.bitwise_and(img, img, mask=mask) return red, mask # 偏好通道差方法可使用下方实现 def red_diff_extract(img): b, g, r = cv2.split(img) red_diff = cv2.subtract(r, cv2.add(g, b) // 2) # 对差值图做Otsu阈值 _, mask = cv2.threshold(red_diff, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) red = cv2.bitwise_and(img, img, mask=mask) return red, mask
效果样例

内容的提问来源于stack exchange,提问作者cedrik24
相关产品推荐
相关产品推荐

