彩色图像目标轮廓检测:如何优化算法解决阴影场景漏检问题
彩色图像目标轮廓检测优化需求
现有彩色图像目标轮廓检测算法仅在部分图像上可得到不错的检测结果,存在两个核心缺陷:带阴影的图像检测效果较差,还会漏检图像中的部分目标,需要适配多样图像场景的鲁棒轮廓检测算法。
(原问题附3张示例图像)
当前实现代码
import cv2 import numpy as np from utils import getMaxContour, getFilteredLabelIndex def get_image_dimensions(img): height, width, channels = img.shape return height,width def create_blank_white_image(height, width): temp_img = np.zeros((width,height,3), np.uint8) temp_img.fill(255) return temp_img # 读取图像 inputImage = cv2.imread("new_test/images/5.png") inputImage = cv2.resize(inputImage, (800, 800)) h,w,chn = inputImage.shape ratio = inputImage.shape[0] / 800.0 # 深拷贝原始图像用于结果绘制 inputImageCopy = inputImage.copy() width, height = get_image_dimensions(inputImage) temp_img = create_blank_white_image(height, width) # 像素值归一化 imgFloat = inputImage.astype(np.float) / 255. # 计算K通道 kChannel = 1 - np.max(imgFloat, axis=2) # 转回8位无符号整型 kChannel = (255*kChannel).astype(np.uint8) _, binaryImage = cv2.threshold(kChannel, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 形态学操作清理掩码 kernelSize = 5 opIterations = 2 morphKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize)) # 闭运算填充孔洞 binaryImage = cv2.morphologyEx(binaryImage, cv2.MORPH_CLOSE, morphKernel, None, None, opIterations, cv2.BORDER_REFLECT101) cv2.imshow("binaryImage", binaryImage) h_threshold,w_threshold = binaryImage.shape area = h_threshold*w_threshold # 连通组件分析 (numLabels, labels, stats, centroids) = cv2.connectedComponentsWithStats( binaryImage, 4, cv2.CV_32S) print("轮廓数量",len(stats)) # 过滤不符合尺寸的连通域 filteredIdx = getFilteredLabelIndex(stats, areaHighLimit=area/2, heightUpperLimit=h_threshold*0.9, widthUpperLimit=w_threshold*0.9) for i in filteredIdx: componentMask = (labels == i).astype("uint8") * 255 cv2.waitKey(0) cv2.imshow("componentMask", componentMask) opIterations = 3 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) componentMask = cv2.morphologyEx(componentMask, cv2.MORPH_CLOSE, kernel, None, None, opIterations, cv2.BORDER_REFLECT101) cv2.imshow("componentMask", componentMask) # 提取最大轮廓 cntrs = getMaxContour(componentMask) # 绘制轮廓到原始图像 cv2.drawContours(inputImage, [cntrs], -1, (255, 0, 255), 4) cv2.imshow("contour", inputImage) # 动态调整线宽 line_width = 4 if int(temp_img.shape[0]/250)>line_width: line_width = int(temp_img.shape[0]/250) # 绘制轮廓到空白图像 cv2.drawContours(temp_img, [cntrs], -1, (255,0,0),line_width ) cv2.imshow("contour2", temp_img) cv2.imshow("original contour", temp_img) cv2.imwrite("new_test/my_algo_results/output/5.jpg", temp_img) cv2.waitKey(0) cv2.destroyAllWindows()
优化方案
原有算法依赖单K通道全局阈值分割,对阴影、光照不均场景抗性差,低对比度目标容易被漏分,可按以下方向优化:
- 预处理阶段加入光照校正:将图像转换到LAB颜色空间,对L通道使用CLAHE自适应直方图均衡,消除局部阴影和光照不均的影响。针对阴影严重的场景,可对L通道做阈值分割分离阴影区域,再做像素值补偿,避免阴影区域被误判为前景或背景。
- 改用多通道特征融合分割:不要仅用K通道做分割,可结合LAB的A、B通道和HSV的S通道,分别对多个通道做阈值分割后取并集,覆盖不同颜色特征的目标,减少漏检。
- 替换全局OTSU阈值为自适应局部阈值:使用
cv2.adaptiveThreshold()做局部阈值分割,对纹理复杂、光照不均的图像分割效果远优于全局阈值。 - 调整连通域过滤规则:在原有尺寸上限过滤的基础上加入面积下限、宽高比过滤,既可以过滤小噪声,也可以适配特定目标的形状特征,减少误检和漏检。
- 可选边缘特征补充:如果目标边缘模糊,可加入Canny边缘检测结果,和阈值分割的掩码做融合,补全漏检的轮廓边缘。
内容的提问来源于stack exchange,提问作者Subham Tiwari
相关产品推荐
相关产品推荐

