基于深度学习的珠海一号高光谱影像云检测

时间:2024-03-06 20:34:24

       2019年上半年参加了珠海欧比特公司举办的高光谱大赛,本意是想着看看数据质量如何,简单的拿着我们团队自己开发的深度学习模型,去参加了一下高光谱竞赛,也没怎么准备,就是简单的应用一下而已,我们花了一个星期东西凑了点东西,介绍文档不到7页,居然拿了个二等奖。。。。主题是云检测。如果大家有任何问题,请与我联系Email:1044625113@qq.com,qq:1044625113.加我时,请备注:高精度云检测

       大家都知道云、雪、高亮地物在没有短波红外波段加入区分时,这几种地物是很容易混淆的,虽然有很多文章宣称可以做到高精度云雪检测,但是真正落地应用的时候,基本上都不行,效果很差,直到深度学习方法出来,这种现象才有了很大的改观。而我们团队主要是深度学习语义分割这一块的,因此云雪自然是我们的一个小目标而已,我们已经在国产高分系列卫星上面实现高精度云检测,在珠海一号高光谱卫星上,表现如何呢?下面我会用实验记录这一次竞赛的情况,不说了,show code and result,首先使用爬虫技术,爬取了欧比特高光谱竞赛官网上所有影像,之所以不手动下载,主要是因为数据太多了。。。

 

     爬虫代码如下所示:

# -*- coding: utf-8 -*-
# Purpose: 下载珠海一号数据
# Author: Mr Zhipan wang,  if you have any question,Email:1044625113@qq.com

import os
import re
import urllib.error
import urllib.request

import requests
from bs4 import BeautifulSoup
from win32com.client import Dispatch  # 调用迅雷下载


#  使用正则表达式获取下载连接,refer: https://zhuanlan.zhihu.com/p/52198820
#  顺便说一句,正则表达式实在是太过于强大...
def findURL(stringName):
    """
    :param stringName: 字符串
    :return: 返回字符串中的URL下载网址, 示例:http://218.13.181.222:8000/f/c9f1805f87/?raw=1
    """
    # findall() 查找匹配正则表达式的字符串
    pattern = r"\w{4}\W{3}\d{3}.\d{2}.\d{3}.\d{3}.\d{4}\W\w\W\w{10}\W{2}.{5}"
    url = re.findall(pattern, stringName)
    return url# 创建文件夹
def mkdir(pathName):
    """
        :pathName : 待创建的路径名
    """
    folder = os.path.exists(pathName)
    if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
        os.makedirs(pathName)  # makedirs 创建文件时如果路径不存在会创建这个路径
        # print "---  新文件夹创建成功...  ---"
    else:
        print("---  文件夹已存在!  ---")


# 下载文件-urllib.request
def getDown_urllib(url, file_path):  # 需要写明文件名称,否则无法写入
    try:
        urllib.request.urlretrieve(url, filename=file_path)
        return True
    except urllib.error.URLError as e:
        # hasttr(e, \'code\'),判断e 是否有.code属性,因为不确定是不是HTTPError错误,URLError包含HTTPError,但是HTTPError以外的错误是不返回错误码(状态码)的
        if hasattr(e, \'code\'):
            print(e.code)  # 打印服务器返回的错误码(状态码),如403,404,501之类的
            return False
        elif hasattr(e, \'reason\'):
            print(e.reason)  # 打印错误原因
            return False


def getDownFile(url, savePath):
    """
    :param url:下载的页面URL
    :param savePath: 保存影像路径
    :return: 下载地址,文件夹名称
    """
    # savePath = "E:\\珠海欧比特遥感应用大赛\\影像数据"

    headers = {\'User-Agent\': \'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6\'}

    temp_Page = requests.get(url, headers=headers)
    soup = BeautifulSoup(temp_Page.text, "lxml")

    Contents = soup.contents[0].text  # 转成string字符串
    downURL = findURL(Contents)
    imgPlace = findPlaceName(Contents)

    saveImagePath = []
    for path in imgPlace:  # 创建影像文件名
        Path = os.path.join(savePath, path + ".rar")
        saveImagePath.append(Path)

    if (len(downURL) == len(imgPlace)):
        for i in range(0, len(downURL)):
            urlImg = downURL[i]
            FileName = saveImagePath[i]

            if os.path.exists(FileName):
                print("文件已经存在...")
            else:
                down_Type = getDown_urllib(urlImg, FileName)  # true 表示当前ts文件下载成功a
                print(\'\' + str(i) + \'个影像爬取完成...\')
    else:
        print("该页面爬取错误...")


# 调用迅雷进行下载
def XunLeiDownLaod(url, savePath):
    """
    :param url:
    :param savePath:
    :return:
    """
    headers = {\'User-Agent\': \'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6\'}

    temp_Page = requests.get(url, headers=headers)
    soup = BeautifulSoup(temp_Page.text, "lxml")

    Contents = soup.contents[0].text  # 转成string字符串
    downURL = findURL(Contents)
    imgPlace = findPlaceName(Contents)

    saveImagePath = []
    for path in imgPlace:  # 创建影像文件名
        Path = os.path.join(savePath, path + ".rar")
        saveImagePath.append(Path)

    Xunlei = Dispatch("ThunderAgent.Agent64.1")

    # print(len(downURL))
    # print(len(imgPlace))

    if (len(downURL) == len(imgPlace)):
        for i in range(0, len(downURL)):
            urlImg = downURL[i]
            FileName = saveImagePath[i]

            if os.path.exists(FileName):
                print("文件已经存在...")
            else:
                Xunlei.AddTask(urlImg, FileName, savePath)
                print(\'\' + str(i) + \'个迅雷下载任务添加完毕...\')

        Xunlei.CommitTasks()  # 开始下载任务
    else:
        print("该页面爬取错误...")


if __name__ == \'__main__\':
    URL_page = [
        "https://web30.obtdata.com/web/dataDownload/page?pageNo=0&pageSize=20&token=a22ca3ec-a644-44d2-b281-bf1e8309e015",
        "https://web30.obtdata.com/web/dataDownload/page?pageNo=1&pageSize=20&token=a22ca3ec-a644-44d2-b281-bf1e8309e015",
        "https://web30.obtdata.com/web/dataDownload/page?pageNo=2&pageSize=20&token=a22ca3ec-a644-44d2-b281-bf1e8309e015",
        "https://web30.obtdata.com/web/dataDownload/page?pageNo=3&pageSize=20&token=a22ca3ec-a644-44d2-b281-bf1e8309e015",
        "https://web30.obtdata.com/web/dataDownload/page?pageNo=4&pageSize=20&token=a22ca3ec-a644-44d2-b281-bf1e8309e015"]

    savePath = "E:\\珠海欧比特遥感应用大赛\\影像数据"

    # pool = Pool(5)
    #
    # Task1 = pool.map(getDownFile, URL_page[0])
    # Task2 = pool.map(getDownFile, URL_page[1])
    # Task3 = pool.map(getDownFile, URL_page[2])
    # Task4 = pool.map(getDownFile, URL_page[3])
    # Task5 = pool.map(getDownFile, URL_page[4])
    #
    # pool.close()
    # pool.join()

    # # requests 下载
    # getDownFile(URL_page[0], savePath)
    # getDownFile(URL_page[1], savePath)
    # getDownFile(URL_page[2], savePath)
    # getDownFile(URL_page[3], savePath)
    # getDownFile(URL_page[4], savePath)

    # 迅雷下载
    # XunLeiDownLaod(URL_page[0], savePath)
    # XunLeiDownLaod(URL_page[1], savePath)
    # XunLeiDownLaod(URL_page[2], savePath)
    XunLeiDownLaod(URL_page[3], savePath)
    # XunLeiDownLaod(URL_page[4], savePath)

    print("全部完成...")

 

     数据搞完了后,就要进行处理了,我把所有的波段组合成一个影像,并生成一个真彩色影像,如下图:

图1 雪样本

图2 云雪混合样本

      同样,我只是举一个例子来说明我所采用的影像数据源,真正的实验过程,我把它裁剪成了512*512大小的图像块,采用GPU进行训练,深度学习模型如下图所示,比赛已经结束,可以开源了:

 

       这个架构中,我们自己在四个空洞卷积层进行了改进,后续接四个池化层,聚合特征,经过实验来看,效果会有一定损失,但是效果会提升2%-5%左右,相比于Unet就会好更多了,经过我们的实验,发现Unet很难区分云雪,尤其是高山雪,我们自己的这个网络架构,基本上把云雪进行了区分,结果还是比较好的,同时,我们也设计一个GUI界面,用来简单的给用户训练模型和持续迭代,这个才真正有点工程的味道了。

 

      总体上来说,包含了模型训练,云检测,批量云检测功能,其实,从应用的角度上来说,这个东西不仅仅可以用来做云雪检测,也可以用来做其他地物监测,我看到了那些一等奖之类的,基本上都是特定地物识别,还取得了不错的成果,如果能结合这个工程化的思路,我相信能够真正的落地应用!

      在实际系统设计时,我主要用了python+matlab混合编程实现,python主要负责的功能是栅格矢量化,调用GDAL实现,matlab是调用深度学习模型进行云雪检测,并实现部分后处理流程,两者调用通过import类实现,这个算是比较简单的,无需复杂配置,即可完成,后期可以考虑使用并行编程,来提高处理速度。来看看结果:

  图3 测试图像真彩色

图4 云检测结果矢量化

     可以看到,结果还是非常nice的。 如果大家有任何问题,或者想交流的,请加我qq联系,在此抛砖引玉,如有任何技术不当之处,烦请高手指正