基于python3+opencv3遥感影像的湖泊边界提取

参考:https://baijiahao.baidu.com/s?id=1607856881407380092&wfr=spider&for=pc

首先进行opencv安装,先安装Anaconda3,配置好环境,在Anaconda3的python3中安装opencv-python。

1、选择遥感影像,本例中选择的遥感影像为南京市玄武湖,影像如下:
基于python3+opencv3遥感影像的湖泊边界提取_第1张图片
(实际应用中湖泊数据可能不会这么分明,需要更近一步研究)

2、导入cv2和numpy,读取影像

import cv2
import numpy
image = cv2.imread("xwh.jpg")

3、获取湖泊区域的BGR值,对应三个数值,可以利用软件提取,软件如:jcpicker.exe,本例中获取的湖泊区域的BGR值分别为90,98,67。提取在该值上下浮动20(可自行修改)区间的值,作为影像二值化的依据。(补充:影像必须先进行灰度化,然后才进行二值化处理。)对于在湖泊BGR区间内的影像部分赋值为白色(255),其余部分赋值为黑色(0).代码如下:

BGR = numpy.array([90,98,67])
upper = BGR + 20
lower = BGR - 20
mask = cv2.inRange(image,lower,upper)
cv2.imshow("Mask",mask)

结果命名为掩膜数据,结果如下图:
基于python3+opencv3遥感影像的湖泊边界提取_第2张图片
4、OpenCV提供了cv2.findContours()函数提取二值化图像的轮廓。对上面生成图片上执行这个函数就可以返回该图片的区域轮廓。由于执行该函数时会直接修改图像,因此我们复制一份图像之传给cv2.findContours();同时,OpenCV提供了cv2.drawContour()函数绘可以把轮廓叠加到另一张图片上。

使用cv2.findContours()函数对mask图片提取轮廓,并调用cv2.drawContour()把轮廓叠加在原始图像,代码如下:

(_,contours,hicrarchy) = cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print("number of contours:%d" %(len(contours)))
alllakesImage = image.copy()
cv2.drawContours(alllakesImage,contours,-1,(0,0,255),2)
cv2.imshow("Image of All Lake",alllakesImage)

结果如下图所示:
基于python3+opencv3遥感影像的湖泊边界提取_第3张图片
5、在获取的轮廓结果图中我们可以看到,存在众多的细小板块,统计结果显示number of contours:7067,其中contours.sort(key=len,reverse=True)可以对细小斑块的面积进行排序,代码如下:

theLargestLake = image.copy()
contours.sort(key=len,reverse=True)
cv2.drawContours(theLargestLake,[contours[0]],-1,(0,0,255),2)
cv2.imshow("Image of the Largest Lake",theLargestLake)

结果如下图:
基于python3+opencv3遥感影像的湖泊边界提取_第4张图片
注意:由于openvc3中cv2.imshow()函数显示的结果存在闪退的情况,在最后显示图的地方添加cv2.waitKey(),表示一直等待,如果其后存在代码,不执行。

未完…….正在继续………

由于上面步骤3中存在,手动赋予像素值的操作,因此考虑,是否可以通过统计直方图,自动找出该值,即将R、G、B三色道直方图中的峰值处对应的灰度值作为输入。
1、首先对影像进行三通道分离。代码如下:

image = cv2.imread("xwh.jpg")
# 转换为浮点数进行计算
fsrc = np.array(image, dtype=np.float32) /255.0
band = cv2.split(fsrc)

其中band是一个数组,即band[b,g,r].

2、定义一个函数,分别对三色道的直方图分别进行峰值处的灰度值提取的操作。

def histing(x):
    #求取最大值和最小值 
  (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(band[x])
    #计算直方图   
  hist = cv2.calcHist([band[x]], [0], None, [256], [minVal, maxVal])
  n = hist.tolist().index(max(hist)
  plt.plot(hist)
  plt.show()
  return n

结果如下:
基于python3+opencv3遥感影像的湖泊边界提取_第5张图片
基于python3+opencv3遥感影像的湖泊边界提取_第6张图片
基于python3+opencv3遥感影像的湖泊边界提取_第7张图片
利用这三个值作为输入值,分割的结果如下图,相比手动而言,效果还是差些。结果如下:
基于python3+opencv3遥感影像的湖泊边界提取_第8张图片
在遥感影像分类中,现阶段计算机能做的结果还是不如人手动进行的效果好,虽然有些公司或者个人在鼓吹AI、人工智能进行分割效果很好之类,其研究范围是个例,不具有广泛的适用性。

遥感影像分割,在现在以及将来都是研究热点,技术难题尚未解决,期待各位同志继续努力….

你可能感兴趣的:(python,python3,opencv3,遥感影像,湖泊边界提取)