余詠勝,易桂軒,尹言軍,高雅冰
(武漢市測繪研究院,湖北 武漢 430022)
近年來,無人機航空攝影技術發展迅速,因其具有精度高、速度快、成本低等優勢,已成為空間數據獲取的一種重要手段,在城市規劃、國土資源管理、農林監測、災害應急等諸多領域廣泛應用[1]。采用無人機設備進行航空攝影時,部分數碼相機可以直接獲取攝影時GPS定位信息,也有較多相機不能直接獲取定位信息,需要輔助POS等相關設備才能得到攝影時的位置和姿態信息。對于后一種情況,一般需要作業員根據需要將影像和定位信息進行關聯處理。
通常POS數據是以文本文件方式提供,作業員需要根據不同的無人機數據處理系統所要求的數據格式進行整理,將指定路徑下影像文件和定位信息逐一關聯,輸入的任何字符遺漏、大小寫錯誤或路徑變更等問題都會導致數據導入失敗,需要反復檢查修改,給后續無人機影像自動化處理工作帶來極大不便。本文針對這些問題,提出了基于Exif信息的無人機影像定位信息處理方法,并在Python環境下對該數據處理方法進行了程序實現。
Exif是Exchangeable Image File(可交換圖像文件)的縮寫,它是由日本電子工業發展協會(JEIDA)制定的相機文件設計標準,用來記錄攝影時的各種狀態參數[2,3]。Exif信息包含了TIFF/JPEG等圖像文件格式的攝影參數信息,它將攝影時的光圈、快門、白平衡等參數信息、相機品牌型號、圖像尺寸、攝影時間以及GPS定位等信息以文件頭形式存儲在TIFF/JPEG文件中,在Windows系統中可以通過文件屬性查看圖像的詳細Exif信息。
以JPEG文件為例,影像文件由標記塊組成,每個標記塊由2字節標記碼0xFFXX標記描述信息,所有JPEG文件都是以0xFFD8表示圖像開始(SOI),0xFFD9表示圖像結束(EOI),其中0xFFE0~0xFFEF之間的標記稱為應用標記。JPEG文件常用的應用標記有Jfif和Exif兩種類型,Jfif使用APP0(0xFFE0)應用標記來插入數碼相機的配置信息和縮略圖信息,為了避免與Jfif信息沖突,Exif使用APP1(0xFFE1)來標記信息。Exif標記記錄的攝影信息更加全面,目前除部分老式數碼相機采用Jfif應用標記外,主流的數碼相機均使用Exif規范來存儲攝影相關參數信息。
Exif信息以IFD結構方式保存,APP1應用標記中包含2個IFD結構:IFD0用來存儲主圖的元數據信息,IFD1用來存儲縮略圖的元數據信息。IFD0除了包含常規攝影參數信息外,還包括Sub IFD項(包含Interoperability IFD和MakerNote IFD子項)和GPS IFD項,其中GPS IFD項就是用來存儲圖像的GPS定位相關信息,GPS信息的標簽值、字段名稱和類型等參數如表1所示。部分無人機攝影時,數碼相機可通過Exif信息直接記錄攝影瞬間影像的GPS相關信息。

GPS屬性信息表 表1

續表1
值得注意的是,應用標記并不是JPEG圖像解碼的必要標記信息,通過Photoshop等圖像處理軟件編輯過的影像可能會刪除APP0或APP1標記,同時插入APP2(ICC色彩配置)、APP13(Photoshop IRB圖像資源)、APP14(Adobe標識)等應用標記,從而造成Jfif/Exif信息的丟失。
Python是一種面向對象的解釋型程序設計語言,首次公開發行是1991年,經過二十多年的發展,Python已成為廣泛應用的編程語言之一。從ArcGIS 9開始,Python作為使用ArcObject空間處理框架的腳本語言與軟件其他組件一起自動安裝到計算機系統上[4]。Python程序不需要像其他編程語言那樣編譯成二進制代碼即可運行,同時還可以通過標準庫和第三方擴展庫拓展其應用領域,ArcGIS軟件缺省安裝的Python是2.7版本。
在Python中操作影像文件的Exif信息需要使用pyexiv2第三方擴展,該擴展庫是C++程序庫exiv2的綁定,用于操作Exif、IPTC和XMP圖像元數據等信息。通過pyexiv2擴展庫,程序可以自動定位到GPS IFD塊,并根據表1中的GPS屬性字段名稱獲取所需的GPS信息。在Python中調用pyexiv2擴展庫的函數,需要使用以下代碼:
from pyexiv2 import *
在讀取影像文件的GPS信息之前,必須通過GPSTag標簽判斷GPS信息是否存在,然后根據GPS屬性字段名稱獲取對應的GPS定位信息。根據影像文件的Exif信息讀取攝影時經度、緯度和高程值等信息的相關代碼如下:
dms2deg=lambda lst:float(lst[0])+float(lst[1])/60.+ float(lst[2])/3600.
im=ImageMetadata(r'd: est.jpg')
im.read()
if "Exif.Image.GPSTag" in im.exif_keys:
lst1=im["Exif.GPSInfo. GPSLongitude"].value
lng=dms2deg(lst1)
lst2=im["Exif.GPSInfo.GPSLatitude"].value
lat=dms2deg(lst2)
alt=float(im["Exif.GPSInfo. GPSAltitude"].value)
通過Exif.GPSInfo標簽返回的經緯度數值為度分秒形式的字符串列表,必須將字符串轉換為浮點數值后再換算成小數度形式,方便后續矢量要素生成等操作。
無人機航空攝影完成后,往往需要快速地將像主點位置疊加到工作底圖上,檢查航線分布和重疊度等飛行質量。在完成影像文件的GPS信息提取后,還需要將定位信息轉換成ESRI Shapefile文件,方便后續檢查處理,相關代碼如下:
import arcpy
arcpy.CreateFeatureclass_management('d:\','test.shp','point')
rows=arcpy.da.InsertCursor(shpPathName,["SHAPE@"])
rows.insertRow([[lng,lat]])
del rows
以上代碼僅完成了單幅影像經緯度坐標的寫入,對于多幅航空影像,只需要進行一次簡單的循環遍歷即可完成所有的操作。在Shapefile文件中,還可以將影像文件名、高程值、攝影時間等相關信息作為屬性字段加入矢量文件中,使檢查工作更加便捷、高效。
很多情況下,無人機攝影獲取的影像數據沒有附加GPS信息,相關定位信息通常以文本文件形式單獨提供,給后續的影像位置關聯和數據處理帶來不便。對于不包含任何Exif信息的影像文件來說,必須先進行APP1應用標記插入,再將IFD0結構和GPS IFD結構嵌入影像文件后才能進行GPS相關信息寫入操作。
GPS標簽是Exif標準的一部分,將GPS信息寫入影像時,必須設置GPSLatitude、 GPSLatitudeRef、GPSLongitude、GPSLongitudeRef、GPSAltitude和GPSAltitudeRef等標簽。其中,GPSLatitudeRef 標簽值只能取字符“N”或“S”表示北緯或南緯,GPSLongitudeRef 標簽值只能取字符“E”或“S”表示東經或西經,GPSLatitudeRef 標簽值只能取數字“0”或“1”表示高于或低于海平面的高程值。經緯度和高程值不能直接使用浮點型數值,必須采用有理型數值,其中GPSLatitude和GPSLongitude使用三個有理型分別表示度、分、秒數值,GPSAltitude使用一個有理型表示高程值。Python可以通過Rational(n,d)函數實現有理型數值的生成,其中n表示有理數的分子,d表示分母,分母通常為1或10的指數倍。GPS信息中的其他屬性標簽值可以根據實際需要進行取舍,典型的GPS信息寫入影像文件的程序代碼如下:
im=ImageMetadata(r'd: est.jpg')
im.read()
im["Exif.Image.GPSTag"]=654
im["Exif.GPSInfo.GPSVersionID"]='2 2 0 0'
im["Exif.GPSInfo.GPSMapDatum"]="WGS-84"
lng=(Rational(114,1),Rational(30,1),Rational(30,1))
im["Exif.GPSInfo.GPSLongitude"]=lng
im["Exif.GPSInfo.GPSLongitudeRef"]='E'
lat=(Rational(30,1),Rational(15,1),Rational(15,1))
im["Exif.GPSInfo.GPSLatitude"]=lat
im["Exif.GPSInfo.GPSLatitudeRef"]='N'
im["Exif.GPSInfo.GPSAltitude"]=Rational(alt*1000,1000)
im["Exif.GPSInfo.GPSAltitudeRef"]=0
im.write()
將無人機設備獲取的GPS信息寫入影像文件后,無人機數據處理軟件就可以直接讀取相關定位數據并進行后續處理。
Python支持4種不同的數值類型:int(整型)、long(長整型)、float(浮點型)、complex(復數型),Python內部自動將整數處理為整型和長整型數值。整型數值長度為機器位長,通常為32位,超過這個范圍的整數自動作為長整型處理,長整型對數值的大小沒有限制。Exif信息中支持的GPS坐標采用有理型數值,組成分子和分母的數值必須采用無符號整型數值,長度不超過32位,最大數值不能超過4294967295L。
按照WGS84參考橢球參數,子午線的緯線弧長每1度長度約為 111 km,平行圈的經線弧長僅在赤道附近與子午線弧長大致相等,經線弧長隨緯度的增加而快速減少,每1度長度值從 111 km~0 km不等[5]。因此,當緯度值精確到10-4秒時可以達到毫米級精度,以度為單位時需要精確到10-8度才能達到毫米級精度。根據Exif信息中的有理型計數規則,GPS坐標以有理型度、分、秒數值寫入時可完全滿足毫米級以上的位置精度,當GPS坐標以度為單位時分母最大值可取至10-7,即最高可達到分米級精度要求,此時可以不進行度分秒數值轉換而直接使用。例如,當已知緯度值為45.2084028°時,可以直接將緯度值轉換為以下表示形式:
lat1=(Rational(45.2084028e7,1e7),Rational(0,1),Rational(0,1))
如果將緯度值進行度分秒換算,即將以上緯度坐標轉換為45°12'30.25",其坐標值也可以等價地表示為以下形式:
lat2=(Rational(45,1),Rational(12,1),Rational(3025,100))
通常,無人機數據處理軟件如PhotoScan、Pix4D、Smart3D、PixelFactory等處理影像數據時,可以直接通過影像的Exif信息讀取影像的GPS定位信息,不需要IMU數據和人工交互式操作即可完成自動數據處理,自動生成正射影像并完成鑲嵌和勻色操作,影像數據成果可以用GIS或RS軟件進行顯示。
本文以Smart3D為平臺,對武漢市東湖綠道范圍內約 15 km2范圍的無人機影像進行了數據處理。Smart3D采用獨特的處理模型,可以根據無人機數據生成基于真實影像的高密度點云,并以此構建具有真實影像紋理的高分辨率實景三維模型。項目影像數據預處理采用本文方法在影像文件中寫入GPS信息,并根據定位信息直接生成Shape file文件便于飛行質量檢查。為提高數據處理效率,項目采用了多臺計算機進行并行處理,本文處理方式可以快速發現并剔除冗余數據,高效進行數據分區部署,提高了整體作業效率。在Smart3D中進行數據分區部署后載入的影像數據情況如圖1所示。
本文以Python的pyexiv2擴展庫為基礎實現了無人機影像數據定位信息的處理。該方法以TIFF/JPEG等圖像文件的Exif信息為GPS定位信息的主要處理對象,實現了影像文件定位信息的讀取和外部GPS定位數據的寫入,并對寫入的GPS坐標精度進行了分析。與常規影像定位信息關聯的處理方式相比,本文處理方法高效、可靠,提高了無人機影像數據自動處理的效率和靈活性,在無人機數據生產中發揮了重要作用。

圖1在Smart3D中分區部署后載入的影像數據