Python中连通域分割Two-Pass算法的原理与实现详解

 更新时间:2023年12月25日 11:49:34   作者:微小冷  
两遍扫描法( Two-Pass ),正如其名,指的就是通过扫描两遍图像,将图像中存在的所有连通域找出并标记,本文将详细介绍Two-Pass算法的原理与实现,需要的可以参考下

连通域Two-Pass算法

在没有任何先验知识的情况下,想完成连通域的搜索,几乎最直接的想法,就是遍历图像所有像素点,如果两个像素点相连接,便将二者视为一体,直到遍历所有的像素。但这种遍历在遇到类似下面的图像时就会出现问题。

上面的矩阵中,数字代表有效像素,如果扫描顺序是从左向右,从上到下,那么在扫描第二行时,2并不和1联通,3尽管和1,2均联通,但只能赋予1个编号,从而上面的情况最终标记如下

所以,原本属于一个连通域的3个像素点,被分为1,3和2两个区域,所以需要再去遍历一次,把相邻的不同编号统一,这就是Two-Pass算法的基本思想。

数据准备

在具体实现算法之前,先准备一张二值图像,并封装一个绘图函数。

import matplotlib.pyplot as plt
from scipy.ndimage import binary_erosion
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>0.4

def drawImg(im1, im2, c1='jet', c2='jet'):
    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()

b = img>0.4
bb = binary_erosion(b, np.ones([5,5]))

第一次

第一次扫描的目的是建立当前像素与左边和上边的像素之间的联通关系,同时需要一个字典保存这种映射,为后续的连通域合并做准备。

def firstPass(inImg):
    L = 0       # 标记号
    outImg = inImg.astype(float)
    h, w = inImg.shape
    dct = {}
    for i,j in product(range(h), range(w)):
        if inImg[i,j] == 0:
            continue
        neighbors = []   # 记录符合要求的邻域前景
        if i-1> 0 and inImg[i-1, j]>0:
            neighbors.append(outImg[i-1, j])
        if j-1 > 0 and inImg[i, j-1] > 0:
            neighbors.append(outImg[i, j-1])
        if len(neighbors) == 0:
            L += 1
            outImg[i,j] = L
            dct[L] = [[i],[j]]
        else:
            tmpL = min(neighbors)
            outImg[i,j] = tmpL
            dct[tmpL][0].append(i)
            dct[tmpL][1].append(j)
    return outImg, dct

实验效果如下

c1, d = firtPass(bb)
drawImg(bb, c1)

第二次

第二次扫描的目的是,将属于同一连通域,但编号不同的区域,赋予相同的序号。为此 ,需要再次遍历图像,并通过第一次遍历得到的映射字典,来完成连通域的合并。

def secondPass(outImg, dct):
    outImg = outImg * 1
    print('version')
    for i,j in zip(*np.where(outImg!=0)):
        Ls = [outImg[i,j]]
        if i-1>0 and outImg[i-1,j] != 0:
            Ls.append(outImg[i-1,j])
        if j-1 > 0 and outImg[i, j-1] != 0:
            Ls.append(outImg[i, j-1])
        Ls = np.unique(Ls)
        if len(Ls)<2:
            continue
        minL = np.min(Ls)
        for L in Ls:
            if L == minL:
                continue
            y,x = dct[L]
            outImg[y,x] = minL
            dct[minL][0].extend(dct[L][0])
            dct[minL][1].extend(dct[L][1])
            del dct[L]
    u = np.unique(outImg)
    u = np.sort(u)  # 排序
    N = len(u) - 1  # 此为图标数
    for i in range(1, N+1):
        outImg[outImg==u[i]] = i
    N = len(np.unique(outImg))
    return N, outImg

效果如下

n, c2 = secondPass(c1, d)
drawImg(c1, c2)

到此这篇关于Python中连通域分割Two-Pass算法的原理与实现详解的文章就介绍到这了,更多相关Python连通域分割内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python的信号库Blinker用法详解

    Python的信号库Blinker用法详解

    在本篇文章里小编给大家整理了一篇关于Python的信号库Blinker用法详解内容,有兴趣的朋友们可以学习下。
    2020-12-12
  • Django 对象关系映射(ORM)源码详解

    Django 对象关系映射(ORM)源码详解

    这篇文章主要介绍了Django 对象关系映射(ORM)源码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • Python基于回溯法子集树模板解决全排列问题示例

    Python基于回溯法子集树模板解决全排列问题示例

    这篇文章主要介绍了Python基于回溯法子集树模板解决全排列问题,简单描述了全排列问题并结合实例形式分析了Python使用回溯法子集树模板解决全排列问题的具体步骤与相关操作注意事项,需要的朋友可以参考下
    2017-09-09
  • python如何实现常用的五种排序算法详解

    python如何实现常用的五种排序算法详解

    排序有很多种实现方法,比如冒泡排序、选择排序、归并排序、希尔排序、快速排序、插入排序、堆排序、基数排序等,这篇文章主要给大家介绍了关于python如何实现常用的五种排序算法,需要的朋友可以参考下
    2021-08-08
  • python算法加密 pyarmor与docker

    python算法加密 pyarmor与docker

    这篇文章主要介绍了python算法加密 pyarmor与docker,,PyArmor 是一个用于加密和保护 Python 脚本的工具。它能够在运行时刻保护 Python脚本的二进制代码不被泄露,设置加密后Python源代码的有效期限,绑 定加密后的Python源代码到硬盘、网卡等硬件设备
    2022-06-06
  • python使用循环实现批量创建文件夹示例

    python使用循环实现批量创建文件夹示例

    这篇文章主要介绍了python使用循环实现批量创建文件夹示例,需要的朋友可以参考下
    2014-03-03
  • Pytest自动化测试的具体使用

    Pytest自动化测试的具体使用

    Pytest是一个Python的自动化测试框架,它可用于编写单元测试、功能测试、集成测试和端到端测试,本文就来介绍一下Pytest自动化测试的具体使用,感兴趣的可以了解一下
    2024-01-01
  • Python两个字典键同值相加的几种方法

    Python两个字典键同值相加的几种方法

    今天小编就为大家分享一篇关于Python两个字典键同值相加的几种方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Pyinstaller将py打包成exe的实例

    Pyinstaller将py打包成exe的实例

    下面小编就为大家分享一篇Pyinstaller将py打包成exe的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Python一行代码实现生成和读取二维码

    Python一行代码实现生成和读取二维码

    二维码被称为快速响应码,可能看起来很简单,但它们能够存储大量数据。无论扫描二维码时包含多少数据,用户都可以立即访问信息。本文将用一行Python代码实现二维码的读取与生成,需要的可以参考一下
    2022-02-02

最新评论