CV2 Find Contours误检测地面而非目标:地板黑胶带检测的阈值调节难题
解决黑色胶带检测的阈值困境
我太懂这种两难了——全局阈值就像一把一刀切的刀,要么把地面误当成胶带,要么把胶带本身给切没了。咱们换几个思路来搞定这个问题:
1. 先试试自适应阈值,告别全局一刀切
全局阈值的问题在于它对整个图像用同一个标准,而地面和胶带的局部灰度差异可能没那么大。自适应阈值会根据每个像素周围的区域计算专属阈值,能更好地应对这种情况:
from cv2 import cv2 import numpy as np img = cv2.imread('tape4.jpeg', cv2.IMREAD_UNCHANGED) img_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 替换全局阈值为自适应阈值 thresh_img = cv2.adaptiveThreshold( img_grey, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, # 用高斯加权的邻域计算阈值 cv2.THRESH_BINARY_INV, # 反转阈值,让黑色胶带变成白色(方便后续找轮廓) 11, # 邻域大小(必须是奇数,可根据图像尺寸微调) 2 # 阈值微调值,控制阈值的偏移量 ) # 后续轮廓检测流程 contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) img_contours = np.zeros(img.shape, dtype=np.uint8) # 指定dtype避免保存图像异常 cv2.drawContours(img_contours, contours, -1, (0,255,0), 3) cv2.imwrite('contours_adaptive.png',img_contours)
2. 用HSV颜色空间直接锁定黑色,比灰度更精准
黑色在HSV颜色空间里有非常明确的范围,咱们直接基于颜色提取胶带,避开灰度值重叠的问题:
from cv2 import cv2 import numpy as np img = cv2.imread('tape4.jpeg', cv2.IMREAD_UNCHANGED) # 转换到HSV颜色空间 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义黑色的HSV范围(可根据实际图像微调V的上限) lower_black = np.array([0, 0, 0]) upper_black = np.array([180, 255, 50]) # 生成黑色区域的掩码 mask = cv2.inRange(hsv, lower_black, upper_black) # 形态学闭操作,去掉小噪点并填补胶带的微小缝隙 mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((5,5), np.uint8)) # 找轮廓并绘制 contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) img_contours = np.zeros(img.shape, dtype=np.uint8) cv2.drawContours(img_contours, contours, -1, (0,255,0), 3) cv2.imwrite('contours_hsv.png',img_contours)
3. 最后再加一层轮廓过滤,干掉误检的小轮廓
哪怕前面的步骤还有一些地面的误检轮廓,咱们可以通过轮廓的面积、宽高比来筛选出真正的胶带:
# 在找到contours之后,添加过滤逻辑 filtered_contours = [] for cnt in contours: area = cv2.contourArea(cnt) # 过滤掉面积太小的轮廓(数值根据你的图像尺寸调整) if area > 500: # 新增宽高比判断:胶带是长条状,宽高比要么远大于1要么远小于1 x, y, w, h = cv2.boundingRect(cnt) aspect_ratio = float(w)/h if aspect_ratio > 3 or aspect_ratio < 0.3: filtered_contours.append(cnt) # 只绘制过滤后的有效轮廓 cv2.drawContours(img_contours, filtered_contours, -1, (0,255,0), 3)
你可以先从HSV颜色空间的方法开始试,这通常是检测特定颜色物体最靠谱的路子,再配合形态学操作和轮廓过滤,基本就能解决你的阈值困境啦。
内容的提问来源于stack exchange,提问作者user14968775
相关产品推荐
相关产品推荐

