OpenCV为何检测到面积与像素长度均为0的轮廓?
OpenCV检测出大量面积为0的轮廓原因及解决方法
我有一个文件夹,里面全是以黑色为主、点缀白色斑点的PNG图像(已附上示例图)。我编写代码输出检测到的每个轮廓面积,但多数轮廓的面积为0。由于面积以像素为单位,我十分困惑这类伪影为何会被检测到。
代码如下:black = (0,0,0) color0 = (0,0,255) #Blue Green Red directory = 'C:/Users/mtl/PIPELINE/SUBTRACTED_deNoised_completed_frames/*.PNG' file_list = glob.glob(directory) # Read through folder and contour # i=0 for filename in file_list: img_read = cv2.imread(filename) img = cv2.cvtColor(img_read, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 5, 255, cv2.THRESH_BINARY) contours, _= cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) black_image = np.zeros((1192, 1192, 3), dtype=np.uint8) for cnt in contours : color=0 area = cv2.contourArea(cnt) print(area)代码输出了数值,但大部分为0,为何OpenCV会识别出无面积的轮廓?尤其是我认为测量单位为像素的情况下。
原因分析
- 轮廓点数量不足:
cv2.contourArea()计算面积的前提是轮廓构成封闭区域。如果轮廓只有1个孤立点,或是2个点组成的线段,没有封闭区域,面积就会返回0。 - 轮廓逼近模式的影响:你使用的
cv2.CHAIN_APPROX_NONE会保留轮廓上的所有像素点,图像中孤立的单白色像素、相邻两个白色像素组成的线段,都会被检测成轮廓,这类轮廓自然没有面积。 - 阈值残留噪声:即使做过去噪处理,阈值化后仍可能残留单像素级的噪声点,这些点会被
findContours识别为极小轮廓。
解决方法
- 过滤小面积轮廓:遍历轮廓时直接跳过面积小于阈值的无效轮廓,比如只保留面积大于1的:
for cnt in contours : area = cv2.contourArea(cnt) if area > 1: print(area) - 切换轮廓逼近模式:把
cv2.CHAIN_APPROX_NONE换成cv2.CHAIN_APPROX_SIMPLE,它会自动压缩轮廓上的冗余点,减少无效轮廓的生成:contours, _= cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) - 增加去噪步骤:阈值处理前再做一次去噪,比如用中值滤波过滤单像素噪声:
img = cv2.cvtColor(img_read, cv2.COLOR_BGR2GRAY) img = cv2.medianBlur(img, 3) # 3x3中值滤波 _, thresh = cv2.threshold(img, 5, 255, cv2.THRESH_BINARY) - 调整阈值参数:适当提高阈值(比如把
5调高到10),过滤掉更暗的噪声点,避免它们被二值化为白色。
内容的提问来源于stack exchange,提问作者mtllama
相关产品推荐
相关产品推荐

