opencv 十六 python下各种连通域处理方法(按面积阈值筛选连通域、按面积排序筛选连通域、连通域分割等方法)

这篇具有很好参考价值的文章主要介绍了opencv 十六 python下各种连通域处理方法(按面积阈值筛选连通域、按面积排序筛选连通域、连通域分割等方法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本博文基于python-opencv实现了按照面积阈值筛选连通域、按照面积排序筛选topK连通域、 连通域细化(连通域骨架提取)、连通域分割(基于分水岭算法使连通域在细小处断开)、按照面积排序赛选topK轮廓等常见的连通域处理代码。并将代码封装为shapeUtils类,在自己的python代码中import shapeUtil后即可使用相应的连通域处理方法。

1、背景知识

1.1 轮廓

轮廓(Contour )由连续的点组成,以线条的形式聚集在一起,通常是一个有x,y组成的点集,形式为N x 2(N表示轮廓中有n个点)。其是空心的,通常所统计的轮廓面积是那一圈线所包含的面积。在opencv中使用cv2.findContours来查找轮廓,使用cv2.contourArea来统计轮廓包含的面积,使用cv2.drawContours绘制轮廓。如下图就包含了2个轮廓
opencv python 提取单连通区域,opencv实战,opencv,python,人工智能

1.2 连通域

连通域(Connection)由在空间上连续(相邻)的像素点组成,是一个图形区域。相邻的标准有4连通域和8连通域,具体可以参考https://zhuanlan.zhihu.com/p/394073982。对二值图统计完连通域后,得到一个labels图,具体如下右图所示,其背景区域被标记为0,每个联通域的值都从原来的255更改为连通域序号。下图是按照8连通域的方式进行统计的,如果按照4连通域进行统计,那么标记为2的连通域就会被断开为两个(总共会有5个连通域,标签从1~5)。
opencv python 提取单连通区域,opencv实战,opencv,python,人工智能

1.3 连通域与轮廓的转换

连通域信息与轮廓存在本质的区别,联通域是一个形状(Mat),轮廓是一个闭合的线条点集(list,元素为坐标)。我们可以使用cv2.drawContours将轮廓绘制为连通域,也可以使用cv2.findContours统计连通域的轮廓信息。在某些情况下,一个轮廓就可以对应一个连通域;当连通域中存在孔洞的时候,则需要多个轮廓才能表示一个连通域。
具体如下图所示,当连通域没有孔洞时,可以转换为一个轮廓;当前存在一个孔洞时,则需要转换2个轮廓。
opencv python 提取单连通区域,opencv实战,opencv,python,人工智能

2、连通域处理方法

2.1 按照面积阈值筛选连通域

通过cv2.connectedComponentsWithStats函数统计出联通域的信息,labels为连通域标记图(具体参考1.2中的描述),stats为联通域统计信息(可见代码中的注释,其包含连通域的xywhs信息),通过对联通域统计信息stats的判断(将连通域面积与阈值threshold进行比较),修改连通域标记图labels将小于阈值的连通域标签值修改为0)。最后通过二值化方法,将联通域标记图转换为二值图。

import cv2
import numpy as np 
class shapeUtils:   
	def find_big_areo(img,threshold=1000):
        #https://blog.csdn.net/weixin_44599604/article/details/111687531
        retval, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)
        #stats的格式为二维数组,其中每一个元素为 x,y,w,h,s的格式,s为联通域面积
        '''
        stats      #我们看出有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)
        '''
        for i in range(1,stats.shape[0]):
            conj=i#获取联通域的标记值
            areo=stats[i,4]
            if areo<threshold:
                labels[labels==conj]=0
        labels=labels.astype(np.uint8)
        ret,labels=cv2.threshold(labels,1,255,cv2.THRESH_BINARY)
        return labels
img=cv2.imread("res.png",0)
ret,img=cv2.threshold(img,64,255,cv2.THRESH_BINARY)
im2=shapeUtils.find_big_areo(img,5000)
cv2.imshow("img",img)
cv2.imshow("labels",im2)
cv2.waitKey()

opencv python 提取单连通区域,opencv实战,opencv,python,人工智能

2.2 按照面积排序筛选topK连通域

按照面积排序筛选topK连通域。先使用connectedComponentsWithStats统计出labels和stats,然后创建一个行号(其实就是labels中连通域的标签值),并使其与stats的shape相同并将其与stats拼接在一起(在原始的stats中,第i个信息对应着标签值为i的联通域,对stats按面积排序后则会无法正常对应,故需要进行拼接),然后使用np.argsort对stats进行排序,在根据排序结果将topk个连通域后的标签值全部修改为0(将topk后的连通域删除),最后通过二值化方法,将联通域标记图转换为二值图。文章来源地址https://www.toymoban.com/news/detail-765591.html


import cv2
import numpy as np 
class shapeUtils:   
        def find_topK_areo(img,k=1):
        #https://blog.csdn.net/weixin_44599604/article/details/111687531
        retval, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)
        #stats的格式为二维数组,其中每一个元素为 x,y,w,h,s的格式,s为联通域面积
        '''
        stats      #我们看出有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)
        '''
        #创建一个行号,并使其与stats的shape相同
        rows_num=[x for x in range(stats.shape[0])]
        rows_num=np.array(rows_num)#shape (3)
        rows_num=rows_num.reshape((-1,1)) #shape (3,1)

        print(rows_num.shape,stats.shape)
        #数据维度变化:(3, 1) (3, 5)=>(3, 6)
        stats=np.concatenate((rows_num,stats),axis=1)#拼接时要仅有一个维度不同,才能拼接
        #此时的stats的格式为二维数组,其中每一个元素为 x,y,w,h,s的格式,s为联通域面积
        '''
        拼接后的 stats 如下所示
                  #row x   y   w   h  s 
        >>> array([[0, 0,  0, 10, 10, 76],  # 这代表整个图片,0值也有连通区域
                   [1, 4,  1,  5,  6, 18],  # 这里18代表有18个像素 下面的6同理
                   [2, 2,  2,  3,  2,  6]], dtype=int32)
        '''

        #安装面积对连通域进行排序
        sortId=np.argsort(stats[:,-1])#生成一个排序好的下标,从小到大排序
        sortId=sortId[::-1]#对下标进行逆序,使其变为从大到小的排序
        stats=stats[sortId]#根据序号重新取数据
        #stats=stats[np.argsort(stats[:,-1])[::-1] ]
        print(stats)

        #将第k面积个后的连通域label设置为0
        for i in range(k+1,stats.shape[0]):
            conj=stats[i][0]#获取联通域的标记值
            labels[labels==conj]=0
        print(labels

到了这里,关于opencv 十六 python下各种连通域处理方法(按面积阈值筛选连通域、按面积排序筛选连通域、连通域分割等方法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [C++]使用OpenCV去除面积较小的连通域

    这是后期补充的部分,和前期的代码不太一样 效果图 源代码 前期做的,方法可能不太一样 一,先看效果图 原图 处理前后图   二,实现源代码      

    2024年04月10日
    浏览(44)
  • Opencv+Python笔记(五)图像阈值化处理

    图像阈值化可以理解为一个简单的图像分割操作,阈值又称为临界值,它的目的是确定出一个范围,然后这个范围内的像素点使用同一种方法处理,而阈值之外的部分则使用另一种处理方法或保持原样。 阈值处理有2种方式,一种是固定阈值方式,又包括多种处理模式,另一

    2023年04月26日
    浏览(41)
  • OpenCV阈值处理(threshold函数、自适应阈值处理、Otsu处理)

    目录 阈值处理 一.threshold函数 1.二值化阈值处理(cv2.THRESH_BINARY) 2.反二值化阈值处理( cv2.THRESH_BINARY_INV) 3.截断阈值化处理(cv2.THRESH_TRUNC) 4.超阈值零处理(cv2.THRESH_TOZERO_INV) 5.低阈值零处理(cv2.THRESH_TOZERO)  二.自适应阈值处理  三.Otsu处理 阈值处理是指剔除图像内像素

    2024年02月12日
    浏览(49)
  • 入门OpenCV:图像阈值处理

    图像阈值是一种简单、高效的图像分割方法,目的是将图像转换成二值图像。这个过程涉及比较像素值和阈值,根据比较结果来确定每个像素点的状态(前景或背景)。图像阈值在处理二维码、文本识别、物体跟踪等领域中非常有用。本博客旨在简介OpenCV中的阈值处理方法,

    2024年02月19日
    浏览(45)
  • OpenCV自学笔记九:阈值处理

    1. 阈值处理(Thresholding):阈值处理是一种图像分割的方法,它根据像素灰度值与设定的阈值进行比较,将像素分为两个类别(例如黑白、前景背景等)。阈值处理可以用于目标检测、图像增强等应用。在OpenCV中,常用的阈值处理函数是`cv2.threshold()`。 2. threshold函数:`cv2.t

    2024年02月08日
    浏览(40)
  • OpenCV 入门教程:全局阈值处理

    全局阈值处理是图像处理中常用的技术之一,用于将图像转换为二值图像,从而提取感兴趣的目标区域。在 OpenCV 中,全局阈值处理可以通过简单的像素比较来实现。本文将以全局阈值处理为中心,为你介绍使用 OpenCV 进行二值图像处理的基本步骤和实例。 😃😄 ❤️ ❤️

    2024年02月13日
    浏览(49)
  • opencv(三)边界填充、图像融合、图像阈值处理

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 边界填充就是将图片按一定的方法将图片的四周向外填充并将图片放大 因为opencv中的颜色通道不是RGB而是BGR,所以我们要用到之前讲到的分割将颜色通道重新整合成RGB后再用matplotlib库将其画出 BORDER_R

    2024年02月21日
    浏览(58)
  • opencv-27 阈值处理 cv2.threshold()

    阈值处理(Thresholding)是一种常用的图像处理技术,在机器学习和计算机视觉中经常被用于二值化图像或二分类任务。它基于设定一个阈值来将像素值进行分类,将像素值大于或小于阈值的部分分为两个不同的类别,从而得到二值化的图像或进行二分类预测。 在图像处理中的

    2024年02月15日
    浏览(43)
  • 第五章 Opencv图像处理框架实战 5-3 图像阈值与平滑处理

    ret, dst = cv2.threshold(src, thresh, maxval, type) src: 输入图,只能输入单通道图像,通常来说为灰度图 dst: 输出图 thresh: 阈值 maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值 type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY

    2024年02月14日
    浏览(43)
  • opencv-28 自适应阈值处理-cv2.adaptiveThreshold()

    对于色彩均衡的图像,直接使用一个阈值就能完成对图像的阈值化处理。但是,有时图像的色彩是不均衡的,此时如果只使用一个阈值,就无法得到清晰有效的阈值分割结果图像。 有一种改进的阈值处理技术,其使用变化的阈值完成对图像的阈值处理,这种技术被称为自适应

    2024年02月15日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包