热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python图像处理—cv2.connectedComponentsWithStats

cv2.connectedComponentsWithStats处理不规则连通区域函数介绍实例-参数详解举个栗子函数介绍retval,labels,stats,centroidsc

cv2.connectedComponentsWithStats 处理不规则连通区域

  • 函数介绍
  • 实例-参数详解
    • 举个栗子


函数介绍

retval, labels, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8)

输入值:

  • image : 是要处理的图片,官方文档要求是8位单通道的图像。
  • connectivity : 可以选择是4连通还是8连通。

输出值

  • retval : 返回值是连通区域的数量。
  • labels : labels是一个与image一样大小的矩形(labels.shape = image.shape),其中每一个连通区域会有一个唯一标识,标识从0开始。
  • stats :stats会包含5个参数分别为x,y,h,w,s。分别对应每一个连通区域的外接矩形的起始坐标x,y;外接矩形的wide,height;s其实不是外接矩形的面积,实践证明是labels对应的连通区域的像素个数。
  • centroids : 返回的是连通区域的质心。

实例-参数详解

举个栗子

1、 我创建了10x10的图片,其中像素值分别有0和100
在这里插入图片描述

输入的image就是我们这个10x10的图片
如果我们要分析8连通,就令

connectivity=8

2、用 opencv 将图片读入

image = cv2.imread('test1.tif') # 将上述的10*10图片存为test.tif的图片
img = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #转灰度
retval, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)

返回值

retval #retval = 3
>>> 3stats #我们看出有3个连通区域# x y w h s
>>> array([[ 0, 0, 10, 10, 76], # 这代表整个图片,0值也有连通区域[ 4, 1, 5, 6, 18], # 这里18代表有18个像素 下面的6同理[ 2, 2, 3, 2, 6]], dtype=int32)labels # labdels 将背景0值标为0,值为100的标为1 和 2
>>> array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],[0, 0, 2, 2, 2, 0, 1, 0, 0, 0],[0, 0, 2, 2, 2, 0, 1, 1, 1, 0],[0, 0, 0, 0, 0, 0, 1, 1, 1, 0],[0, 0, 0, 0, 1, 1, 1, 1, 1, 0],[0, 0, 0, 0, 1, 1, 1, 1, 1, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)centroids
>>> array([[4.17105263, 4.68421053],[6.38888889, 4.38888889],[3. , 2.5 ]]

3、我们来详细看一下如何利用stats和labels处理不规则图形

按照 stats返回的外接矩形分别如下两个矩形,其中蓝色的矩形有两个值在红色矩形内,同时可以看到原始数据的连通区域与labels可以相互对应
在这里插入图片描述
在这里插入图片描述

问题来了: 如果我想要将原始图片红色框内的100变为0,如果我们直接令外接矩形框内全部为0,这样不可避免的会伤及无辜将蓝色框内的两个100值都改为0.这个是不允许的。
所以我们可以利用labels的标识

label = labels[y:y + h, x:x + w] #获取要处理的红色方框外接矩形
lab = label.reshape(-1, ) # 二维转一维
lab = np.unique(lab) # 去掉重复
lab = np.setdiff1d(lab, 0) # 去掉0值,因为0值是背景的标识,我们不用处理0,只要除去1保留2即可

之后又因为stats中的返回值s是像素值的个数,并不是外接矩形内所有100值的个数。
下面两个图可以看出,红色框内100的值是20个,但构成连通区域的之后18个像素,所以stats返回值中是18不是20;这个很重要!!!!
在这里插入图片描述
这样在红色矩形框内的labels= 2 的数量只有两个,labels = 1的数量有18个,并且与s一致,可以依据这个条件,获取labels = 1 的坐标,并令这些坐标所在值等于0,这样labels = 2 的值并没有受到影像。

for l in lab:seeds = np.argwhere(label==l)seedlist = list(seeds)print(seedlist)if len(seedlist) == s:
# print(seedlist)for point in seedlist:image[point[0],point[1]] = 0img[y:y + h, x:x + w] = image

4 、结果:
在这里插入图片描述
原始图:
在这里插入图片描述

在这之前我尝试了一些别的函数,都不能很好的操作,下期会整理一下。


推荐阅读
author-avatar
TiaoHun35p_376
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有