python实现分水岭算法分割遥感图像
1. 定义
分水岭算法(watershed algorithm)可以将图像中的边缘转化为“山脉”,将均匀区域转化为“山谷”,在这方面有助于分割目标。
分水岭算法:是一种基于拓扑理论的数学形态学的分割方法。把图像看作是测地学上的拓扑地貌,图像中的每一个点像素值的灰度值表示该点的海拔高度,每一个局部极小值及其影响的区域称为“集水盆”,集水盆的边界可以看成分水岭。在每一个局部极小值表面刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢的向外扩展,在两个集水盆汇合处构建大坝,形成分水岭。
迭代标注过程:
- 排序过程:对每个像素的灰度级进行从低到高的排序
- 淹没过程:对每一个局部最小值在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实现分水岭算法分割遥感图像的更多相关文章
- python实现分水岭算法
目录: 问题:分水岭算法对图像分割很有作用,怎么把对象分割开来的?分水岭算法是比较完美的分割,跟前面的讲的轮廓不一样! (一)原理 (二)实现 (一)原理 opencv中的分水岭算法是基于距离变换的, ...
- OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法
1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...
- python数字图像处理(19):骨架提取与分水岭算法
骨架提取与分水岭算法也属于形态学处理范畴,都放在morphology子模块内. 1.骨架提取 骨架提取,也叫二值图像细化.这种算法能将一个连通区域细化成一个像素的宽度,用于特征提取和目标拓扑表示. m ...
- 【Keras】基于SegNet和U-Net的遥感图像语义分割
上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰"天空之眼".这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新 ...
- 第八节、图片分割之GrabCut算法、分水岭算法
所谓图像分割指的是根据灰度.颜色.纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性.我们先对目前主要的图像分割方法做个概述,后面再 ...
- 图片分割之GrabCut算法、分水岭算法
https://www.cnblogs.com/zyly/p/9392881.html 所谓图像分割指的是根据灰度.颜色.纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出 ...
- opencv分水岭算法对图像进行切割
先看效果 说明 使用分水岭算法对图像进行切割,设置一个标记图像能达到比較好的效果,还能防止过度切割. 1.这里首先对阈值化的二值图像进行腐蚀,去掉小的白色区域,得到图像的前景区域.并对前景区域用255 ...
- 图片像素对比OpenCV实现,实现人工分割跟算法分割图像结果的对比
图片对比,计算不同像素个数,已经比率.实现人工分割跟算法分割图像结果的对比,但是只能用灰度图像作为输入 // imageMaskComparison.cpp : 定义控制台应用程序的入口点. // / ...
- opencv学习之路(30)、分水岭算法及图像修补
一.简介 二.分水岭算法 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat srcImg = ...
随机推荐
- java继承基础详解
java继承基础详解 继承是一种由已存在的类型创建一个或多个子类的机制,即在现有类的基础上构建子类. 在java中使用关键字extends表示继承关系. 基本语法结构: 访问控制符 class 子类名 ...
- solr(CVE-2017-12629)远程命令执行
影响版本Apache Solr 5.5.0到7.0.1版本 solr(CVE-2017-12629-RCE) 环境搭建 1.burp检测 创建listen POST /solr/demo/config ...
- 【LeetCode】81. 搜索旋转排序数组 II
81. 搜索旋转排序数组 II 知识点:数组,二分查找: 题目描述 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 ...
- Java8 Lambda表达式(二)
目录 一.Java8 内置的四大核心函数式接口 1. 消费型接口 Consumer 2. 供给型接口 Supplier 3. 函数型接口 Function 4.断言型接口 Predicate 二.方法 ...
- 数据结构与算法 java描述 第一章 算法及其复杂度
目录 数据结构与算法 java描述 笔记 第一章 算法及其复杂度 算法的定义 算法性能的分析与评价 问题规模.运行时间及时间复杂度 渐进复杂度 大 O 记号 大Ω记号 Θ记号 空间复杂度 算法复杂度及 ...
- 阿里面试官:Android中binder机制的实现原理及过程?
Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...
- HttpClient执行post请求
public class Httpclient_post { private ResourceBundle bundle; private String url; private BasicCooki ...
- 解决docker删除加载失败的镜像报错
背景: 准备在vulhub复现weblogic反序列化漏洞时报错,环境加载失败准备删除weblogic镜像时报错: unable to delete 7d35c6cd3bcd (must be for ...
- SQL 练习22
查询出只选修两门课程的学生学号和姓名 --方式1: SELECT Student.SId,Sname from Student WHERE SId in ( SELECT sid from sc GR ...
- NOIP 模拟 6 模板
题目 题解 这道题是一道启发式合并的题目,每次合并完重构一下线段树就可以,不用线段树合并. 以操作时间为下标,建立一颗线段树,维护小球的个数与小球的颜色数,最后线段树上二分查找. 我们先不用考虑每个节 ...