【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'))

导出为图片

# 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)

基于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()
# 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()
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕南路GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值