• 【Arcpy】提取遥感影像像元值


    基于开源库执行

    GDAL 是读写大量的栅格空间数据格式的广泛应用的开源库。该库起源于 1998年,已经大幅进化。 它支持他自己的数据模型和应用程序接口(API)。 从最初的单一发展的起源,GDAL已发展成为一个分布式的项目,开发人员的数量相对比较大。
    目前GDAL是OSGEO的子项目,代码进行了重新组织。 在 RFC 17号文件中, 实现了Python的新的名称空间osgeo, 并将gdal与ogr都包含在这个名称空间之下。

    下面给出主要学习的链接:
    官方文档
    python与开源GIS
    OSGeo中国中心

    下面附上基于gdal计算像元值的代码。

    import os
    import math
    import numpy as np
    from tqdm import tqdm
    from openpyxl import Workbook
    from osgeo import gdal, gdalconst
    #读取python文件所在的位置
    base_dir = os.path.dirname(os.path.abspath(__file__))
    
    
    #读取图像数据
    def getData(path):
        #读取一个GeoTiff文件的信息,GA_ReadOnly只读形式
        dataset = gdal.Open(path, gdalconst.GA_ReadOnly)
        #栅格数据的宽度(X方向上的像素个数)
        width = dataset.RasterXSize
        #栅格数据的高度(Y方向上的像素个数)
        height = dataset.RasterYSize
        
        '''
    六个参数分别是:
        geos[0]  top left x 左上角x坐标
        geos[1]  w-e pixel resolution 东西方向像素分辨率
        geos[2]  rotation, 0 if image is "north up" 旋转角度,正北向上时为0
        geos[3]  top left y 左上角y坐标
        geos[4]  rotation, 0 if image is "north up" 旋转角度,正北向上时为0
        geos[5]  n-s pixel resolution 南北向像素分辨率,为负值
        x/y为图像的x/y坐标,geox/geoy为对应的投影坐标
        
        (294256.45800898736, 500.0, 0.0, 4314092.674585257, 0.0, -500.0)
        可知,200201_month_p的像元大小为500
    '''
        #栅格数据仿射变换的六参数
        im_geotrans = dataset.GetGeoTransform()
        #图像的投影信息
        im_proj = dataset.GetProjection()
        
        '''
        ReadAsArray(xoff=0, yoff=0, xsize=None, ysize=None)
        xoff,yoff :指定想要读取的部分原点位置在整张图像中距离全图原点的位置(以像元为单位)。
        xsize,ysize : 指定要读取部分图像的矩形的长和宽(以像元为单位)。
        
        dataset.ReadAsArray(0, 0, width, height)
        就是读取全图
        '''
        
        #读取图像数据(以numpy数组的形式)
        data = np.array(dataset.ReadAsArray(0, 0, width, height), dtype=float)
        #返回图像数据,六参数和投影
        return data, im_geotrans, im_proj
    
    #换算在array中的下标
    def get_r_c(lat, lon, im_geotrans):
        row = math.floor((im_geotrans[3] - lat) / np.abs(im_geotrans[5]))
        col = math.floor((lon - im_geotrans[0]) / im_geotrans[1])
        return row, col
    #写入excel
    def get_ref_excel(data, im_geotrans):
        wbook = Workbook()
        book = wbook.create_sheet(0)
        for i in range(data.shape[0]):
            lat = im_geotrans[3] + i*im_geotrans[5]
            col = 2
            for j in range(data.shape[1]):
                lon = im_geotrans[0] + j*im_geotrans[1]
                
                book.cell(row=i+2, column=1).value = lat
                book.cell(row=1, column=col).value = lon
                book.cell(row=i+2, column=col).value = data[i,j]
                col += 1
        wbook.save(os.path.join(base_dir, '201812_sm.xlsx'))
        
        
    #输出modis数据
    def writeRSData(filename, im_data, im_geotrans, im_proj): #将数据写入Tif文件
        path, name = os.path.split(filename)
        if not os.path.exists(path):
            os.makedirs(path)
            
        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  # 多维或1.2维
            
        driver = gdal.GetDriverByName("GTiff")            #数据类型必须有,因为要计算需要多大内存空间
        dataset = driver.Create(filename, 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
        
    #读取图像
    #ref_file, im_geotrans_ref, im_proj_ref分别为图像数据,六参数和投影
    ref_file, im_geotrans_ref, im_proj_ref = getData(r'data\\200201_month_p.tif')
    extract_file, im_geotrans_c, im_proj_c = getData(r'data\\200201_1month_NDVI.tif')
    
    #创建一个excel表
    #sheet工作表的集合
    wbook = Workbook()
    # row 行 或 column 列的一维集合
    book = wbook.create_sheet(0)
    
    #列表化图像的仿射变换参数
    im_geotrans_ref = list(im_geotrans_ref)
    im_geotrans_c = list(im_geotrans_c)
    print(im_geotrans_ref)
    
    #get_ref_excel(ref_file, im_geotrans_ref) 输出modis数据,不需要的话就注释掉
    
    #tqdm是 Python 进度条库,可以在 Python长循环中添加一个进度提示信息。
    #ref_file.shape[0]代表行数,ref_file.shape[1]代表列数
    #遍历行(经度)
    for i in tqdm(range(ref_file.shape[0]), desc='提取数据'):
        #读取经度(左上角初始经度,每次偏移一个像素点)
        lat = im_geotrans_ref[3] + i*im_geotrans_ref[5]
        col = 2
        #遍历列(维度)
        for j in range(ref_file.shape[1]):
            #读取经度(左上角初始维度,每次偏移一个像素点)
            lon = im_geotrans_ref[0] + j*im_geotrans_ref[1]
            #计算出array中对应的值的位置
            row_c = math.floor(np.abs(im_geotrans_c[3] - lat) / np.abs(im_geotrans_c[5]))
            col_c = math.floor(np.abs(lon - im_geotrans_c[0]) / np.abs(im_geotrans_c[1]))
            #填写维度,第一列的那些数据
            book.cell(row=i+2, column=1).value = lat
            #填写经度,第一行的数据
            book.cell(row=1, column=col).value = lon
            #填写经纬度对应的值
            book.cell(row=i+2, column=col).value = extract_file[row_c, col_c]
            col += 1
    print(base_dir)
    wbook.save(os.path.join(base_dir, '200201_ndvi_1month.xlsx'))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    导出为图片

    # coding=GBK
    from osgeo import gdal
    import pandas
    import numpy as np
    
    csv_data = pandas.read_csv('200201_ndvi_month.csv')#CSV所在位置
    np_data = np.array(csv_data)
    print(np_data)
    #np_data[np_data == -9999] = np.nan
    b4dataset = gdal.Open('200201_month_p.tif')#投影信息——将现有投影信息赋给将要生成的tif
    im_geotrans = b4dataset.GetGeoTransform()  # 获取仿射矩阵信息
    im_proj = b4dataset.GetProjection()  # 获取投影信息
    datatype = gdal.GDT_Float64
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create('200201_ndvi_month.tif', np_data.shape[1], np_data.shape[0], 1, datatype)
    #tif影像存放位置
    dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
    dataset.SetProjection(im_proj)  # 写入投影
    dataset.GetRasterBand(1).WriteArray(np_data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    基于arcpy

    将要提取的坐标转为点数据,调用arcpy的值提取到点工具执行,然后将结果导出为表格

    # coding=GBK
    #读取坐标
    lines = open('point_inform.csv','r')
    i=1
    for line in lines:
        if(i==1):
            lats=line.strip('\n').strip(',').split(',')
        else:
            lons=line.strip('\n').split(',')
        i=i+1
    #将坐标输出为csv文件
    fo = open('point.csv','w')
    fo.writelines('ID,lon,lat\n')
    fo.close()
    i=1
    fo = open('point.csv','a')
    for lat in lats:
        for lon in lons:
            line=str(i)+','+lon+','+lat
            fo.writelines(line+'\n')
            i=i+1
    fo.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    # coding=GBK
    
    import arcpy
    from arcpy import env
    arcpy.CheckOutExtension('Spatial')
    data_path="pythonProject\\"
    image_path="pythonProject\data\\"
    arcpy.env.workspace = "pythonProject\\数据库.gdb"
    #可以覆盖已有要素
    env.overwriteOutput = True
    '''
    #转点要素
    arcpy.MakeXYEventLayer_management(data_path+"point.csv", "lon", "lat", "point_t","WGS 1984 UTM Zone 50N.prj")
    arcpy.FeatureToPoint_management ("point_t","point")
    #从NDVI提取值
    arcpy.sa .ExtractValuesToPoints ("point",image_path+'200201_1month_NDVI.tif',"point_value")
    '''
    #获取经纬度信息
    lines = open(data_path+'point_inform.csv','r')
    i=1
    for line in lines:
        #维度
        if(i==1):
            lats=line.strip('\n').strip(',').split(',')
            lats_len=len(lats)
        #经度
        else:
            lons=line.strip('\n').strip(',').split(',')
            lons_len = len(lons)
        i=i+1
    lines.close()
    #写入其余行
    cursor = arcpy.SearchCursor("point_value")
    fo = open('200201_ndvi_month.csv','w')
    n=0
    i=0
    line=''
    for row in cursor:
        if(line==''):
            line= str(row.getValue("RASTERVALU"))
        else:
            line=line +','+ str(row.getValue("RASTERVALU"))
        n=n+1
        if(n==lons_len):
            fo.writelines(line+'\n')
            n=0
            i=i+1
            if(i==lats_len):
                break
            line=''
    fo.close()
    '''
    #写入表格第一行
    fo = open('200201_ndvi_month.csv','w')
    line=' '
    for lon in lons:
        line=line+','+lon
    fo.writelines(line+'\n')
    fo.close()
    #写入其余行
    cursor = arcpy.SearchCursor("point_value")
    fo = open('200201_ndvi_month.csv','a')
    n=1
    i=0
    line=lats[i]
    for row in cursor:
        line=line +','+ str(row.getValue("RASTERVALU"))
        n=n+1
        if(n==lons_len):
            fo.writelines(line+'\n')
            n=1
            i=i+1
            if(i==lats_len):
                break
            line=lats[i]
    fo.close()
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
  • 相关阅读:
    图书管理系统的分析与设计
    滴滴可观测平台 Metrics 指标实时计算如何实现了又准又省?
    log4j:WARN No appenders could be found for logger
    “数聚瑞安 · 创新未来”中国·瑞安第四届创新创业大赛角逐火热,初赛结果已公布!
    腾讯云【Hiflow】新时代自动化工具
    基于HTML美食餐饮文化项目的设计与实现 HTML学生网页设计作业 计算机毕业设计 HTML+CSS+JavaScript
    回溯算法的了解
    Python 机器学习入门之线性回归
    echarts、dataV 数据可视化大屏
    java-php-python-springboot网上教学系统计算机毕业设计
  • 原文地址:https://blog.csdn.net/xza13155/article/details/126278899