以下代码,可以根据经纬度批量提取遥感影像光谱反射率信息,其实也就是提取特定经纬度的像元值。我找了一幅遥感影像,实验了一下,效果还是可以的,分享一下,如需自取。
实验材料:
1.一幅(也可多幅,不需拼接)经过辐射定标和QUAC大气校正的遥感影像(Landsat8,ENVI处理),包含DAT文件和HDR头文件;
2.一个包含经纬度信息的csv文件(虚拟的点);
如下图所示:
接下来,运行文章末尾的代码,运行过程和结果如下图:
将record文件内的提取内容经过整理后,与ENVI提取的光谱曲线对比,结果一致,如下所示,其中只提取了4个点,因为第5个点是在图像外,被过滤掉了:
注意事项:
1.代码运行过程中对存在于图像边缘的点可能会存在范围上的误判,不过一般不影响结果。对于出现范围误判的点,在结果文件中会有“AN ERROR”字样出现,对个别误判的,手动查一下即可,一般没什么意义。本例中没有误判点,没法演示;
2.代码运行结果文件中包含有很多信息,包括从哪个图像提取了哪些点等等,对于冗余信息,利用excel可以很简单的处理掉,不再赘述;
3.代码运行过程中有很多‘Info:’信息,多关注信息有利于掌握代码运行规律;
4.代码已给出,使用可自取。有任何问题咱们可以一起探讨,
鄙人邮箱:[email protected]
公众号:科研萌新
以下是完整代码:
# -*- coding: utf-8 -*-"""@author:ai wo zhong hua"""from osgeo import gdalfrom osgeo import osrimport osimport numpy as npimport pandas as pdimport timegdal.AllRegister#find all files which end with '.dat'def Filenames(path): f_num = 0 file_list = os.listdir(path) filenames = [] for f in file_list: if f.endswith('.dat'): filenames.append(f) f_num += 1 else: pass print('Info: {} files with suffix .dat were found.'.format(f_num)) return filenames# xy coordinate to lon-lat coordinatedef XY2Lonlat(gcs,pcs,x,y): ct = osr.CoordinateTransformation(pcs,gcs) lon,lat,_ = ct.TransformPoint(x,y) return lon,lat#lon-lat coordinate to xy coordinatedef Lonlat2XY(gcs,pcs,lon,lat): ct = osr.CoordinateTransformation(gcs,pcs) coor = ct.TransformPoint(lon,lat) #coor[0] is lon,coor[1] is lat return coor[0],coor[1]# xy coord to row-coldef XY2Rowcol(extend,x,y): ''' Pay particular attention to whether x and y represent longitude or latitude and how they relate to the index of rows and columns. this is very important! ''' c1 = extend[4] * (x - extend[0]) - extend[1] * (y - extend[3]) c2 = extend[2] * extend[4] - extend[5] * extend[1] c = c1 / c2 r = (x - extend[0] - c * extend[2]) / extend[1] row = int(np.floor(r)) col = int(np.floor(c))# print(extend,c,r,x,y) return col,row #return the x-y coord about image top-left and low-rightdef RectCoor(extend,xsize,ysize): lefttop_x = extend[0] lefttop_y = extend[3] lowright_x = extend[0] + ysize * extend[1] + xsize * extend[2] lowright_y = extend[3] + ysize * extend[4] + xsize * extend[5] return lefttop_x,lefttop_y,lowright_x,lowright_y# read the lon-lat file,return a list of all lon-lat#Determine whether the point is within the range of the imagedef ReadCoordFile(filename,lp_lon,lp_lat,lt_lon,lt_lat): data = pd.read_csv(filename) points = [] p = 0 total_point = len(data.iloc[:,0]) for n in range(total_point): #determine the longitude if data.iloc[n,0] >= lp_lon and data.iloc[n,0] <= lt_lon: #determine the latitude if data.iloc[n,1] >= lt_lat and data.iloc[n,1] <= lp_lat: points.append(('{:.8f}'.format(data.iloc[n,0]),'{:.8f}'.format(data.iloc[n,1]), str(data.iloc[n,2]))) p += 1 else: pass else: pass print('Info: {0} points totally,{1} points in the image range.'.format(total_point,p)) return points#main functiondef main(dat_file_path,csv_file_path): for file in Filenames(dat_file_path): print('Info: Running: {}'.format(file)) stime = time.time() dataset = gdal.Open(dat_file_path + '/' + file) Bands = dataset.RasterCount #bands number Xsize = dataset.RasterXSize #columns Ysize = dataset.RasterYSize #rows# pixel_nums = Xsize * Ysize datatransform = dataset.GetGeoTransform() projection = dataset.GetProjection() pcs = osr.SpatialReference() pcs.ImportFromWkt(projection) gcs = pcs.CloneGeogCS() #get image range:top-left and low-right lefttop_x,lefttop_y,lowright_x,lowright_y = RectCoor(datatransform, Xsize,Ysize) lefttop_lon,lefttop_lat = XY2Lonlat(gcs,pcs,lefttop_x,lefttop_y) lowright_lon,lowright_lat = XY2Lonlat(gcs,pcs,lowright_x,lowright_y) # print(lefttop_lon,lefttop_lat,lowright_lon,lowright_lat) #points that fit the range,return a list points_list = ReadCoordFile(csv_file_path,lefttop_lon, lefttop_lat,lowright_lon,lowright_lat) if points_list: with open(dat_file_path + '/record.txt','a') as record: record.write(file + '') record.write('name'+','+'lon'+','+'lat'+','+'0.443'+','+'0.4826'+','+'0.5613'+',' +'0.6546'+','+'0.8646'+','+'1.609'+','+'2.201'+'') for point in points_list: print('Info: Running {}...'.format(point)) px,py = Lonlat2XY(gcs,pcs,float(point[0]),float(point[1])) row,col = XY2Rowcol(datatransform,px,py) record.write(str(point[2]) + ','+str(point[0])+','+str(point[1])) try: for i in range(1,Bands+1): datarray = dataset.GetRasterBand(i).ReadAsArray() record.write(','+str(datarray[row,col])) except Exception as e: print('ERROR: An error occurred,been recorded in txt:') print('ERROR: {}'.format(e)) record.write(','+'AN ERROR'+'') continue record.write('') pass else: print('Info: {} not contain any point.'.format(file)) etime = time.time() print('Info: Processed Time: {:.4}s'.format(etime - stime)) passif __name__ == '__main__': dat_file_path = 'E:/test' csv_file_path = 'E:/test/lonlat.csv' starttime = time.time() main(dat_file_path,csv_file_path) endtime = time.time() proc_time = endtime - starttime print('------Complete Successfully!------') print(' Total Time: {:.4}s'.format(proc_time))