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

news2024/9/21 14:30:35

本博文基于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个轮廓
在这里插入图片描述

1.2 连通域

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

1.3 连通域与轮廓的转换

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

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()

在这里插入图片描述

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

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Llama 架构分析

从代码角度进行Llama 架构分析 Llama 架构分析前言Llama 架构分析分词网络主干DecoderLayerAttentionMLP 下游任务因果推理文本分类 Llama 架构分析 前言 Meta 开发并公开发布了 Llama系列大型语言模型 (LLM)&#xff0c;这是一组经过预训练和微调的生成文本模型&#xff0c;参…

AWS向量数据库Amazon OpenSearch Service使用测评

前言 在大模型盛行的当今&#xff0c;选择适宜的数据库显得尤为重要。因为你需要面对海量训练数据&#xff0c;快速的检索至关紧要&#xff0c;以及对于存储的要求也是至关重要的。对于海量的数据查询和存储是需要巨大的算力支持。向量数据库常用在一些图像文本或者视频的生成…

了解 Flutter 3.16 功能更新

作者 / Kevin Chisholm 我们在季度 Flutter 稳定版发布会上带来了 Flutter 3.16&#xff0c;此版本包含诸多更新: Material 3 成为新的默认主题、为 Android 带来 Impeller 的预览版、允许添加适用于 DevTools 的扩展程序等等&#xff0c;以及同步推出 Flutter 休闲游戏工具包重…

php查询数据库,并通过表格展示

第一步&#xff1a;创建数据库 创建一个数据库php-crud 第二步&#xff1a;创建数据库表 在数据库php-crud下创建一个歌曲表song /*Navicat Premium Data TransferSource Server : MariaDBSource Server Type : MariaDBSource Server Version : 100605 (10.6.5-M…

PrimDiffusion:3D 人类生成的体积基元扩散模型NeurIPS 2023

NeurIPS2023 &#xff0c;这是一种用于 3D 人体生成的体积基元扩散模型&#xff0c;可通过离体拓扑实现明确的姿势、视图和形状控制。 PrimDiffusion 对一组紧凑地代表 3D 人体的基元执行扩散和去噪过程。这种生成建模可以实现明确的姿势、视图和形状控制&#xff0c;并能够在…

linux 开机启动流程

1.打开电源 2.BIOS 有时间和启动方式 3.启动Systemd 其pid为1 4.挂载引导分区 /boot 5.启动各种服务 如rc.local

Ps:形状工具 - 描边选项

在形状工具的工具选项栏或“属性”面板中&#xff0c;单击“设置形状描边类型” Set shape stroke type菜单图标可打开“描边选项” Stroke Options面板。 描边预设 Stroke Type 默认列出了实线、虚线和点线三种类型的描边&#xff0c;单击可应用。 自己创建并存储的描边类型&a…

蓝桥杯专题-真题版含答案-【国庆星期日】【三色棋】【蒙地卡罗法求 PI】【格雷码(Gray Code)】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

selenium-grid4.3.0两种模式记录

selenium-grid4.3.0两种模式记录 本文运行&#xff0c;需要提前配置好Java11以及安装好Chrom、Firefox、Safari其中一个浏览器&#xff0c;如果是Chrom、Firefox需要下载对应版本的驱动&#xff0c;并给 webdriver 配置环境变量&#xff0c;Safari浏览器Mac系统会自带&#xf…

SQL进阶理论篇(八):SQL查询的IO成本

文章目录 简介数据库缓冲池查看缓冲池的大小数据页加载的三种方式通过 last_query_cost 统计 SQL 语句的查询成本总结参考文献 简介 本节将介绍磁盘IO是如何加载数据的&#xff0c;重点介绍一下数据库缓冲池的概念。主要包括&#xff1a; 什么是数据库缓冲池&#xff0c;它在…

CSS学习笔记整理

CSS 即 层叠样式表/CSS样式表/级联样式表&#xff0c;也是标记语言&#xff0c; 用于设置HTML页面中的文本内容&#xff08;字体、大小、对齐方式等&#xff09;、图片的外形&#xff08;宽高、边框样式、边距&#xff09;以及版面的布局和外观显示样式 目录 准备工作 Chrome调…

关于反射机制的简单理解

1、反射的简单认识 1.1 定义 Java的反射&#xff08;reflection&#xff09;机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff0c;既然能拿到,那么我…

持续集成交付CICD:Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前后端应用

目录 一、实验 1.部署Ansible自动化运维工具 2.K8S 节点安装nginx 3.Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前后端应用 二、问题 1.ansible安装报错 2.ansible远程ping失败 3. Jenkins流水线通过ansible命令直接ping多台机器的网络状态报错 一、实验 …

Photoshop插件3D Map Generator Geo的使用记录1(版本说明、安装卸载使用和高程数据生成3D地形图的准备工作)

3D Map Generator是一款强大的地图创建和定制化工具&#xff0c;具有以下特点和功能&#xff1a; 快速创建3D地图&#xff1a;用户可以通过该工具快速创建出高质量的3D地图&#xff0c;而无需具备专业的GIS或PS技能。支持多种图层类型&#xff1a;3D Map Generator支持多种图层…

pytest之allure测试报告03:allure动态自定义报告

1、测试用例模块中引入allure&#xff1a;import allure 2、yaml文件中定义添加title、story的值&#xff1a; 3、测试用例中读取调用。eg:allure.dynamic.title() 4、运行报告查看&#xff1a;成功动态展示yaml文件中配置的story、title

WPF-UI HandyControl 控件简单实战

文章目录 前言UserControl简单使用新建项目直接新建项目初始化UserControlGeometry:矢量图形额外Icon导入最优解决方案 按钮Button切换按钮ToggleButton默认按钮图片可切换按钮加载按钮切换按钮 单选按钮和复选按钮没有太大特点&#xff0c;就不展开写了总结 DataGrid数据表格G…

用标记接口定义类型

标记接口是不含有任何方法的接口&#xff0c;它的目的是通过将特定接口应用于类来为该类添加类型信息。以下是一个示例&#xff1a; public interface Drawable {// 标记接口&#xff0c;不包含任何方法 }public class Circle implements Drawable {private int radius;public…

过滤器和监听器及应用

Filter及应用 Filter有什么用?一、Filter处理中文乱码二、监听器&#xff0c;统计网站在线人数1.监听器引入2.统计网站在线人数 三、Filter实现权限拦截 Filter有什么用? Filter:过滤器&#xff0c;可以用来过滤网站的数据。 比如处理中文乱码&#xff0c;每次写servlet&…

k8syaml提供的几个有意思的功能,Kubernetes在线工具网站

k8syaml.cn 提供的几个有意思的功能。 一、yaml资源快速生成 之前编写operator的helm的时候就需要自己写deployment、service、configmap这些资源&#xff0c;那么多字段也记不清&#xff0c;都是先找个模版&#xff0c;然后copy改改&#xff0c;再看官方文档&#xff0c;添加…

LeetCode(66)二叉树的最大深度【二叉树】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 二叉树的最大深度 1.题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7]…