分水岭算法 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);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • getopt在Python中的使用

    getopt在Python中的使用在运行程序时,可能需要根据不同的条件,输入不同的命令行选项来实现不同的功能。目前有短选项和长选项两种格式。短选项格式为”-“加上单个字母选项;长选项为”–“加上一个单词。长格式是在Linux下引入的。许多Linux程序都支持这两种格式。在Python中提供了getopt模块很好的实现了对这两种用法的支持,而且使用简单。取得命令行参数  在使用之前,首先要取得命令行参数。使用sys模块

  • 如何将excel表格导入mysql数据库_MySQL数据库

    如何将excel表格导入mysql数据库_MySQL数据库怎么把excel里的数据导入数据库中的表中打开企业管理器开要导入数数据库,在表上按右键,所务–>导入数据,弹出DTS导入/导出向导,按下一步,2、选择数据源MicrosoftExcel97-2000,文件名选择要导入的xls文件,按下一步,3、选择目的用于SQLServer的MicrosoftOLEDB提供程序,服务器选择本地(如果是本地数据库的话,如VVV…

  • C# 匿名方法和拉姆达表达式「建议收藏」

    C# 匿名方法和拉姆达表达式「建议收藏」“`“`代码如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespace拉姆拉表达式{///

    ///C#匿名方法和拉姆达表达

  • 伪代码书写规则_伪代码及其实例讲解

    伪代码书写规则_伪代码及其实例讲解伪代码书写规则输入缩进变量数组选择结构循环结构返回值注释大小写最近要用到伪代码写算法,所以在网上查阅了一些资料,写这篇博客正好整理、记录一下自己所学的书写规则,以便自己日后使用,如果能对大家有所帮助,那就更好了。文中不足,欢迎给位大神多多指点。输入赋值语句用符号←表示,x←exp表示将exp的值赋给x,其中x是一个变量,exp是一个与x同类型的变量或表达式(该表达式的结果与x同类型);多重赋…

    2022年10月24日
  • amule的服务器列表

    amule的服务器列表

  • [GBA ROM列表]不断补完中……

    [GBA ROM列表]不断补完中……出处:http://www.ezflash.cn/vbb/showthread.php?s=3a42901b8c2aacb56a02e61f690b8a05&threadid=14&perpage=15&pagenumber=10001-F-Zero(J)(最高时速)(J)RCG320002-SuperMarioAdvance(J)(超级马里奥A)(J)ACT32000

发表回复

您的电子邮箱地址不会被公开。

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