三维种子点生长算法(以及Python递归深度问题)

news2025/1/23 17:35:25

前言

种子点生长算法是从一个种子点向周围的遍历图像的每个像素的图遍历算法。
通常在二维中有8邻域方法,三维中有6邻域与26邻域方法。
本文实现了三维种子点生长的6邻域算法。
种子点生长算法本质上是对图像的连通部分进行遍历,因此可以分别利用深度优先搜索与广度优先搜索的图遍历算法实现。
其中,深度优先搜索算法应用了递归的技术,当三维图形较大的时候,随着递归层数的加深,计算机堆栈区内存不足会导致程序无法继续,因此对于大的三维图形建议采用广度优先搜索算法。
两种算法的都是高效的图遍历算法,都可以实现O(n)时间的遍历。
在这里插入图片描述

Python的递归问题

Python默认的递归深度是1000层,当三维矩阵较大时,1000层肯定是不够的,使用如下代码可以设置递归层数限制:

import sys  #引入系统模块
sys.setrecursionlimit(3000) #设置为3000层

如果程序运行到限制的递归层数时,会出现下面情况:
在这里插入图片描述

RecursionError: maximum recursion depth exceeded in comparison

出现上面情况的时候,我们可以通过将限制递归层数的值调大。
但是递归层数也不是可以无限大的,当递归使用的堆栈区内存达到最大时,会出现以下情况。
使用Spyder运行程序时,如果递归层数太深导致计算机堆栈区内存不足,会出现以下情况:
在这里插入图片描述

Restarting kernel... 
[SpyderKernelApp] WARNING | No such comm: 27435501f4ff11ebaedb1208b1daf499

如果堆栈区的内存缺的不多的时候,可以不使用Spyder等IDE执行程序,建议使用CMD直接执行程序。

在这里插入图片描述
在这里插入图片描述

三维种子点生长算法

本实现的输入是一个给定的三维二值图像的矩阵,即只有0,1值的三维矩阵(0代表黑色,1代表白色)。输出是从一个白色的生长点周围寻找到的同为白色的连通区域中的所有点坐标。
定义的生长规则为,每次从当前生长点的上下左右前后6个相邻点中查看,如果相邻点中有白色(1)那就也搜索相邻白色点的邻域,以此类推。

深度优先搜索算法

在这里插入图片描述
在这里插入图片描述

算法实现

伪代码:

FloodFill(P,bitmap,replaceColor,targetColor)
  foreach point T in Adj(P)
      if color at T is equal to targetColor
      set color at T to replaceColor
      FloodFill(T,bitmap,replaceColor,targetColor)
  end

Python代码:

def FloodFill(P,figure,target_pos,targetcolor): 
    # function: the algorithm of grow
    # input: P is growing point (type is tuple)
    #        figure is 3D picture matrix (type is numpy.ndarray)
    #        target_pos is a set of position which we need
    #        targetcolor is the value of color which we want (type is int)
    # output: None
    x,y,z = P
    adj = [] #邻域列表
    # 如果在边界上,则不能越界添加邻域
    if x>0:
        adj.append((x-1,y,z))
    if x<L-1:
        adj.append((x+1,y,z))
    if y>0:
        adj.append((x,y-1,z))
    if y<W-1:
        adj.append((x,y+1,z))
    if z>0:
        adj.append((x,y,z-1))
    if z<H-1:
        adj.append((x,y,z+1))
        
    for xn,yn,zn in adj:# 六邻域
        if (xn,yn,zn) not in target_pos:# 属于邻域且未遍历过
            if figure[xn][yn][zn] == targetcolor: #如果该点为目标值,将该邻近点加入集合中,并且递归调用
                target_pos.add((xn,yn,zn))
                FloodFill((xn,yn,zn),figure,target_pos,targetcolor)
        

输出所有目标点到.txt文件:

with open('target_pos.txt','w') as f:
    for x in target_set:
        for s in x:
            f.write(str(s))
            f.write(" ")
        f.write('\n')

广度优先搜索算法

在这里插入图片描述
在这里插入图片描述

算法实现

伪代码:

FloodFill(seed,bitmap,replaceColor)
    get targetColor from bitmap using seed position
    set color at seed point to replaceColor
    set queue Q to empty
    push seed into Q
    while Q is not empty
        pop a point P from Q
        foreach point T in Adj(P)
            if color at T is equal to targetColor
                set color at T to replaceColor
                push T into Q
    end 

下面的代码稍微做了一些改动,主要是添加了一个edge与感知集sense,目的是当一个图像中有一个非封闭的连通区域,但是这个区域与外界的连通部分(开口)很小时,我们希望程序不遍历该连通区域外部的区域。
那么这个开口大小如何定义呢,如果我们认为这个开口很大,那么edge应该设置的较大,如果我们认为这个开口很小,那么edge应该设置的小一些。

def FloodFill(P,figure,target_pos,targetcolor):
    # function: the algorithm of grow
    # input: P is growing point (type is tuple) 
    #        figure is 3D picture matrix (type is numpy.ndarray)
    #        target_pos is a set of position which we need
    #        targetcolor is the value of color which we want (type is int)
    # output: None
    
    Q = collections.deque()  # 建立一个双边队列
    Q.append(P) # 添加队列元素
    
    while Q: # 当Q队列不为空时
        seed = Q.popleft() #弹出种子
        x,y,z = seed  #种子
        sense = set() # 感知集
        
        # 搜索到距离边界的edge范围就放弃搜索
        edge = 3
        if x<edge: 
            continue
        if x>L-edge-1: # 要注意到python中索引从0开始,那么长度为N的矩阵,末端的长度索引是N-1
            continue
        if y<edge:
            continue
        if y>W-edge-1:
            continue
        if z<edge:
            continue
        if z>H-edge-1:
            continue
        
        for i in range(-edge,edge+1):  #遍历以xyz为原点,半径为edge的范围  (edge*2+1)^3的方块
            for j in range(-edge,edge+1): # 要注意到range(0,2)会生成0,1两个数,没有2,python中的0:2也是这样,口诀:顾头不顾尾
                for p in range(-edge,edge+1):
                        sense.add(figure[x+i,y+j,z+p])  #将遍历得到的值加入集合,利用集合的去重特性,可以减少内存占用
        if 0 in sense:  #如果感知到黑色(0) 
            continue  #当前点周围不再查找,直接开始下一轮循环

        # 六邻域
        adj = [(x-1,y,z),(x+1,y,z),(x,y-1,z),(x,y+1,z),(x,y,z-1),(x,y,z+1)] #邻域列表
            
        for xn,yn,zn in adj:  #对于所有的邻域点
            if (xn,yn,zn) not in target_pos: # 该点已经在目标点集合
                if figure[xn][yn][zn] == targetcolor: #如果该点为目标值,将该邻近点加入集合中,并且递归调用
                    target_pos.add((xn,yn,zn)) # 该点添加到目标点集合
                    Q.append((xn,yn,zn)) # 将该点作为生长点加入队列

输出.txt文件:

with open('target_pos.txt','w') as f:  #打开文件  下次跑这段代码会覆盖上次跑这段代码生成的txt文件(因为没用调为追加写入形式,我们需要的正是覆盖所以不用动)
    for x in target_set:  # 遍历目标点集合所有点
        for s in x: #遍历点元组(x,y,z)中的每个值
            f.write(str(s)) # 将其转化为字符形式,写入文件,只能写字符数据类型
            f.write(" ") #用空格隔开
        f.write('\n') #不同点用回车隔开

参考资料

https://www.cnblogs.com/chnhideyoshi/p/SeedGrow2d.html
https://www.itdaan.com/blog/2016/05/17/84e0a189821d.html
在这里插入图片描述

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

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

相关文章

spring initializr脚手架搭建详解

前段时间&#xff0c;我在「基于start.spring.io&#xff0c;我实现了Java脚手架定制」一文中讲述了敝司的微服务脚手架落地过程中的前世今生&#xff0c;并提到了基于 spring initializr 的搭建了 2.0 版本的脚手架。今天我打算和你分享一下这其中的实现过程与细节&#xff0c…

Vue3 如何实现一个全局搜索框

前言&#xff1a;自从学习 vue 以来&#xff0c;就对 vue 官网全局的 command K 调出全局关键词搜索这个功能心心念念。恰好最近项目也是需要实现一个全局搜索的功能&#xff0c;也正好可以正大光明的带薪学习这个功能的思路。网上的教程水平参差不齐&#xff0c;而恰好之前的…

qmake 与 配置文件

用qmake生成makefile的时候&#xff0c;背后会先执行一堆用qmake language编写的库文件&#xff08;配置文件&#xff09;&#xff0c;用于初始化一些环境相关的工作&#xff0c;为后续解析pro文件做准备。 下面是qmake解析一个新建的qt工程的pro文件背后所解析的配置文件的文件…

2022-11-27阿里云物联网平台 MICROPYTHON记录

之前写过EMQX在阿里云的云服务器上搭建流程&#xff0c;近期云服务器到期了&#xff0c;而且由于没有业务支撑短期也不打算再开云服务器了&#xff0c;但是物联网还是要用的&#xff0c;于是开了这个阿里云物联网的记录。 这个是比较详细的已有的博客记录 这个博客居然还有配套…

从ABNF读懂HTTP协议格式

定义 HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;超文本传输协议 HTML&#xff08; Hyper Text Markup Language&#xff09;超文本标记语言 URI&#xff08;Uniform Resource Identifier&#xff09;用于标识某一互联网资源名称的字符串&#xff08;uri 包括了…

自动控制原理1~3章课后练习题

1.适合于应用传递函数描述的系统是线性定常系统 2.某0型单位反馈系统的开环增益为K&#xff0c;则在 r(t)1/2*t^2 输入下&#xff0c;系统的稳态误差为 无穷 3.动态系统 0 初始条件是指 t<0 时系统的 输入、输出以及它们的各阶导数为 0 4.若二阶系统处于无阻尼状态&#…

毕业设计-opencv图像视频质量评价分析

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

二级域名配置以及nginx解析二级域名到html页面

此文章适合发布前端项目使用&#xff0c;如果想要配置二级域名到后端服务&#xff0c;可以查看这篇文章&#xff1a;nginx配置二级域名 - 简书 在阿里云上配置二级域名&#xff0c;就是添加一条记录就可以了&#xff0c;超级简单&#xff0c;不懂的可以看后面的解释说明&#…

05.深入理解JMM和Happens-Before

JMM都问啥&#xff1f; 最近沉迷P5R&#xff0c;所以写作的进度很不理想&#xff0c;但不得不说高卷杏YYDS。话不多说&#xff0c;开始今天的主题&#xff0c;JMM和Happens-Before。 关于它们的问题并不多&#xff0c;基本上只有两个&#xff1a; JMM是什么&#xff1f;详细…

[附源码]计算机毕业设计JAVA社团管理系统

[附源码]计算机毕业设计JAVA社团管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

c语言实现三子棋

目录 一、三子棋玩法 二、需要实现的游戏功能 三、拆分代码 3.1游戏菜单 3.2初始化棋盘 3.2.1函数调用 3.2.2函数体实现 3.3打印棋盘 3.3.1函数调用 3.3.2函数体实现 3.4玩家下棋 3.4.1函数调用 3.4.2函数体实现 3.4.3效果展示 3.5电脑下棋 3.5.1函数调用 3.5…

强大博客搭建全过程(1)-hexo博客搭建保姆级教程

1、 前言 本人本来使用国内的开源项目solo搭建了博客&#xff0c;但感觉1核CPU2G内存的服务器&#xff0c;还是稍微有点重&#xff0c;包括服务器内还搭建了数据库。如果自己开发然后搭建&#xff0c;耗费时间又比较多&#xff0c;于是乎开始寻找轻量型的博客系统。 此时hexo…

苹果系统(macos)code with me 控制端下载不下来,下载缓慢,解决办法

jetbrains的插件,依赖包,或者是工具之类的下载通常都比较慢,尤其是大文件等很久后可能还断开了.又要重头下.比如 code with me,以下简称cwm curl: (56) Recv failure: Connection reset by peer 如果你曾用sh安装时提示这个,多数就是网络连接不行了. 简单说就是用下载工具下…

redis集群搭建教程及遇到的问题处理

这里&#xff0c;在一个Linux虚拟机上搭建6个节点的redis伪集群&#xff0c;思路很简单&#xff0c;一台虚拟机上开启6个redis实例&#xff0c;每个redis实例有自己的端口。这样的话&#xff0c;相当于模拟出了6台机器了&#xff0c;然后在以这6个实例组建redis集群就可以了。 …

jsp旅行社管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 旅行社管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5 开发&#xff0c;数据库为Mysql&#xff0c;使用…

JAVA之Spring MVC 请求与响应 REST风格 SSM整合(注解版)

SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 使用简单&#xff0c;开发便捷&#xff08;相比于Servlet&#xff09; 灵活性强 入门案例 导入依赖SpringMVC坐标 <dependency><groupId>org.springframework</groupId><artifactId>spring-web…

[附源码]计算机毕业设计JAVA实践教学管理系统

[附源码]计算机毕业设计JAVA实践教学管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

01 使用docker搭建wordpress博客网站

文章目录1. 前言1.1 容器技术思维导图1.2 wordpress 网络架构图2. 拉取镜像3. 搭建博客网站3.1 启动MariaDB3.2 运行应用服务器 WordPress3.3 使用nginx 做反向代理3.4 检查容器状态4. 登录博客配置5 查看数据库1. 前言 基于之前学习kubernetes 比较乱&#xff0c;打算重新学习…

机器学习笔记 十九:由浅入深的随机森林模型之分类

随机森林学习内容1. 集成学习2.sklearn中的集成算法2.1 sklearn中的集成算法模块ensemble2.2 RandomForestClassifier2.2.1 参数2.2.2 n_estimators2.2.3 random_state2.2.4 bootstrap & oob_score2.3 随机森林的重要接口2.4 Bonus&#xff08;装袋法的必要条件&#xff09…

【指针详解】(上)看一遍就会❗❗❗家人们冲❗

前言 ❤️ 铁汁们大家好&#xff0c;欢迎大家来到出小月的博客里&#xff0c; &#x1f917;&#x1f917;&#x1f917;之前呢&#xff0c;我分享了C语言的小游戏“扫雷”。。。。今天呢&#xff0c;给大家分享指针篇&#xff0c;&#xff0c;希望大家看完我这篇文章都能够“涨…