python实现对遥感影像经纬度获取并实现海陆分离

遥感数据制作数据集预处理

    • 1 珊格数据(.pix、.lyr等)转tif
    • 2 使用gdal库实现经纬度获取
    • 3 tif 转 jpg
    • 4 jpg图像裁剪为指定分辨率
    • 5 常见的几何变换扩充数据集(opencv实现)

1 珊格数据(.pix、.lyr等)转tif

tif百科
转tif

2 使用gdal库实现经纬度获取

tif图像自带经纬度信息,因此可以使用gdal包获取经纬度信息然后对相应像素点负值操作

from osgeo import gdal
from global_land_mask import globe
from  global_land_mask.globe import is_land
from glob import *
from osgeo import osr
import os
# import numpy as np
from functools import lru_cache

# -*- coding: utf-8 -*-
# /**
#  * 各地图API坐标系统比较与转换;
#  * WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,
#  * 谷歌地图采用的是WGS84地理坐标系(中国范围除外);
#  * GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系;
#  * 3BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系;
#  */
import math
from decimal import *

class GLM(object):
    def __init__(self, fileName):
        self.fileName_ = fileName

    # 读取tif数据集
    def readTif(self):
        dataset = gdal.Open(self.fileName_)
        if dataset is None:
            print(self.fileName_+"文件无法打开")
        return dataset

    # 获取仿射矩阵信息
    def Getgeotrans(self):
        dataset = self.readTif()
        # dataset = GLM.readTif(self)

        im_width = dataset.RasterXSize  # 栅格矩阵的列数
        im_height = dataset.RasterYSize  # 栅格矩阵的行数
        im_geotrans = dataset.GetGeoTransform()  # 仿射矩阵
        print("放射矩阵:",im_geotrans)
        im_proj = dataset.GetProjection()  # 地图投影信息
        im_data = dataset.ReadAsArray(0, 0, im_width, im_height)  # 将数据写成数组,对应栅格矩阵

        del dataset
        return im_proj, im_geotrans, im_data



    #像素坐标和地理坐标仿射变换
    def CoordTransf(self, Xpixel, Ypixel, GeoTransform): #wgs坐标
        XGeo = GeoTransform[0]+GeoTransform[1]*Xpixel+Ypixel*GeoTransform[2]
        YGeo = GeoTransform[3]+GeoTransform[4]*Xpixel+Ypixel*GeoTransform[5]
        return XGeo, YGeo

    # 写文件,写成tif
    def write_img(self, outpath, im_proj, im_geotrans, im_data):
        # gdal数据类型包括
        # gdal.GDT_Byte,
        # gdal .GDT_UInt16, gdal.GDT_Int16, gdal.GDT_UInt32, gdal.GDT_Int32,
        # gdal.GDT_Float32, gdal.GDT_Float64

        # 判断栅格数据的数据类型
        if 'int8' in im_data.dtype.name:
            datatype = gdal.GDT_Byte
        elif 'int16' in im_data.dtype.name:
            datatype = gdal.GDT_UInt16
        else:
            datatype = gdal.GDT_Float32

        # 判读数组维数
        if len(im_data.shape) == 3:
            im_bands, im_height, im_width = im_data.shape
        else:
            im_bands, (im_height, im_width) = 1, im_data.shape

        # 创建文件
        driver = gdal.GetDriverByName("GTiff")  # 数据类型必须有,因为要计算需要多大内存空间
        dataset = driver.Create(outpath, im_width, im_height, im_bands, datatype)

        dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
        dataset.SetProjection(im_proj)  # 写入投影

        if im_bands == 1:
            dataset.GetRasterBand(1).WriteArray(im_data)  # 写入数组数据
        else:
            for i in range(im_bands):
                dataset.GetRasterBand(i + 1).WriteArray(im_data[i])

        del dataset


if __name__ == "__main__":
    filelist = glob("data_tif/cut_example.tif") #tif路径
    # image_list = []
    for file in filelist:
        print('[INFO] {}'.format(file))
        glm = GLM(file)
        proj, geotrans, data = glm.Getgeotrans()
        print(data)
        depth,height, width= data.shape
        print("depth,height,width:",depth,height,width)
        for y in range(0, height):
            for x in range(0, width):
                #longitude 经度 latitude 维度
                lon,lat = glm.CoordTransf(y, x, geotrans)
                #print('lat={}, lon={} is on land:'.format(lon, lat))
                is_on_land=is_land(lat,lon)
                #print('lat={}, lon={} is on land: {}'.format(lon, lat, is_on_land))
                if is_on_land==False:
                    data[:, y, x] = 0
                else:
                    data[:,y,x] = 255
                #print(data[:, y, x])
        print(data)
        #保存路径
        glm.write_img("fenli_data/cut_example_out.tif", proj, geotrans,data[:, :, :])  # 写数据
        #glm.write_img(os.path.join(out_dir, os.path.basename(file).split('.')[0]+'.tif'), proj, geotrans, data[:, :, :])  # 写数据

结果:(1m分辨率,可以看到,误差很大,没法用)
python实现对遥感影像经纬度获取并实现海陆分离_第1张图片
500m分辨率 MODIS效果就好多了
python实现对遥感影像经纬度获取并实现海陆分离_第2张图片
经纬度1秒误差在30m左右,1度3600秒,如果遥感影像的分辨率大 比如(1m,或者2m)想实现海陆分离不能根据经纬度坐标了,这时候建议裁剪所需区域手动标记制作掩膜。

3 tif 转 jpg

import os,sys
import cv2
import numpy as np
from skimage import io#使用IO库读取tif图片


def tif_jpg_transform(file_path_name, bgr_savepath_name):
    img = io.imread(file_path_name)#读取文件名
    img = img / img.max()#使其所有值不大于一
    img = img * 255 - 0.001  # 减去0.001防止变成负整型
    img = img.astype(np.uint8)#强制转换成8位整型
    # img = np.array([img,img,img])
    # img = img.transpose(1,2,0)
    print(img.shape)  # 显示图片大小和深度
    b = img[:, :, 0]  # 读取蓝通道
    g = img[:, :, 1]  # 读取绿通道
    r = img[:, :, 2]  # 读取红通道
    bgr = cv2.merge([r, g, b])  # 通道拼接
    cv2.imwrite(bgr_savepath_name, bgr)#图片存储


tif_file_path = r'yourpath'  # 为tif图片的文件夹路径
tif_fileList = os.listdir(tif_file_path)
for tif_file in tif_fileList:
    file_path_name = tif_file_path + '/' + tif_file
    print(file_path_name)
    jpg_path = r'yourpath' + '/' + tif_file.split('.')[0] + '.jpg' #.jpg图片的保存路径
    print(jpg_path)
    tif_jpg_transform(file_path_name, jpg_path)

4 jpg图像裁剪为指定分辨率

import cv2
import numpy as np
import os
pic_path = '/Users/xxx/PycharmProjects/py38_tf/遥感大作业/cut/222_out.jpg' # 分割的图片的位置
pic_target = '/Users/xxx/PycharmProjects/py38_tf/遥感大作业/cut/1024x1024/' # 分割后的图片保存的文件夹
if not os.path.exists(pic_target):  #判断是否存在文件夹如果不存在则创建为文件夹
    os.makedirs(pic_target)
#要分割后的尺寸
cut_width = 1024
cut_length = 1024
# 读取要分割的图片,以及其尺寸等数据
picture = cv2.imread(pic_path)
(width, length, depth) = picture.shape
print(width,length,depth)
# 预处理生成0矩阵
pic = np.zeros((cut_width, cut_length, depth))
# 计算可以划分的横纵的个数
num_width = int(width / cut_width)
num_length = int(length / cut_length)
# for循环迭代生成
for i in range(0, num_width):
    for j in range(0, num_length):
        pic = picture[i*cut_width : (i+1)*cut_width, j*cut_length : (j+1)*cut_length, :]
        result_path = pic_target + '{}_{}.jpg'.format(i+1, j+1)
        cv2.imwrite(result_path, pic)

print("done!!!")

5 常见的几何变换扩充数据集(opencv实现)

# 程序功能:python+opencv实现数据增强,并保存图片
import numpy as np
import cv2
import os
#数据增强后的图片保存路劲,不要有中文路径!!!
org_path_images="D:/pycharm/MyCode/demo/data/training/images/"
save_path_images="D:/pycharm/MyCode/demo/data/training/DA_images/"
org_path_labels="D:/pycharm/MyCode/demo/data/training/labels/"
save_path_labels="D:/pycharm/MyCode/demo/data/training/DA_labels/"
def SDA(org_path,save_path):
    i=100
    print(os.listdir(org_path))
    for info in os.listdir(org_path):
        info1 = os.path.join(org_path, info)  # 将路径与文件名结合起来就是每个文件的完整路径
        print(info1)
        img = cv2.imread(info1)
        #print("img:",img)
        # if(img==None):
        #     print("None!!!")
        # 水平镜像
        i += 1
        h_flip = cv2.flip(img, 1)
        cv2.imwrite(save_path+str(i)+'.png', h_flip)
        # 垂直镜像
        i += 1
        v_flip = cv2.flip(img, 0)
        cv2.imwrite(save_path+str(i)+'.png', v_flip)
        # 水平垂直镜像
        i += 1
        hv_flip = cv2.flip(img, -1)
        #cv2.imshow("Flipped Horizontally & Vertically", hv_flip)
        cv2.imwrite(save_path+str(i)+'.png', hv_flip)
        # 90度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
        dst_90 = cv2.warpAffine(img, M, (cols, rows))
        cv2.imwrite(save_path+str(i)+'.png', dst_90)
        # 70度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 70, 1)
        dst_70 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_70", dst_70)
        cv2.imwrite(save_path+str(i)+'.png', dst_70)
        # 60度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 60, 1)
        dst_60 = cv2.warpAffine(img, M, (cols, rows))
       # cv2.imshow("dst_60", dst_60)
        cv2.imwrite(save_path+str(i)+'.png', dst_60)
        # 50度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 50, 1)
        dst_50 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_50", dst_50)
        cv2.imwrite(save_path+str(i)+'.png', dst_50)
        # 45度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 1)
        dst_45 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_45", dst_45)
        cv2.imwrite(save_path+str(i)+'.png', dst_45)
        # 40度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 40, 1)
        dst_40 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_40", dst_40)
        cv2.imwrite(save_path+str(i)+'.png', dst_40)
        # 30度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 30, 1)
        dst_30 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_30", dst_30)
        cv2.imwrite(save_path+str(i)+'.png', dst_30)
        # 20度旋转
        i += 1
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 20, 1)
        dst_20 = cv2.warpAffine(img, M, (cols, rows))
        #cv2.imshow("dst_20", dst_20)
        cv2.imwrite(save_path+str(i)+'.png', dst_20)
        # 缩放
        # height, width = img.shape[:2]
        # res = cv2.resize(img, (2 * width, 2 * height))
        # cv2.imshow("large", res)
        # cv2.imwrite(save_path+info+'res.png', res)
        # 仿射变换
        # 对图像进行变换(三点得到一个变换矩阵)
        # 我们知道三点确定一个平面,我们也可以通过确定三个点的关系来得到转换矩阵
        # 然后再通过warpAffine来进行变换
        i += 1
        point1 = np.float32([[50, 50], [300, 50], [50, 200]])
        point2 = np.float32([[10, 100], [300, 50], [100, 250]])
        M = cv2.getAffineTransform(point1, point2)
        dst1 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255, 255, 255))
        #cv2.imshow("affine transformation", dst1)
        cv2.imwrite(save_path+str(i)+'.png', dst1)
    cv2.waitKey(0)

if __name__=="__main__":
    #图片跟标签做同样的增强操作
    #print("ghi8gweohboier")
    SDA(org_path_images,save_path_images)
    SDA(org_path_labels,save_path_labels)


你可能感兴趣的:(遥感影像处理,python,经纬度获取,gdal)