Python实现连通域标记算法

 更新时间:2023年12月13日 09:04:12   作者:微小冷  
如果把图像分为前景和背景两部分,那么连通域就是连通在一起的前景,这种关系对于二值图像来说比较明显,下面我们就来了解一下连通域标记算法原理及其Python实现吧

问题引入

通俗地说,如果把图像分为前景和背景两部分,那么连通域就是连通在一起的前景,这种关系对于二值图像来说比较明显。

以下面的硬币图像,在二值化之后,可以很明显看到,图像被分为黑色和白色两个部分,若以白色为背景,则黑色被白色隔开,彼此之间并不联通。连通域标记的目的,就是为不连通的这些黑色区域,标上不同的序号。

其绘图代码如下,其中climb是此前实现的自动ostu阈值算法,参考这篇:OTSU算法及其Python实现

import matplotlib.pyplot as plt
import numpy as np
path = r"coin.png"
img = plt.imread(path).astype(float)
img = np.mean(img, axis=2)
th = 0.513    # climb(img, 0.1, 0, 0.01)
b = img>th

def drawImg(im1, im2, c1='gray', c2='gray'):
    fig = plt.figure()
    ax = fig.add_subplot(121)
    plt.imshow(im1, cmap=c1)
    plt.axis('off')
    ax = fig.add_subplot(122)
    plt.imshow(im2, cmap=c2)
    plt.axis('off')
    plt.show()

drawImg(img, b)

实现

常用的连通域标记算法是Two-Pass算法,顾名思义,就是迭代两次,第一次用于记录相邻像素的连通域关系,第二次则把相连通的区域置以相同的标签。

在遍历之前,先初始化一个编号矩阵,考虑到Python提供了字典这种数据类型,所以第一次遍历,将关联相邻像素的编号。比如,点P12的编号是3,点P22的编号是4,而且二者均为目标,则将产生一组键值对{3:4}。

下面就是这个字典的创建过程,由于在遍历过程中,每个像素点要和它左侧和上方的像素点进行比较,所以这个字典的值应该是一个列表。

from itertools import product
def getIndDct(img):
    # 元素个数
    m,n = img.shape
    # 编号矩阵
    indMat = np.arange(m*n).reshape([m,n])
    dct = {}
    for i,j in product(range(m), range(n)):
        if img[i,j] == 0:
            continue
        ind = indMat[i,j]
        dct[ind] = []
        if i>1 and img[i-1,j]!=0:
            dct[ind].append(indMat[i-1,j])
        if i+1<m and img[i+1, j]!=0:
            dct[ind].append(indMat[i+1,j])
        if j > 1 and img[i,j-1]!=0:
            dct[ind].append(indMat[i, j-1])
        if j+1 < n and img[i, j+1] != 0:
            dct[ind].append(indMat[i, j+1])
    return dct

在得到编号映射字典之后,需要将其归一化,就是把类似a:[b,c]和]c:[d,e]合并为a:[b,c,d,e]。当所有编号都已经归类之后,还可以继续将其变为[a,b,c,d,e]实现如下

from copy import deepcopy
def mergeKey(dct, key):
    keys = [key]
    st, ed = 0, 1
    while len(keys)>0:
        for i in range(st, ed):
            k = keys[i]
            if k in dct:
                keys += dct[k]
                del dct[k]
        if ed == len(keys):
            break
        st, ed = ed, len(keys)
    return keys

def uniqueDct(dct):
    uDct = deepcopy(dct)
    for k in dct:
        if k in uDct:
            uDct[k] = list(set(mergeKey(uDct, k)))
    return [list(set([k]+v)) for k,v in uDct.items()]

最后,将其重新赋值,由于编号矩阵是按照自然数列的顺序创建的,故而只需先把图像展平,就可以通过编号矩阵的索引直接对图像的某些区域重新赋值。

def cds(img):
    dct = getIndDct(img)
    lst = uniqueDct(dct)
    arr = img.reshape(-1)*0
    for i,L in enumerate(lst, 1):
        arr[L] = i
    return arr.reshape(img.shape)

测试

接下来,将这个连通域算法应用到硬币图像上,由于上面的硬币图案有很多噪声,会影响连通域计算结果,所以先对其进行预处理

from scipy.ndimage import binary_erosion

b = img>0.4
bb = binary_erosion(b, np.ones([5,5]))
c = cds(bb)
drawImg(img, c, 'gray', 'jet')

效果如下

到此这篇关于Python实现连通域标记算法的文章就介绍到这了,更多相关Python连通域标记内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Jupyter Notebook/VSCode导出PDF中文不显示的解决

    Jupyter Notebook/VSCode导出PDF中文不显示的解决

    这篇文章主要介绍了Jupyter Notebook/VSCode导出PDF中文不显示的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Python实现把类当做字典来访问

    Python实现把类当做字典来访问

    今天小编就为大家分享一篇Python实现把类当做字典来访问,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • python3中pip3安装出错,找不到SSL的解决方式

    python3中pip3安装出错,找不到SSL的解决方式

    今天小编就为大家分享一篇python3中pip3安装出错,找不到SSL的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • Python 正则表达式从入门到实战(看完就能直接用在项目里)

    Python 正则表达式从入门到实战(看完就能直接用在项目里)

    本文介绍了Python正则表达式的基本概念、核心模块re及其常用方法match、search、findall,详细讲解了正则表达式基础语法、分组与分组引用、贪婪与非贪婪模式、修饰符等高级特性,并提供了一些实战案例,感兴趣的朋友跟随小编一起看看吧
    2026-04-04
  • Django使用paginator插件实现翻页功能的实例

    Django使用paginator插件实现翻页功能的实例

    今天小编就为大家分享一篇关于Django使用paginator插件实现翻页功能的实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • 简单介绍Python的第三方库yaml

    简单介绍Python的第三方库yaml

    今天给大家带来的是关于Python的相关知识,文章围绕着Python的第三方库yaml展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Python中的Dunder方法实现小结

    Python中的Dunder方法实现小结

    本文主要介绍了Python中的Dunder方法实现小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • Python如使用正则表达式匹配提取文章日期

    Python如使用正则表达式匹配提取文章日期

    在处理文本数据时,从文章中提取日期信息是一个常见需求,本文将详细介绍如何使用正则表达式匹配各种常见日期格式,并提供可复用的代码示例,希望对大家有所帮助
    2026-04-04
  • Python使用ConfigParser解析INI配置文件的完全指南

    Python使用ConfigParser解析INI配置文件的完全指南

    配置文件提供了一种结构化的方式来管理应用程序设置,比单独使用环境变量更有组织性,INI文件采用简单的基于部分的格式,既易于阅读又易于解析,Python内置的configparser模块使处理这些文件变得简单而强大,需要的朋友可以参考下
    2025-10-10
  • pytorch加载的cifar10数据集过程详解

    pytorch加载的cifar10数据集过程详解

    这篇文章主要介绍了pytorch加载的cifar10数据集,到底有没有经过归一化,本文对这一问题给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11

最新评论