watershed算法及vc实现

合集下载

分水岭算法(完整版)

分水岭算法(完整版)
分水岭分割算法的实现 与分析
青 衣
11053413 李小泷
• 分水岭算法实现步骤:先把图片转化为灰度梯度级图像, 在图像梯度空间内逐渐增加一个灰度阈值,每当它大于一 个局部极大值时,就把当时的二值图像(只区分陆地和水 域,即大于灰度阈值和小于灰度阈值两部分)与前一个时 刻(即灰度阈值上一个值的时刻)的二值图像进行逻辑异或 (XOR)操作,从而确定出灰度局部极大值的位置 。根据所 有灰度局部极大值的位置集合就可确定分水岭。
Lrgb = label2rgb(L, 'jet', 'w', 'shuffle');%转 化为伪彩色图像 subplot(122); imshow(Lrgb)%显示伪彩色图 像 title('分水岭伪彩色图像') 青 衣
figure; imshow(I), hold on himage = imshow(Lrgb);%在原图上显示 伪彩色图像 set(himage, 'AlphaData', 0.3); title('原图像上的Lrgb处理')
imcomplement(Iobr));%形态学重建 Iobrcbr = imcomplement(Iobrcbr);%图像求反 subplot(122); imshow(Iobrcbr), %显示重建求反后的 图像 title('重建求反后的图像(Iobrcbr)')
fgm = imregionalmax(Iobrcbr);%局部极大值 figure; imshow(fgm), %显示重建后局部极大值图像 title('重建后局部极大值图像(fgm)')
此时再进行分水岭变换并显示得到的效果。

python实现分水岭算法分割遥感图像

python实现分水岭算法分割遥感图像

python实现分⽔岭算法分割遥感图像1. 定义 分⽔岭算法(watershed algorithm)可以将图像中的边缘转化为“⼭脉”,将均匀区域转化为“⼭⾕”,在这⽅⾯有助于分割⽬标。

分⽔岭算法:是⼀种基于拓扑理论的数学形态学的分割⽅法。

把图像看作是测地学上的拓扑地貌,图像中的每⼀个点像素值的灰度值表⽰该点的海拔⾼度,每⼀个局部极⼩值及其影响的区域称为“集⽔盆”,集⽔盆的边界可以看成分⽔岭。

在每⼀个局部极⼩值表⾯刺穿⼀个⼩孔,然后把整个模型慢慢浸⼊⽔中,随着浸⼊的加深,每⼀个局部极⼩值的影响域慢慢的向外扩展,在两个集⽔盆汇合处构建⼤坝,形成分⽔岭。

迭代标注过程:1. 排序过程:对每个像素的灰度级进⾏从低到⾼的排序2. 淹没过程:对每⼀个局部最⼩值在h阶⾼度的影响域采⽤先进先出结构判断及标注。

2.实现算法:watershed()函数 这些标记的值可以使⽤findContours()函数和drawContours()函数由⼆进制的掩模检索出来3.程序代码:import numpy as npimport cv2from osgeo import gdal, gdal_arrayimport shapefiletry:import Imageimport ImageDrawexcept:from PIL import Image, ImageDrawdef tif_jpg(rasterfile):in_ds = gdal.Open(rasterfile) # 打开样本⽂件xsize = in_ds.RasterXSize # 获取⾏列数ysize = in_ds.RasterYSizebands = in_ds.RasterCountblock_data = in_ds.ReadAsArray(0, 0, xsize, ysize).astype(np.float32)B = block_data[0, :, :]G = block_data[ 1,:, :]R = block_data[2,:, :]R1 = (R/np.max(R)*255).astype(np.int16)G1 = (G / np.max(G) * 255).astype(np.int16)B1 = (B / np.max(B) * 255).astype(np.int16)data2 = cv2.merge([R1,G1,B1])return data2def watershed(path,out):print("分⽔岭分割")in_ds = gdal.Open(path) # 打开样本⽂件xsize = in_ds.RasterXSize # 获取⾏列数ysize = in_ds.RasterYSizebands = in_ds.RasterCountgeotransform = in_ds.GetGeoTransform()projection = in_ds.GetProjectionRef()#tif转jpg ⾮255通道转换为255通道img=tif_jpg(path).astype(np.uint8)# 转换为灰度图⽚gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# canny边缘检测函数返回⼀副⼆值图,其中包含检测出的边缘。

数字图像处理领域的二十四个典型算法和vc实现(I)

数字图像处理领域的二十四个典型算法和vc实现(I)

数字图像处理领域的二十四个典型算法及vc实现、第一章一、256色转灰度图二、Walsh变换三、二值化变换四、阈值变换五、傅立叶变换六、离散余弦变换数字图像处理领域的二十四个典型算法及vc实现、第二章七、高斯平滑八、图像平移九、图像缩放十、图像旋转数字图像处理领域的二十四个典型算法及vc实现、第三章图像处理,是对图像进行分析、加工、和处理,使其满足视觉、心理以及其他要求的技术。

图像处理是信号处理在图像域上的一个应用。

目前大多数的图像是以数字形式存储,因而图像处理很多情况下指数字图像处理。

本文接下来,简单粗略介绍下数字图像处理领域中的24个经典算法,然后全部算法用vc实现。

由于篇幅所限,只给出某一算法的主体代码。

ok,请细看。

一、256色转灰度图算法介绍(百度百科):什么叫灰度图?任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:1.浮点算法:Gray=R*0.3+G*0.59+B*0.112.整数方法:Gray=(R*30+G*59+B*11)/1003.移位方法:Gray =(R*28+G*151+B*77)>>8;4.平均值法:Gray=(R+G+B)/3;5.仅取绿色:Gray=G;通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。

灰度分为256阶。

所以,用灰度表示的图像称作灰度图。

程序实现:ok,知道了什么叫灰度图,下面,咱们就来实现此256色灰度图。

这个Convert256toGray(),即是将256色位图转化为灰度图:void Convert256toGray(HDIB hDIB){LPSTR lpDIB;// 由DIB句柄得到DIB指针并锁定DIBlpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);// 指向DIB象素数据区的指针LPSTR lpDIBBits;// 指向DIB象素的指针BYTE * lpSrc;// 图像宽度LONG lWidth;// 图像高度LONG lHeight;// 图像每行的字节数LONG lLineBytes;// 指向BITMAPINFO结构的指针(Win3.0)LPBITMAPINFO lpbmi;// 指向BITMAPCOREINFO结构的指针LPBITMAPCOREINFO lpbmc;// 获取指向BITMAPINFO结构的指针(Win3.0)lpbmi = (LPBITMAPINFO)lpDIB;// 获取指向BITMAPCOREINFO结构的指针lpbmc = (LPBITMAPCOREINFO)lpDIB;// 灰度映射表BYTE bMap[256];// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板 int i,j;for (i = 0; i < 256; i ++){// 计算该颜色对应的灰度值bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed + 0.587 * lpbmi->bmiColors[i].rgbGreen +0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);// 更新DIB调色板红色分量lpbmi->bmiColors[i].rgbRed = i;// 更新DIB调色板绿色分量lpbmi->bmiColors[i].rgbGreen = i;// 更新DIB调色板蓝色分量lpbmi->bmiColors[i].rgbBlue = i;// 更新DIB调色板保留位lpbmi->bmiColors[i].rgbReserved = 0;}// 找到DIB图像象素起始位置lpDIBBits = ::FindDIBBits(lpDIB);// 获取图像宽度lWidth = ::DIBWidth(lpDIB);// 获取图像高度lHeight = ::DIBHeight(lpDIB);// 计算图像每行的字节数lLineBytes = WIDTHBYTES(lWidth * 8);// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)//逐行扫描for(i = 0; i < lHeight; i++){//逐列扫描for(j = 0; j < lWidth; j++){// 指向DIB第i行,第j个象素的指针lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; // 变换*lpSrc = bMap[*lpSrc];}}//解除锁定::GlobalUnlock ((HGLOBAL)hDIB);}变换效果(以下若无特别说明,图示的右边部分都是为某一算法变换之后的效果):二、Walsh变换算法介绍:有关Walsh变换的深入介绍,请看此论文:.cn/doc/ucit200510/ucit.pdf 程序实现:函数名称:WALSH()参数:double * f - 指向时域值的指针double * F - 指向频域值的指针r -2的幂数返回值:无。

腐蚀膨胀算法原理

腐蚀膨胀算法原理

腐蚀膨胀算法原理
腐蚀膨胀算法(Erosion-DilationAlgorithm,缩写为EDA)是图像处理中最常用的算法之一。

它主要应用于图像的二值化处理,可以有效地消除图像中的噪声,以及实现图像中文字和物体的分割。

EDA是一种分水岭算法(Watershed Algorithm),该算法包括两个步骤,腐蚀和膨胀。

腐蚀步骤将从图像中提取图像对象的轮廓,而膨胀步骤将对象的轮廓填充,从而实现对图像对象的分割。

一般来说,EDA算法可以分为以下两步:
(1)腐蚀:腐蚀是图像处理中常用的技术,它的目的是去除图像中的噪声,消除图像中的噪点,并实现对图像中的文字或物体的轮廓提取。

腐蚀的基本原理是:使用一个结构元素(structuring element),它可以是不同类型的形状,如圆形、菱形、矩形等,将图像中某像素的非零元素替换为零。

(2)膨胀:膨胀是EDA算法中另一个重要的步骤,它是腐蚀的反向过程。

膨胀的基本原理是:使用一个结构元素将图像中某像素的零元素替换为非零元素,如果临近的像素是非零元素,则认为此像素属于某个对象的轮廓。

EDA算法的优点在于它既可以去除噪声,又可以实现文字或物体的分割。

此外,EDA算法还性能卓越,比一般算法要快得多,是图像处理中用到较多的算法之一。

但EDA算法也存在缺点:结构元素的选择不当,会影响到最终的结果;由于腐蚀操作的迭代,会导致目标图像的误差及失真问题;同
样,膨胀操作也会null影响图像的体积及精度。

总而言之,腐蚀膨胀算法是一种有效的图像处理算法,在图像的噪声消除、文字分割等应用中均有良好的效果,但也有一定的缺点,应该合理选择结构元素,以保证算法的正确性和最佳效果。

传统算法——分水岭算法

传统算法——分水岭算法

传统算法——分⽔岭算法分⽔岭算法是⼀种基于区域分割的算法。

它是基于地理形态的分析的图像分割算法,模仿地理结构(⽐如⼭川、沟壑,盆地)来实现对不同物体的分类。

封闭性是分⽔岭算法的⼀个重要特征图像的灰度空间很像地球表⾯的整个地理结构,每个像素的灰度值代表⾼度。

其中的灰度值较⼤的像素连成的线可以看做⼭脊,也就是分⽔岭。

其中的⽔就是⽤于⼆值化的gray threshold level,⼆值化阈值可以理解为⽔平⾯,⽐⽔平⾯低的区域会被淹没,刚开始⽤⽔填充每个孤⽴的⼭⾕(局部最⼩值)。

当⽔平⾯上升到⼀定⾼度时,⽔就会溢出当前⼭⾕,可以通过在分⽔岭上修⼤坝,从⽽避免两个⼭⾕的⽔汇集,这样图像就被分成2个像素集,⼀个是被⽔淹没的⼭⾕像素集,⼀个是分⽔岭线像素集。

最终这些⼤坝形成的线就对整个图像进⾏了分区,实现对图像的分割。

在该算法中,空间上相邻并且灰度值相近的像素被划分为⼀个区域。

分⽔岭算法的运⾏过程:1. 把梯度图像中的所有像素按照灰度值进⾏分类,并设定⼀个测地距离阈值。

2. 找到灰度值最⼩的像素点(默认标记为灰度值最低点),让threshold从最⼩值开始增长,这些点为起始点。

3. ⽔平⾯在增长的过程中,会碰到周围的邻域像素,测量这些像素到起始点(灰度值最低点)的测地距离,如果⼩于设定阈值,则将这些像素淹没,否则在这些像素上设置⼤坝,这样就对这些邻域像素进⾏了分类。

4. 随着⽔平⾯越来越⾼,会设置更多更⾼的⼤坝,直到灰度值的最⼤值,所有区域都在分⽔岭线上相遇,这些⼤坝就对整个图像像素的进⾏了分区。

⽤上⾯的算法对图像进⾏分⽔岭运算,由于噪声点或其它因素的⼲扰,可能会得到密密⿇⿇的⼩区域,即图像被分得太细(over-segmented,过度分割),这因为图像中有⾮常多的局部极⼩值点,每个点都会⾃成⼀个⼩区域。

其中的解决⽅法:1. 对图像进⾏⾼斯平滑操作,抹除很多⼩的最⼩值,这些⼩分区就会合并。

2. 不从最⼩值开始增长,可以将相对较⾼的灰度值像素作为起始点(需要⽤户⼿动标记),从标记处开始进⾏淹没,则很多⼩区域都会被合并为⼀个区域,这被称为基于图像标记(mark)的分⽔岭算法。

OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭算法(图文并茂+浅显易懂+程序源码)

OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭算法(图文并茂+浅显易懂+程序源码)

OpenCV开发笔记(五⼗九):红胖⼦8分钟带你深⼊了解分⽔岭算法(图⽂并茂+浅显易懂+程序源码)上⼀篇:《》下⼀篇:持续补充中…前⾔ 红胖⼦,来也! 做识别,有时候需求要识别物体,物体在背景上⽐较杂,但是其边缘与背景图相差⼤,这个时候可以使⽤分⽔岭算法突出两边的颜⾊对⽐度,从⽽更好的分割。

Demo分⽔岭算法概述 分⽔岭分割⽅法,是⼀种基于拓扑理论的数学形态学的分割⽅法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每⼀点像素的灰度值表⽰该点的海拔⾼度,每⼀个局部极⼩值及其影响区域称为集⽔盆,⽽集⽔盆的边界则形成分⽔岭。

简单来说就是根据图像相邻的像素差值,分成不同区域,将各区域染成不同颜⾊,其适合使⽤者已经可以标记已知对象或背景中的⼀部分。

 &emp;分⽔岭的概念和形成可以通过模拟浸⼊过程来说明。

在每⼀个局部极⼩值表⾯,刺穿⼀个⼩孔,然后把整个模型慢慢浸⼊⽔中,随着浸⼊的加深,每⼀个局部极⼩值的影响域慢慢向外扩展,在两个集⽔盆汇合处构筑⼤坝,即形成分⽔岭。

分⽔岭的计算过程是⼀个迭代标注过程。

原理 分⽔岭⽐较经典的计算⽅法是L. Vincent提出的。

在该算法中,分⽔岭计算分两个步骤,⼀个是排序过程,⼀个是淹没过程。

⾸先对每个像素的灰度级进⾏从低到⾼排序,然后在从低到⾼实现淹没过程中,对每⼀个局部极⼩值在h阶⾼度的影响域采⽤先进先出(FIFO)结构进⾏判断及标注。

分⽔岭变换得到的是输⼊图像的集⽔盆图像,集⽔盆之间的边界点,即为分⽔岭。

显然,分⽔岭表⽰的是输⼊图像极⼤值点。

因此,为得到图像的边缘信息,通常把梯度图像作为输⼊图像,即g(x,y)=grad(f(x,y))={[f(x,y)-f(x-1,y)]2[f(x,y)-f(x,y-1)]2}0.5式中,f(x,y)表⽰原始图像,grad{.}表⽰梯度运算。

分⽔岭算法对微弱边缘具有良好的响应,图像中的噪声、物体表⾯细微的灰度变化,都会产⽣过度分割的现象。

滑动窗口式三维Watershed算法实现视频序列分割

滑动窗口式三维Watershed算法实现视频序列分割
石荣;傅志中;李晓峰;李在铭
【期刊名称】《信号处理》
【年(卷),期】2004(020)002
【摘要】视频序列分割是实现视频对象提取、处理和识别的基础,也是基于内容的视频压缩和检索的前提.目前普遍采用的watershed算法是全局涨水算法,用于视频分割时占用的存储和处理空间巨大.针对这一问题本文提出了新的滑动窗口式三维watershed算法(SW3DW),通过时间轴上的局部窗口对视频序列进行观察和分割,而在相邻窗口间采用水源区标号传递和局部流域更新相结合的方法,以较小的存储和处理空间实现了局域和全局处理的一致性.理论分析和实验证明该算法能有效性地实现视频序列的分割,为后续视频对象提取和处理创造了条件.
【总页数】5页(P192-196)
【作者】石荣;傅志中;李晓峰;李在铭
【作者单位】电子科技大学通信与信息工程学院,成都,610054;电子科技大学通信与信息工程学院,成都,610054;电子科技大学通信与信息工程学院,成都,610054;电子科技大学通信与信息工程学院,成都,610054
【正文语种】中文
【中图分类】TP3
【相关文献】
1.在并行分布式图匹配方案中的分割算法实现 [J], 向珏良
2.基于Mean Shift的三维医学图像交互式分割方法 [J], 杨娟;陈兆学;姜雪;史梦雪
3.定子分割式轴向磁通切换混合励磁同步电机三维有限元分析与实验研究 [J], 刘细平;郑爱华;王晨
4.蜂窝状的交互式三维分割方法 [J], 李梭;孙健永;张建国
5.基于级联式三维卷积神经网络的肝肿瘤自动分割 [J], 李渊强; 吴宇雳; 杨孝平因版权原因,仅展示原文概要,查看原文内容请购买。

emgu分水岭算法计数

emgu分水岭算法计数摘要:一、分水岭算法简介1.分水岭算法的概念2.分水岭算法的应用场景二、emgu分水岭算法实现1.emgu库简介2.emgu分水岭算法原理3.emgu分水岭算法步骤三、emgu分水岭算法计数1.计数原理2.计数方法3.计数结果分析四、案例演示1.图像处理实例2.结果分析正文:【一、分水岭算法简介】分水岭算法(Watershed algorithm)是一种图像处理领域中的边缘检测和分割技术。

它的基本思想是寻找图像中像素之间的极值点,将这些极值点作为分水岭,将图像划分为不同的区域。

这种算法具有较好的适应性和稳定性,可以有效处理复杂场景下的图像分割问题。

【二、emgu分水岭算法实现】emgu(Emgu CV)是一个基于OpenCV的.NET库,提供了丰富的图像处理功能。

emgu分水岭算法实现了分水岭原理,并对算法进行了优化。

以下是emgu分水岭算法的基本步骤:1.对输入图像进行预处理,如滤波、去噪等。

2.计算图像的梯度幅值和方向。

3.寻找梯度幅值的最大值点和最小值点。

4.将最大值点和最小值点连接成边缘。

5.对边缘进行填充,得到分割后的图像。

【三、emgu分水岭算法计数】emgu分水岭算法计数是对分割后的图像中边缘像素进行统计的过程。

计数原理是根据边缘像素的颜色、纹理等特征,将其分为不同的类别。

以下是一种简单的计数方法:1.预处理:对分割后的图像进行去噪、平滑等操作,以消除边缘附近的噪声。

2.特征提取:从处理后的图像中提取边缘像素的特征,如颜色、纹理等。

3.分类:根据特征将边缘像素分为不同的类别。

可以使用机器学习方法(如SVM、神经网络等)进行分类。

4.计数:统计各个类别边缘像素的数量,得到最终的结果。

【四、案例演示】以下是一个使用emgu分水岭算法进行图像处理的实例:1.输入图像:一幅包含建筑物、道路、树木等元素的复杂场景图像。

2.使用emgu分水岭算法进行分割。

3.观察分割结果:可以发现,建筑物、道路和树木等元素得到了较好的分割。

数据结构课程VC商店选址短路径Floyd算法实现(含源代码)

2008/2009学年度第二学期《数据结构》课程设计说明书题目:商店选址问题班级:姓名:学号:指导教师:日期:2009-6-22~2009-6-26计算机与信息工程系1、问题描述2、需求分析3、开发环境4、算法设计思想5、流程图6、课程设计过程中的关键算法7、测试及结果测试数据:输入:单位个数、单位间的路径数、单位名称、相通两单位以及之间的距离、和各单位去商店的频率输出:相通两单位之间的路径和他的长度结果:8、总结与收获这次的程序软件基本上运行成功,可以简单的对已经输入的数据进行计算,求出商店的最佳选址单位。

但是程序较小,功能不全面,只是理论,并未实践。

同时,这次数据结构课程设计让我们感触很深,使我们每个人都了解到的学习不应该只局限于我们的课本,因为课本上告诉我们的只是很有限的一部分,所涉及的面也是狭窄的。

但是怎样在有限的范围内学习到无限的知识呢?那就要我们自己懂得竞争,懂得自学,懂得充分利用身边的任何资源。

应该说,我们在这次的课程设计中学到了很多知识,这并不仅仅包括书本上的知识,更重要的是我们学会了如何去和别人交流,怎样用语言去实现自己的想法,在这个过程中使我懂得了勤学好问的重要性。

虽然在我的程序中有一部分是从网上搜索得来的,但我竭力将所获得的信息变成自己的资源。

在我动手上机操作的同时,我在了解和看懂的基础上有所改变和创新,但是在我的程序软件中还有部分的不足,需要加以更新。

同时,通过这次课程设计,我们都意识到了自己动手实践的弱势,特别是在编程方面,于是我们知道了计算机的实践操作是很重要的,只有通过上机编程才能充分的了解自己的不足。

相信通过这次的课程设计,更让我深刻意识到自己在学习中的弱点,同时也找到了克服这些弱9、参考文献10、指导教师评语附件一:程序清单#include <string.h>#include <stdio.h>#include <time.h>#include "malloc.h"#include <iostream.h>#define TURE 1#define FALSE 0#define OK 1#define ERROR 0#define OVERFLOW -1#define INF 32767const int MAXVEX=100; typedef char Vextype; typedef struct{Vextype vexs[MAXVEX][MAXVEX]; //单位名称(顶点信息);int adj[MAXVEX][MAXVEX]; //单位之间的相通情况(是否有边);int dis[MAXVEX][MAXVEX]; //单位间距离(边的长度);int f[MAXVEX]; //各单位去商店的频率;int n; //顶点数和边数;int e;}Mgraph;void CreatMgraph(Mgraph *G){int i,j,k;printf("请输入单位个数:\n");scanf("%d",&(G->n));printf("请输入单位间的路径数:\n");scanf("%d",&(G->e));printf("请输入单位名称:\n");for(i=0;i<G->n;i++){printf("请输入第%d个单位名称:\n",i);scanf("%s",&G->vexs[i]);}for(i=0;i<G->n;i++) //结构体的初始化;for(j=0;j<G->n;j++){G->adj[i][j]=0;G->dis[i][j]=0;G->f[i]=0;}for(k=0;k<G->e;k++){printf("请输入相通的两单位 (输入格式:i,j):\n");scanf("%d,%d",&i,&j);//在距离上体现为无向;printf("请输入相同两个单位间的距离(格式:dis):\n");scanf("%d",&(G->dis[i][j]));G->adj[i][j]=1;G->adj[j][i]=1;G->dis[j][i]=G->dis[i][j];}for(k=0;k<G->n;k++){printf("请输入第%d个单位去商店的相对频率:\n",k);scanf("%d",&(G->f[k]));}for(i=0;i<G->n;i++) //以距离和频率之积作为权值;for(j=0;j<G->n;j++){G->dis[i][j]*=G->f[i]; //最终权值非完全无向;if(G->adj[i][j]==0&&i!=j)G->dis[i][j]=INF;}}void Floyed(Mgraph *G) //带权有向图求最短路径floyd算法{int A[MAXVEX][MAXVEX],path[MAXVEX][MAXVEX];int i,j,k,pre;int count[MAXVEX];for(i=0;i<G->n;i++) //初始化A[][]和path[][]数组for(j=0;j<G->n;j++) //置初值;{A[i][j]=G->dis[i][j];path[i][j]=-1;count[i]=0;}for(k=0;k<G->n;k++) //k代表运算步骤{for(i=0;i<G->n;i++)for(j=0;j<G->n;j++)if(A[i][j]>(A[i][k]+A[k][j])) //从i经j到k的一条路径更短{A[i][j]=A[i][k]+A[k][j];path[i][j]=k;}}cout<<endl<<"Floyed算法求解如下:"<<endl;for(i=0;i<G->n;i++)for(j=0;j<G->n;j++){if(i!=j){cout<<" "<<i<<"->"<<j<<";";if(A[i][j]==INF){if(i!=j)cout<<"不存在路径"<<"\n"<<endl;}else{cout<<"路径长度为:"<<A[i][j]<<"\n";cout<<"路径为:"<<i<<" ";pre=path[i][j];while(pre!=-1){cout<<pre<<"\n";pre=path[pre][j];}cout<<j<<endl;}}}//以下为选择总体最优过程,然后确址;for(i=0;i<G->n;i++)for(j=0;j<G->n;j++){if(A[i][j]==INF)count[i]=0;elsecount[i]=1;}for(i=0;i<G->n;i++)if(count[i]){for(j=0;j<G->n;j++)A[i][0]+=A[i][j];}for(i=0;i<G->n;i++){k=0;if(count[i])if(A[k][0]>A[i][0])k=i;}cout<<"商店的最佳地址为:"<<G->vexs[k]<<endl;}void main(){Mgraph *Gh=NULL;Gh=(Mgraph *)malloc(sizeof(Mgraph));CreatMgraph(Gh);Floyed(Gh);}。

分水岭算法(理论+opencv实现)

分水岭算法(理论+opencv实现)
把图像用一维坐标表示,二维和三维不好画,必须用matlab了,我不会用,意思可以表述到位
第一步:找到图像的局部最低点,这个方法很多了,可以用一个内核去找,也可以一个一个比较,实现起来不难。

第二步:从最低点开始注水,水开始网上满(图像的说法就是梯度法),其中那些最低点已经被标记,不会被淹没,那些中间点是被淹没的。

第三步:找到局部最高点,就是图中3位置对应的两个点。

第四步:这样基于局部最小值,和找到的局部最大值,就可以分割图像了。

分类图
模拟结果图
是不是感觉上面的方法很好,也很简单?接着看下面的图:
利用上面的步骤,第一步找到了三个点,然后第二步开始漫水,这三个点都被记录下来了,又找到两个局部最大值。

这是我们想要的吗?
回答是否定的!其中中间那个最小值我们不需要,因为只是一个很少并且很小的噪点而已,我们不需要图像分割的那么细致。

缺陷显露出来了吧?没关系,下面我们的opencv把这个问题解决了。

模拟分类图
模拟结果图
opencv改进的分水岭算法:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

分水岭算法(Watershed Algorithm) 所谓分水岭算法有好多种实现算法,拓扑学,形态学,浸水模拟和降水模拟等方式。要搞懂就不容易了。Watershed Algorithm(分水岭算法),顾名思义,就是根据分水岭的构成来考虑图像的分割。现实中我们可以或者说可以想象有山有湖的景象,那么那一定是水绕山,山围水的情形。而区分高山(plateaus)与水的界线,以及湖与湖之间的间隔或都是连通的关系,就是我们可爱的分水岭(watershed)。为了得到一个相对集中的集水盆,那么让水涨到都接近周围的最高的山顶就可以了,再涨就要漏水到邻居了,而邻居,嘿嘿,水质不同诶,会混淆自我的。那么这样的话,我们就可以用来获取边界高度大,中间灰阶小的物体区域了,它就是集水盆。

浸水法,就是先通过一个适当小的阈值得到起点,即集水盆的底;然后是向周围淹没也就是浸水的过程,直到得到分水岭。当然如果我们要一直淹没到山顶,即是一直处理到图像灰阶最高片,那么,当中就会出现筑坝的情况,不同的集水盆在这里想相遇了,我们要洁身自爱,到这里为止,因为都碰到边界了。不再上山。构筑属于自己的分水岭。

在计算机图形学中,可利用灰度表征地貌高。图像中我们可以利用灰度高与地貌高的相似性来研究图像的灰度在空间上的变化。这是空域分析,比如还可以通过各种形式的梯度计算以得到算法的输入,进行浸水处理。分水岭具有很强的边缘检测能力,对微弱的边缘也有较好的效果。

为会么这么说呢?为什么有很强的边缘检测能力,而又能得到相对集中的连通的集水盆?现实中很好办,我们在往凹地加水的时候,直到它涨到这一块紧凑的山岭边缘就不加了;但是如果有一条小山沟存在,那没办法,在初始阈值分割的时候,也就是山沟与集水盆有同样的极小值,而且它们之间是以这个高度一直连接的。那没关系,我们将它连通。在图像上呢?如何实现?

看看算法,算法思想是这样的: 首先准备好山和初始的水。这山就是我们的初始图像了,比如用自然获取的图像的梯度来表征山地的每一点的高度吧;而初始的水就是在阈值记为Thre底下,所有的低于这个高度的整个山地都加水,直到这个阈值Thre高度。从而有三个初始量:unsigned char** Ori_image、char** Seed_image和int** Label_image。最后一个是为最终的结果做准备的。当然要做好初始化,比如,Ora_image赋值为原图像(256色灰度图)的梯度值,Seed_image则是初始状态下有水的置位,无水的复位,而Label_image则全初始化为0,最终得到的是各点对应的区域号。

接下来是考虑将已加的水进行记录,记录成连通的区域,也就是看看有多少个互不相关的集水盆,有五个,那么我们就涨出五个湖,而且尽可能的高,只要大家想到不溢出。在算法上,有多少个连通的区域就记录成多少个数据结构,工夫就在于如何将这些连通的区域连接成一块,并由一个数据结构来表达了。很好,我们准备用一个向量容器来实现初始保存,保存所有标记区域种子队列的数组,里面放的是种子队列的指针vector vque,而且这个队列是由一系列属于同一个区域的图像点组成,我们来自一个集水盆:);其保存方式是这样的:queue *pque=new queue[256];vque.push_back(pque),这样便将一个成员放进到这个区域来了,即容器--集水盆的保管都,容器中的每个指针,都指向一个集水盆,也就是我们要的连通区域;所以我们可以方便地由这个容器数据结构直接读值的方便性进行操作,一个脚标就可以得到一个区域(队列指针)的指针;而每个队列还不简单,并不是一列整形数那么易搞,所以说啊,这个算法,真头痛,这个队列的一个成员是一个点;而注意到vque里存放的一256个队列的的起始指针,真够残忍的。也就是说vque[i][j]就表达了一个队列,这个队列里可以存储操作一系列的点;显然容量取256是因为所有的初始或者是最终的区域中可能有0-256之间的不同的灰阶的点,那么我一个区域分用256个队列来记录这些成员点啦,很有可能,这里就只有一个集水盆,那么,256个灰阶的点都存在一个区域就有可能了。

统计初始连通区域的方法是,八连通邻域法,即从逐一扫描输入的Seed_image的每个像素点,将所有的标记了的初始集水盆一一纳入各自的区域,这是整修图像的扫描,形成外循环。先创建一个临时队列quetem,用来处理当前初始集水盆的连通连接,将逐一扫描到的属于一个特定的初始集水盆区域的可生长点暂存,并形成一个内循环。对当前扫描点的处理是,首先判断该点是否为某个初始集水盆的点,如果不是跳过;接下来是,如果是初始集水盆的点,那么它的八连通域中是否存在不可生长的点(这里的不可生长是指Seed_image中没有标记的点),扫描的八连通邻域中的点是可生长的,即有标记的,则将之加入到临时队列中quetem;如果扫描到的连通邻域中有不可生长的至少一个点存在,那么加入到种子队列,记当前区域号为Num,当前扫描点为(m,n),从而当前的灰阶为Ori_image[m][n],将当前点添加到种子队列:vque[Num-1][Ori_image[m][n]].push(POINT(m,n))。这里有两个循环,一个是quetem,另一个是Seed_image。直到两个循环完整结束,那么就得到了各个连通初始集水盆的记录,保存标记是区域号Num;而我们同时得到了初始的分水岭,那就放在了保存地点vque,这里面标识了它们对应的区域号,和区域里面对应的点的灰阶,即是特定区域特定灰阶对应的点的集合;我们可以获取这些分水岭的点所在的区域号,可以得到该区域的所有的灰阶的点信息。一句话,统计连通区域的功能有两个,一是标记初始区域,二是找分水岭。

初始的区域标记好了,分岭也找到了,那么可以开始“水漫梁山”了。这就是淹没过程。淹没过程由也是由一个内嵌循环的循环来实现的:外循环是做水位上升(这里循环次数一定要256以内),waterlevel的上升,原来是已经做过了初始的水位分割,那么现在可以从Thre开始了,让水位慢慢上升,让它原本的湖慢慢扩张,尽量利用其应有的空间,而又不至于淹没到其它的邻居湖泊。内循环是扫描每个初始区域(当前Num,从而有Num个循环)的分水岭的点(在vque[][]中),按照给定的水位进行扩张。扩张过程是这样的:扫描到的分水岭的当前点,对其进行四连通邻域进行逐一检查,如果四连通域中有点没有标记的(那这一定是高度较高的点,较低的前面一定扫描过),那么先对该点以本区域号做标记Num(注意是当前的Num);再判断它在当前水位下是否可生长(灰阶是否小于等于waterlevel),如果可生长那么加入到vque[Num][waterlevel]种子队列中,将会再次进入内循环,否则如果在当前水位下不可生长,则加入到这个邻域点的分水岭集合中vque[Num][Ori_image[邻域点]]队列中。如此往复循环,直到对应区域完成,一个水位,扫描所有的区域的分水岭,这样各自同时在一个水位下扩张,保证了不出现跳跃的情况出现(就是一个水位一个区域全局扩张)。

最终,所有的区域在每个水位都扩张完毕,得到了分割图,我们的大湖泊形成了。 这是分水岭算法的一种实现方式。仔细考察不难发现这种实现方式不能产生新的集水盆,也就是说,由于初始集水盆的局限性,很可能会浪费大部分没有发掘出来的起始点较高的集水盆地。这样,我们就要对算法进行修改了。实现方式是:在淹没的过程中,我们是由阈值Thre的水位开始淹没的,那么我们可以对初始区域之外的没有标记的点(从Seed_image中考察),对之进行标记,条件是先把这一轮的内循环做好,然后在剩下的没标记区域中发掘新的集水盆,并加入到我们的种子队列中,下一个水位开始,就又多了一个新成员了,让它们不断膨胀,成长,拥有自己的小天的成员就会逐一的被分割出来。不过话说回来,我们这里是采用梯度图像,一般情况下,阈值初始分割能够满足我们的要求,把灰阶变化平滑的先截取出来,梯度信息已然足够强大;而如果采用了新盆地扩张,则比较适用于原始图像。

分水岭算法主要的分割目的在于找到图像的连通区域。利用梯度信息作为输入图像,会有一个矛盾点,如果对原始图像进行梯度计算时不作滤波平滑处理,很容易将物体分割成多个物体,那是因为噪声的影响;而如果进行滤波处理,又容易造成将某些原本几个的物体合成一个物体。当然这里的物体主要还是指图像变化不大或者说是灰度值相近的目标区域。 12月21日 分水岭算法(Watershed Algorithm) 所谓分水岭算法有好多种实现算法,拓扑学,形态学,浸水模拟和降水模拟等方式。要搞懂就不容易了。Watershed Algorithm(分水岭算法),顾名思义,就是根据分水岭的构成来考虑图像的分割。现实中我们可以或者说可以想象有山有湖的景象,那么那一定是水绕山,山围水的情形。而区分高山(plateaus)与水的界线,以及湖与湖之间的间隔或都是连通的关系,就是我们可爱的分水岭(watershed)。为了得到一个相对集中的集水盆,那么让水涨到都接近周围的最高的山顶就可以了,再涨就要漏水到邻居了,而邻居,嘿嘿,水质不同诶,会混淆自我的。那么这样的话,我们就可以用来获取边界高度大,中间灰阶小的物体区域了,它就是集水盆。

浸水法,就是先通过一个适当小的阈值得到起点,即集水盆的底;然后是向周围淹没也就是浸水的过程,直到得到分水岭。当然如果我们要一直淹没到山顶,即是一直处理到图像灰阶最高片,那么,当中就会出现筑坝的情况,不同的集水盆在这里想相遇了,我们要洁身自爱,到这里为止,因为都碰到边界了。不再上山。构筑属于自己的分水岭。

在计算机图形学中,可利用灰度表征地貌高。图像中我们可以利用灰度高与地貌高的相似性来研究图像的灰度在空间上的变化。这是空域分析,比如还可以通过各种形式的梯度计算以得到算法的输入,进行浸水处理。分水岭具有很强的边缘检测能力,对微弱的边缘也有较好的效果。

为会么这么说呢?为什么有很强的边缘检测能力,而又能得到相对集中的连通的集水盆?现实中很好办,我们在往凹地加水的时候,直到它涨到这一块紧凑的山岭边缘就不加了;但是如果有一条小山沟存在,那没办法,在初始阈值分割的时候,也就是山沟与集水盆有同样的极小值,而且它们之间是以这个高度一直连接的。那没关系,我们将它连通。在图像上呢?如何实现?

看看算法,算法思想是这样的: 首先准备好山和初始的水。这山就是我们的初始图像了,比如用自然获取的图像的梯度来表征山地的每一点的高度吧;而初始的水就是在阈值记为Thre底下,所有的低于这个高度的整个山地都加水,直到这个阈值Thre高度。从而有三个初始量:unsigned char** Ori_image、char** Seed_image和int** Label_image。最后一个是为最终的结果做准备的。当然要做好初

相关文档
最新文档