分水岭算法 matlab实现

分水岭算法 matlab实现背景     做图像分割的时候用到了,就学习了一下大概思想     把图像中的像素大小理解成山地的海拔,向山地灌水,海拔低的地方会积水,这些地方称之为谷底。随着水位上升,不同谷底的水会相遇,相遇的地方就是分水岭。    &nbs

大家好,又见面了,我是你们的朋友全栈君。

背景

          做图像分割的时候用到了,就学习了一下

大概思想

          把图像中的像素大小理解成山地的海拔,向山地灌水,海拔低的地方会积水,这些地方称之为谷底。随着水位上升,不同谷底的水会相遇,相遇的地方就是分水岭。

          总体上是按照给每个点贴标签的方法实现的对每个在谷底的点贴上从1开始的不同的标签,同一个谷底标签相同。给分水岭贴上0的标签。未贴标签的点标为-1,其实就是初始化的时候全部-1。

  • 1、将图像中的每个像素按像素值大小排好顺序。
  • 2、从较小的像素值开始进行处理。
  • 3、搜索统计当前点周围像素(8邻域,边界的话就少几个像素点)中标签的种类,
  •           a、如果只有一种标签,为该点贴上相同的标签;
  •           b、 如果有2种及以上的标签,认为该点为分水岭。
  •           c、如果没有标签(-1没处理过)或只存在0(分水岭),搜索当前点的连通区域,,这儿可能会出现两种情况
  •                 (1)、当前点的连通域和之前处理过的接通了,如果是这样的话呢,把当前点的连通区域标记为和他连通的区域中较小的编号
  •                 (2)、当前点的连通域没有连通,那么当前点就把认为该点为新的谷底,谷底数加一,并把当前点的连通域都标记为新的谷底编号

流程框图

在这里插入图片描述

在这里插入图片描述

代码

          data 是一个图片的灰度值矩阵

clear all 
clc

load data
picture = data;
[row,col] = size(picture);   % 获得图片尺寸
watershed_result = -ones(row,col);  % 将结果矩阵全部赋值为-1表示所有点都未处理过

valley_number = 0; % 谷底数为0
tic
[picture_value, picture_index] = sort(picture(:)); % 将图片中所有元素按像素值大小排序
toc
total_pixel_number = row*col;  % 总元素个数

tic
for now_index = 1:total_pixel_number   % 对每个像素都要处理

    if watershed_result(picture_index(now_index)) ~= -1  % 如果标记为处理过跳过该像素
        continue;
    end
    
    now_picture_index = picture_index(now_index);     % 正在处理的像素的位置
    now_picture_value = picture(now_picture_index);   % 正在处理的像素的像素值

    vector_now_pixel_neighbor = neighbor_find_C(row,col,now_picture_index); % 获取当前像素点的周围8个像素点的位置

    temp_vector = sort(watershed_result(vector_now_pixel_neighbor));%获取周围像素点的标签
    temp_vector = unique(temp_vector);
    temp_vector = temp_vector(temp_vector>0);  %除了-10的标签种类
    temp_vector_length = length(temp_vector); 
    if temp_vector_length == 0  %种类为0
        is_same_area_index = zeros(2*col+2*row,1,'double');%和处理点像素值相同的连通区域
        is_same_area_index(1) = now_picture_index;
        area_num = 1;%连通区域的像素个数
        while(1)   %获得和处理点像素值相同的连通区域
            %获取联通区域的周围像素点的位置          
            is_same_area_neighbor_index = area_neighbor_find_C(row,col,is_same_area_index(1:area_num));
            
            %获取联通区域的周围像素点像素值大小和当前点像素值大小相同的点的像素值
            temp_vector = is_same_area_neighbor_index(picture(is_same_area_neighbor_index) == now_picture_value);
            temp_vector_length = length(temp_vector);
            if temp_vector_length == 0
                break;
            end
            is_same_area_index(area_num+1:area_num+temp_vector_length) = temp_vector;
            area_num = area_num + temp_vector_length;
            is_same_area_index = is_same_area_index(is_same_area_index>0);
        end

        temp_vector = sort(watershed_result(is_same_area_neighbor_index));%获取连通区域周围像素点的标签
        temp_vector = unique(temp_vector);
        temp_vector = temp_vector(temp_vector>0);
        temp_vector_length = length(temp_vector);%除了-10的标签种类
        if temp_vector_length == 0%种类为0
            valley_number = valley_number+1;%谷底数加1
            watershed_result(is_same_area_index(is_same_area_index>0)) = valley_number;%认为该连通区域为一个新的谷底
        else 
            watershed_result(now_picture_index) = temp_vector(1);%否则该点贴与之相邻的标签中除-10外较小的标签
        end
    else if temp_vector_length == 1      % 相邻8个像素中标签种类除-10还有1watershed_result(now_picture_index) = temp_vector(1);               % 该像素点贴相同标签
        else                             % 相邻8个像素中标签种类除-101个以上
            watershed_result(now_picture_index) = 0;                            % 认为该点为分水岭
        end
    end
end
toc
figure,imshow(watershed_result);%输出分水岭

用到的两个函数

          neighbor_find_C.m

function vector_neighbor_C = neighbor_find_C(row,col,nn)
total_number=row*col;
now_col= floor(nn/row)+1;
temp=rem(nn,row);
if temp==0
    now_row=row;
else
    now_row=temp;
end
if nn==1
    vector_neighbor_C=[2;row+1;row+2];
else if nn==row
    vector_neighbor_C=[row;row+row;row+row-1];
    else if nn==total_number-row+1
            vector_neighbor_C=[total_number-row+2;total_number-row-row;total_number-row-row+1];
        else if nn==total_number
                vector_neighbor_C=[total_number-1;total_number-row;total_number-row-1];
            else if now_row==1
                    vector_neighbor_C=[nn+row;nn-row;nn+1;nn+row+1;nn-row+1];
                else if now_row==row
                        vector_neighbor_C=[nn+row;nn-row;nn-1;nn+row-1;nn-row-1];
                    else if now_col==1
                            vector_neighbor_C=[nn+1;nn-1;nn+row;nn+row+1;nn+row-1];
                        else if now_col==col
                                vector_neighbor_C=[nn+1;nn-1;nn-row;nn-row+1;nn-row-1];
                            else
                                vector_neighbor_C=[nn+1;nn-1;nn-row;nn+row;nn-row+1;nn-row-1;nn+row+1;nn+row-1];
                            end
                        end
                    end
                end
            end
        end
    end
end

          area_neighbor_find_C.m

function vector_neighbor = area_neighbor_find_C(row,col,area_index)
I = zeros(row,col);
se=ones(3);
I(area_index) = 1;
I2 = imfilter(I,se);  % 滤波
I2=I2-I.*9;
vector_neighbor = find(I2>0);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149690.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • PLSQL来Oracle创建表空间和创建用户

    PLSQL来Oracle创建表空间和创建用户//创建临时表空间createtemporarytablespacetest_temptempfile’E:/oracle/product/10.2.0/oradata/testserver/test_temp01.dbf’size32mautoextendonnext32mmaxsize2048mextentmanagementlocal;

    2022年7月27日
    3
  • 使用socks4 socks5 http代理的客户端

    使用socks4 socks5 http代理的客户端///定义的结构structsock4req1{   charVN;   charCD;   unsignedshortPort;   unsignedlongIPAddr;   charother[1];};structsock4ans1{   charVN;   charCD;};structsock5req1{   charVer;   char

    2022年6月26日
    31
  • matlab如何做正交多项式曲线拟合,matlab正交多项式拟合

    matlab如何做正交多项式曲线拟合,matlab正交多项式拟合在实验模态分析中用Matlab实现离散化正交多项式算法[C],马永列;陈章位;胡海清4.在实验模态分析中用Matlab实现离散化正交多项式算法[C],马永列……变换后的条件数上限表如下:拟合次数1=1cond2(A)2<9.93<50.34<435④在实际应用中还可以利用正交多项式求拟合多项式。一种方法是构造离散……..

    2025年5月24日
    0
  • java学习——Java 动态代理机制分析

    越学越觉得自己不懂的越多!java的动态代理学习资料整理:Java 动态代理机制分析及扩展,第 1 部分: https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/Java 动态代理作用是什么? https://www.zhihu.com/question/20794107Java动态代理机制详解(JDK 和CGLIB,Javassist,A

    2022年2月26日
    32
  • SpringBoot自动配置的原理及实现

    SpringBoot自动配置的原理及实现SpringBoot自动配置的实现原理SpringBoot的核心就是自动配置,自动配置又是基于条件判断来配置Bean。关于自动配置的源码在spring-boot-autoconfigure-2.0.3.RELEASE.jar回顾配置属性在通常需要我们在property中配置信息时,通常使用@ConfigurationProperties(pefix=“前缀”)注解的方式从配置文件中获取配置…

    2022年5月5日
    37
  • 数据库常见面试题(附答案)

    数据库常见面试题(附答案)1.事务四大特性原子性,要么执行,要么不执行隔离性,所有操作全部执行完以前,其它会话不能看到过程一致性,事务前后,数据总额一致持久性,一旦事务提交,对数据的改变就是永久的2.数据库隔离级别,每个级别会引发什么问题,mysql默认是哪个级别脏读:事务B读取事务A还没有提交的数据不可重复读:两次事务读的数据不一致幻读:事务A修改了数据,事务B也修改了数据,这时在事务A看

    2022年5月2日
    73

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号