python+gdal+遙感圖像拼接(mosaic)的實(shí)例
作為攝影測(cè)量與遙感的從業(yè)者,筆者最近開(kāi)始深入研究gdal,為工作打基礎(chǔ)!個(gè)人覺(jué)得gdal也是沒(méi)有什么技術(shù)含量,調(diào)用別人的api。但是想想這也是算法應(yīng)用的一個(gè)技能,多學(xué)無(wú)害!
關(guān)于遙感圖像的鑲嵌,主要分為6大步驟:
step1:
1)對(duì)于每一幅圖像,計(jì)算其行與列;
2)獲取左上角X,Y
3)獲取像素寬和像素高
4)計(jì)算max X 和 min Y,切記像素高是負(fù)值
maxX1 = minX1 + (cols1 * pixelWidth)minY1 = maxY1 + (rows1 * pixelHeight)
step2 :計(jì)算輸出圖像的min X ,max X,min Y,max Y
minX = min(minX1, minX2, …)maxX = max(maxX1, maxX2, …)
y坐標(biāo)同理
step3:計(jì)算輸出圖像的行與列
cols = int((maxX ? minX) / pixelWidth)rows = int((maxY ? minY) / abs(pixelHeight)
step 4:創(chuàng)建一個(gè)輸出圖像
driver.create()
step 5:
1)計(jì)算每幅圖像左上角坐標(biāo)在新圖像的偏移值
2)依次讀入每幅圖像的數(shù)據(jù)并利用1)計(jì)算的偏移值將其寫(xiě)入新圖像中
step6 :對(duì)于輸出圖像
1)刷新磁盤(pán)并計(jì)算統(tǒng)計(jì)值
2)設(shè)置輸出圖像的幾何和投影信息
3)建立金字塔
下面附上筆者的代碼:
#mosica 兩張圖像import os, sys, gdalfrom gdalconst import *os.chdir(’c:/temp/****’)#改變文件夾路徑# 注冊(cè)gdal(required)gdal.AllRegister()# 讀入第一幅圖像ds1 = gdal.Open(’**.img’)band1 = ds1.GetRasterBand(1)rows1 = ds1.RasterYSizecols1 = ds1.RasterXSize# 獲取圖像角點(diǎn)坐標(biāo)transform1 = ds1.GetGeoTransform()minX1 = transform1[0]maxY1 = transform1[3]pixelWidth1 = transform1[1]pixelHeight1 = transform1[5]#是負(fù)值(important)maxX1 = minX1 + (cols1 * pixelWidth1)minY1 = maxY1 + (rows1 * pixelHeight1)# 讀入第二幅圖像ds2 = gdal.Open(’**.img’)band2 = ds2.GetRasterBand(1)rows2 = ds2.RasterYSizecols2 = ds2.RasterXSize# 獲取圖像角點(diǎn)坐標(biāo)transform2 = ds2.GetGeoTransform()minX2 = transform2[0]maxY2 = transform2[3]pixelWidth2 = transform2[1]pixelHeight2 = transform2[5]maxX2 = minX2 + (cols2 * pixelWidth2)minY2 = maxY2 + (rows2 * pixelHeight2)# 獲取輸出圖像坐標(biāo)minX = min(minX1, minX2)maxX = max(maxX1, maxX2)minY = min(minY1, minY2)maxY = max(maxY1, maxY2)#獲取輸出圖像的行與列cols = int((maxX - minX) / pixelWidth1)rows = int((maxY - minY) / abs(pixelHeight1))# 計(jì)算圖1左上角的偏移值(在輸出圖像中)xOffset1 = int((minX1 - minX) / pixelWidth1)yOffset1 = int((maxY1 - maxY) / pixelHeight1)# 計(jì)算圖2左上角的偏移值(在輸出圖像中)xOffset2 = int((minX2 - minX) / pixelWidth1)yOffset2 = int((maxY2 - maxY) / pixelHeight1)# 創(chuàng)建一個(gè)輸出圖像driver = ds1.GetDriver()dsOut = driver.Create(’mosiac.img’, cols, rows, 1, band1.DataType)#1是bands,默認(rèn)bandOut = dsOut.GetRasterBand(1)# 讀圖1的數(shù)據(jù)并將其寫(xiě)到輸出圖像中data1 = band1.ReadAsArray(0, 0, cols1, rows1)bandOut.WriteArray(data1, xOffset1, yOffset1)#讀圖2的數(shù)據(jù)并將其寫(xiě)到輸出圖像中data2 = band2.ReadAsArray(0, 0, cols2, rows2)bandOut.WriteArray(data2, xOffset2, yOffset2)’’’ 寫(xiě)圖像步驟’’’# 統(tǒng)計(jì)數(shù)據(jù)bandOut.FlushCache()#刷新磁盤(pán)stats = bandOut.GetStatistics(0, 1)#第一個(gè)參數(shù)是1的話(huà),是基于金字塔統(tǒng)計(jì),第二個(gè)#第二個(gè)參數(shù)是1的話(huà):整幅圖像重度,不需要統(tǒng)計(jì)# 設(shè)置輸出圖像的幾何信息和投影信息geotransform = [minX, pixelWidth1, 0, maxY, 0, pixelHeight1]dsOut.SetGeoTransform(geotransform)dsOut.SetProjection(ds1.GetProjection())# 建立輸出圖像的金字塔gdal.SetConfigOption(’HFA_USE_RRD’, ’YES’)dsOut.BuildOverviews(overviewlist=[2,4,8,16])#4層
補(bǔ)充知識(shí):運(yùn)用Python的第三方庫(kù):GDAL進(jìn)行遙感數(shù)據(jù)的讀寫(xiě)
0 背景及配置環(huán)境
0.1 背景
GDAL(Geospatial Data Abstraction Library)是一個(gè)在X/MIT許可協(xié)議下的開(kāi)源柵格空間數(shù)據(jù)轉(zhuǎn)換庫(kù)。它利用抽象數(shù)據(jù)模型來(lái)表達(dá)所支持的各種文件格式。它還有一系列命令行工具來(lái)進(jìn)行數(shù)據(jù)轉(zhuǎn)換和處理。
這個(gè)開(kāi)源柵格空間數(shù)據(jù)轉(zhuǎn)換庫(kù)擁有許多和其他語(yǔ)言的接口,對(duì)于python,他有對(duì)應(yīng)的第三方包GDAL,下載安裝已在上篇文章中提到。
目的: 可以使用Python的第三方包:GDAL進(jìn)行遙感數(shù)據(jù)的讀寫(xiě),方便批處理。
0.2 配置環(huán)境
電腦系統(tǒng): win7x64Python版本: 3.6.4GDAL版本: 2.3.2
1 讀
1.1 TIFF格式
標(biāo)簽圖像文件格式(Tag Image File Format,簡(jiǎn)寫(xiě)為T(mén)IFF)是一種靈活的位圖格式,主要用來(lái)存儲(chǔ)包括照片和藝術(shù)圖在內(nèi)的圖像。它最初由Aldus公司與微軟公司一起為PostScript打印開(kāi)發(fā)。TIFF與JPEG和PNG一起成為流行的高位彩色圖像格式。
TIFF文件以.tif為擴(kuò)展名。
def tif_read(tifpath, bandnum): ''' Use GDAL to read data and transform them into arrays. :param tifpath:tif文件的路徑 :param bandnum:需要讀取的波段 :return:該波段的數(shù)據(jù),narray格式。len(narray)是行數(shù),len(narray[0])列數(shù) ''' image = gdal.Open(tifpath) # 打開(kāi)該圖像 if image == None: print(tifpath + '該tif不能打開(kāi)!') return lie = image.RasterXSize # 柵格矩陣的列數(shù) hang = image.RasterYSize # 柵格矩陣的行數(shù) im_bands = image.RasterCount # 波段數(shù) im_proj = image.GetProjection() # 獲取投影信息 im_geotrans = image.GetGeoTransform() # 仿射矩陣 print(’該tif:{}個(gè)行,{}個(gè)列,{}層波段, 取出第{}層.’.format(hang, lie, im_bands, bandnum)) band = image.GetRasterBand(bandnum) # Get the information of band num. band_array = band.ReadAsArray(0,0,lie,hang) # Getting data from zeroth rows and 0 columns # band_df = pd.DataFrame(band_array) del image # 減少冗余 return band_array, im_proj, im_geotrans
2 寫(xiě)
2.1 TIFF格式
TIFF格式的數(shù)據(jù)格式有:Byete、int16、uint16、int32、uint32、float32、float64等7余種。
首先,要判斷數(shù)據(jù)的格式,才能按需求寫(xiě)出。
def tif_write(self, filename, im_data, im_proj, im_geotrans): ''' gdal數(shù)據(jù)類(lèi)型包括 gdal.GDT_Byte, gdal.GDT_UInt16, gdal.GDT_Int16, gdal.GDT_UInt32, gdal.GDT_Int32, gdal.GDT_Float32, gdal.GDT_Float64 :param filename: 存出文件名 :param im_data: 輸入數(shù)據(jù) :param im_proj: 投影信息 :param im_geotrans: 放射變換信息 :return: 0 ''' if ’int8’ in im_data.dtype.name: # 判斷柵格數(shù)據(jù)的數(shù)據(jù)類(lèi)型 datatype = gdal.GDT_Byte elif ’int16’ in im_data.dtype.name: datatype = gdal.GDT_UInt16 else: datatype = gdal.GDT_Float32 # 判讀數(shù)組維數(shù) 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維 #創(chuàng)建文件 driver = gdal.GetDriverByName('GTiff') #數(shù)據(jù)類(lèi)型必須有,因?yàn)橐?jì)算需要多大內(nèi)存空間 dataset = driver.Create(filename, im_width, im_height, im_bands, datatype) dataset.SetGeoTransform(im_geotrans) #寫(xiě)入仿射變換參數(shù) dataset.SetProjection(im_proj) #寫(xiě)入投影 if im_bands == 1: dataset.GetRasterBand(1).WriteArray(im_data) #寫(xiě)入數(shù)組數(shù)據(jù) else: for i in range(im_bands): dataset.GetRasterBand(i+1).WriteArray(im_data[i]) del dataset
3 展示
3.1 TIFF格式
# 這個(gè)展示的效果并不是太好,當(dāng)做示意圖用 def tif_display(self,im_data): ''' :param im_data: 影像數(shù)據(jù),narray :return: 展出影像 ''' # plt.imshow(im_data,’gray’) # 必須規(guī)定為顯示的為什么圖像 plt.imshow(im_data) # 必須規(guī)定為顯示的為什么圖像 plt.xticks([]), plt.yticks([]) # 隱藏坐標(biāo)線(xiàn) plt.show() # 顯示出來(lái),不要也可以,但是一般都要了
以上這篇python+gdal+遙感圖像拼接(mosaic)的實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. PHP字符串前后字符或空格刪除方法介紹2. html小技巧之td,div標(biāo)簽里內(nèi)容不換行3. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法4. nestjs實(shí)現(xiàn)圖形校驗(yàn)和單點(diǎn)登錄的示例代碼5. python開(kāi)發(fā)飛機(jī)大戰(zhàn)游戲6. laravel ajax curd 搜索登錄判斷功能的實(shí)現(xiàn)7. 以PHP代碼為實(shí)例詳解RabbitMQ消息隊(duì)列中間件的6種模式8. css進(jìn)階學(xué)習(xí) 選擇符9. Echarts通過(guò)dataset數(shù)據(jù)集實(shí)現(xiàn)創(chuàng)建單軸散點(diǎn)圖10. python實(shí)現(xiàn)自動(dòng)化辦公郵件合并功能
