python OpenCV连通域处理函数
胖大海pyh 人气:01、两个函数介绍
总得来说,connectedComponents()仅仅创建了一个标记图(图中不同连通域使用不同的标记,和原图宽高一致),connectedComponentsWithStats()可以完成上面任务,除此之外,还可以返回每个连通区域的重要信息–bounding box, area, andcentroid。
1.1什么是连通域
连通区域一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域。连通区域分析是指将图像中的各个连通区域找出并标记。
连通区域分析是一种在CVPR和图像分析处理的众多应用领域中较为常用和基本的方法。
例如:OCR识别中字符分割提取(车牌识别、文本识别、字幕识别等)、视觉跟踪中的运动前景目标分割与提取(行人入侵检测、遗留物体检测、基于视觉的车辆检测与跟踪等)、医学图像处理(感兴趣目标区域提取)、等等。也就是说,在需要将前景目标提取出来以便后续进行处理的应用场景中都能够用到连通区域分析方法,通常连通区域分析处理的对象是一张二值化后的图像。
1.2 cv2.connectedComponents()
函数各参数意义:
num_objects, labels = cv2.connectedComponents(image)
参数介绍如下:
image:也就是输入图像,必须是二值图,即8位单通道图像。(因此输入图像必须先进行二值化处理才能被这个函数接受)
返回值:
num_labels:所有连通域的数目
labels:图像上每一像素的标记,用数字1、2、3…表示(不同的数字表示不同的连通域)
1.3 cv2.connectedComponentsWithStats()
这个函数的作用是对一幅图像进行连通域提取,并返回找到的连通域的信息:retval、labels、stats、centroids
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8, ltype=None)
参数介绍如下:
- image:也就是输入图像,必须是二值图,即8位单通道图像。(因此输入图像必须先进行二值化处理才能被这个函数接受)
- connectivity:可选值为4或8,也就是使用4连通还是8连通。
- ltype:输出图像标记的类型,目前支持CV_32S 和 CV_16U。
返回值:
- num_labels:所有连通域的数目
- labels:图像上每一像素的标记,用数字1、2、3…表示(不同的数字表示不同的连通域)
- stats:每一个标记的统计信息,是一个5列的矩阵,每一行对应每个连通区域的外接矩形的x、y、width、height和面积,示例如下: 0 0 720 720 291805
- centroids:连通域的中心点
2、代码实践
两个代码的用处是共通的,cv2.connectedComponentsWithStats函数返回的信息量更大,所以这里展示它的应用。
import cv2 import numpy as np # 读入图片 img = cv2.imread("001.jpg") # 中值滤波,去噪 img = cv2.medianBlur(img, 3) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.namedWindow('original', cv2.WINDOW_AUTOSIZE) cv2.imshow('original', gray) # 阈值分割得到二值化图片 ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 膨胀操作 kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) bin_clo = cv2.dilate(binary, kernel2, iterations=2) # 连通域分析 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(bin_clo, connectivity=8) # 查看各个返回值 # 连通域数量 print('num_labels = ',num_labels) # 连通域的信息:对应各个轮廓的x、y、width、height和面积 print('stats = ',stats) # 连通域的中心点 print('centroids = ',centroids) # 每一个像素的标签1、2、3.。。,同一个连通域的标签是一致的 print('labels = ',labels) # 不同的连通域赋予不同的颜色 output = np.zeros((img.shape[0], img.shape[1], 3), np.uint8) for i in range(1, num_labels): mask = labels == i output[:, :, 0][mask] = np.random.randint(0, 255) output[:, :, 1][mask] = np.random.randint(0, 255) output[:, :, 2][mask] = np.random.randint(0, 255) cv2.imshow('oginal', output) cv2.waitKey() cv2.destroyAllWindows()
打印出的连通域的信息如下:
重点是理解stats和 labels 参数的意义,其他的参数都容易理解:
labels :对原始图中的每一个像素都打上标签,背景为0,连通域打上1,2,3。。。的标签,同一个连通域的像素打上同样的标签。相当与对每一个像素进行了分类(分割)
stats:每一连通域的信息,表示每个连通区域的外接矩形(起始点的x、y、宽和高)和面积
连通域检测的效果图:
3、总结
(1)连通域分析可以实现将前景目标提取出来以便后续进行处理(类似于轮廓处理)
(2)重点是cv2.connectedComponentsWithStats函数中stats和 labels 参数的意义
labels :对原始图中的每一个像素都打上标签,背景为0,连通域打上1,2,3。。。的标签,同一个连通域的像素打上同样的标签。相当与对每一个像素进行了分类(分割)
stats:每一连通域的信息,表示每个连通区域的外接矩形(起始点的x、y、宽和高)和面积
(3)从上面的例子可以看出,因物体有重叠会把不同物体的多个连通域 计为一个连通域,所以在连通域分析前可以先进行效果更好的分割和预处理操作。
加载全部内容