1. 定义

  分水岭算法(watershed algorithm)可以将图像中的边缘转化为“山脉”,将均匀区域转化为“山谷”,在这方面有助于分割目标。
  分水岭算法:是一种基于拓扑理论的数学形态学的分割方法。把图像看作是测地学上的拓扑地貌,图像中的每一个点像素值的灰度值表示该点的海拔高度,每一个局部极小值及其影响的区域称为“集水盆”,集水盆的边界可以看成分水岭。在每一个局部极小值表面刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢的向外扩展,在两个集水盆汇合处构建大坝,形成分水岭。

迭代标注过程:

  1. 排序过程:对每个像素的灰度级进行从低到高的排序
  2. 淹没过程:对每一个局部最小值在h阶高度的影响域采用先进先出结构判断及标注。

2.实现算法:watershed()函数

  这些标记的值可以使用findContours()函数和drawContours()函数由二进制的掩模检索出来

3.程序代码:

import numpy as np
import cv2
from osgeo import gdal, gdal_array
import shapefile
try:
import Image
import ImageDraw
except:
from PIL import Image, ImageDraw def tif_jpg(rasterfile):
in_ds = gdal.Open(rasterfile) # 打开样本文件
xsize = in_ds.RasterXSize # 获取行列数
ysize = in_ds.RasterYSize
bands = in_ds.RasterCount
block_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 data2 def watershed(path,out):
print("分水岭分割")
in_ds = gdal.Open(path) # 打开样本文件
xsize = in_ds.RasterXSize # 获取行列数
ysize = in_ds.RasterYSize
bands = in_ds.RasterCount
geotransform = 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边缘检测 函数返回一副二值图,其中包含检测出的边缘。
canny = cv2.Canny(gray_img, 80,120)
# 寻找图像轮廓 返回修改后的图像 图像的轮廓 以及它们的层次
# canny, contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 32位有符号整数类型,
marks = np.zeros(img.shape[:2], np.int32)
# findContours检测到的轮廓
imageContours = np.zeros(img.shape[:2], np.uint8)
# 轮廓颜色
compCount = 0
index = 0
# 绘制每一个轮廓
for index in range(len(contours)):
# 对marks进行标记,对不同区域的轮廓使用不同的亮度绘制,相当于设置注水点,有多少个轮廓,就有多少个轮廓
# 图像上不同线条的灰度值是不同的,底部略暗,越往上灰度越高
marks = cv2.drawContours(marks, contours, index, (index, index, index), 1, 8, hierarchy)
# 绘制轮廓,亮度一样
imageContours = cv2.drawContours(imageContours, contours, index, (255, 255, 255), 1, 8, hierarchy)
# 查看 使用线性变换转换输入数组元素成8位无符号整型。
markerShows = cv2.convertScaleAbs(marks)
# cv2.imshow('imageContours',imageContours)
# 使用分水岭算法
marks = cv2.watershed(img, marks)
driver = gdal.GetDriverByName('GTiff')
outfile_lake = out + "\\" + "watershed_cut.tif"
out_dataset = driver.Create(outfile_lake, xsize, ysize, 1, gdal.GDT_Float32)
out_band1 = out_dataset.GetRasterBand(1)
out_band1.WriteArray(marks)
out_dataset.SetGeoTransform(geotransform) # 写入仿射变换
out_dataset.SetProjection(projection)
return outfile_lake if __name__ == "__main__":
path = r"D:\data\实验数据\fenlei2.tif"
out = r"D:\data\实验结果\分割结果"
watershed(path, out)

python实现分水岭算法分割遥感图像的更多相关文章

  1. python实现分水岭算法

    目录: 问题:分水岭算法对图像分割很有作用,怎么把对象分割开来的?分水岭算法是比较完美的分割,跟前面的讲的轮廓不一样! (一)原理 (二)实现 (一)原理 opencv中的分水岭算法是基于距离变换的, ...

  2. OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法

    1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...

  3. python数字图像处理(19):骨架提取与分水岭算法

    骨架提取与分水岭算法也属于形态学处理范畴,都放在morphology子模块内. 1.骨架提取 骨架提取,也叫二值图像细化.这种算法能将一个连通区域细化成一个像素的宽度,用于特征提取和目标拓扑表示. m ...

  4. 【Keras】基于SegNet和U-Net的遥感图像语义分割

    上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰"天空之眼".这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新 ...

  5. 第八节、图片分割之GrabCut算法、分水岭算法

    所谓图像分割指的是根据灰度.颜色.纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性.我们先对目前主要的图像分割方法做个概述,后面再 ...

  6. 图片分割之GrabCut算法、分水岭算法

    https://www.cnblogs.com/zyly/p/9392881.html 所谓图像分割指的是根据灰度.颜色.纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出 ...

  7. opencv分水岭算法对图像进行切割

    先看效果 说明 使用分水岭算法对图像进行切割,设置一个标记图像能达到比較好的效果,还能防止过度切割. 1.这里首先对阈值化的二值图像进行腐蚀,去掉小的白色区域,得到图像的前景区域.并对前景区域用255 ...

  8. 图片像素对比OpenCV实现,实现人工分割跟算法分割图像结果的对比

    图片对比,计算不同像素个数,已经比率.实现人工分割跟算法分割图像结果的对比,但是只能用灰度图像作为输入 // imageMaskComparison.cpp : 定义控制台应用程序的入口点. // / ...

  9. opencv学习之路(30)、分水岭算法及图像修补

    一.简介 二.分水岭算法 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat srcImg = ...

随机推荐

  1. java继承基础详解

    java继承基础详解 继承是一种由已存在的类型创建一个或多个子类的机制,即在现有类的基础上构建子类. 在java中使用关键字extends表示继承关系. 基本语法结构: 访问控制符 class 子类名 ...

  2. solr(CVE-2017-12629)远程命令执行

    影响版本Apache Solr 5.5.0到7.0.1版本 solr(CVE-2017-12629-RCE) 环境搭建 1.burp检测 创建listen POST /solr/demo/config ...

  3. 【LeetCode】81. 搜索旋转排序数组 II

    81. 搜索旋转排序数组 II 知识点:数组,二分查找: 题目描述 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 ...

  4. Java8 Lambda表达式(二)

    目录 一.Java8 内置的四大核心函数式接口 1. 消费型接口 Consumer 2. 供给型接口 Supplier 3. 函数型接口 Function 4.断言型接口 Predicate 二.方法 ...

  5. 数据结构与算法 java描述 第一章 算法及其复杂度

    目录 数据结构与算法 java描述 笔记 第一章 算法及其复杂度 算法的定义 算法性能的分析与评价 问题规模.运行时间及时间复杂度 渐进复杂度 大 O 记号 大Ω记号 Θ记号 空间复杂度 算法复杂度及 ...

  6. 阿里面试官:Android中binder机制的实现原理及过程?

    Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...

  7. HttpClient执行post请求

    public class Httpclient_post { private ResourceBundle bundle; private String url; private BasicCooki ...

  8. 解决docker删除加载失败的镜像报错

    背景: 准备在vulhub复现weblogic反序列化漏洞时报错,环境加载失败准备删除weblogic镜像时报错: unable to delete 7d35c6cd3bcd (must be for ...

  9. SQL 练习22

    查询出只选修两门课程的学生学号和姓名 --方式1: SELECT Student.SId,Sname from Student WHERE SId in ( SELECT sid from sc GR ...

  10. NOIP 模拟 6 模板

    题目 题解 这道题是一道启发式合并的题目,每次合并完重构一下线段树就可以,不用线段树合并. 以操作时间为下标,建立一颗线段树,维护小球的个数与小球的颜色数,最后线段树上二分查找. 我们先不用考虑每个节 ...