超大影像柵格轉矢量快速實現

      距離上一次博客更新,起碼又是大半年,時光飛逝,我也已經老了。。。這一次,我解決了一個工程上的小問題,可能在行家看來簡單,但是呢,它好像又沒那麼簡單,就是我們通常用的柵格轉矢量,

我們知道柵格轉矢量,通常有以下方法:採用Arcgis進行柵格轉矢量,然後工程化呢,就用arcpy實現,就可以了,或者用qgis,原理也差不多,編程的話,繞不過去的,當然是GDAL,這個大家都是直接

調用GDAL的柵格轉矢量API就完事了,對於小數據,或者幾百MB這種數據效率也不錯,問題不大,但是當你的數據規模達到幾個G,或者幾百個G之後,在涉密的單機上,你怎麼解決,只能重寫,我這裏

採用GDAL從源碼層實現了超大影像的柵格轉矢量,相比於直接調用GDAL的函數接口實現,效率要高太多了,我們看一下柵格轉矢量的實現代碼:

 1 def RasterToPoly(rasterName, shpName):
 2     """
 3         柵格轉矢量
 4         :param rasterName: 輸入分類後的柵格名稱
 5         :param shpName: 輸出矢量名稱
 6         :return:
 7    """
 8     inraster = gdal.Open(rasterName)  # 讀取路徑中的柵格數據
 9     inband = inraster.GetRasterBand(1)  # 這個波段就是最後想要轉爲矢量的波段,如果是單波段數據的話那就都是1
10     prj = osr.SpatialReference()
11     prj.ImportFromWkt(inraster.GetProjection())  # 讀取柵格數據的投影信息,用來爲後面生成的矢量做準備
12 
13     outshp = shpName
14     drv = ogr.GetDriverByName("ESRI Shapefile")
15     if os.path.exists(outshp):  # 若文件已經存在,則刪除它繼續重新做一遍
16         drv.DeleteDataSource(outshp)
17     Polygon = drv.CreateDataSource(outshp)  # 創建一個目標文件
18     Poly_layer = Polygon.CreateLayer(shpName[:-4], srs=prj, geom_type=ogr.wkbMultiPolygon)  # 對shp文件創建一個圖層,定義爲多個面類
19     newField = ogr.FieldDefn('Value', ogr.OFTReal)  # 給目標shp文件添加一個字段,用來存儲原始柵格的pixel value
20     Poly_layer.CreateField(newField)
21 
22     gdal.FPolygonize(inband, None, Poly_layer, 0)  # 核心函數,執行的就是柵格轉矢量操作
23     Polygon.SyncToDisk()
24     Polygon = None
25 
26     deleteBackground(shpName, 0)  # 刪除背景    

 然後轉成矢量後,有一些Nodata圖層需要刪掉,調用如下代碼解決:

def deleteBackground(shpName, backGroundValue):
    """
    刪除背景,一般背景的像素值爲0
    """
    driver = ogr.GetDriverByName('ESRI Shapefile')
    pFeatureDataset = driver.Open(shpName, 1)
    pFeaturelayer = pFeatureDataset.GetLayer(0)
    strValue = backGroundValue

    strFilter = "Value = '" + str(strValue) + "'"
    pFeaturelayer.SetAttributeFilter(strFilter)
    pFeatureDef = pFeaturelayer.GetLayerDefn()
    pLayerName = pFeaturelayer.GetName()
    pFieldName = "Value"
    pFieldIndex = pFeatureDef.GetFieldIndex(pFieldName)

    for pFeature in pFeaturelayer:
        pFeatureFID = pFeature.GetFID()
        pFeaturelayer.DeleteFeature(int(pFeatureFID))

    strSQL = "REPACK " + str(pFeaturelayer.GetName())
    pFeatureDataset.ExecuteSQL(strSQL, None, "")
    pFeatureLayer = None
    pFeatureDataset = None

 我們來看一下時間對比情況(影像大小爲9G):

實現平臺 時間
GDAL 柵格轉矢量API 1小時43分鐘
改進後API 3分45秒

 當然,我沒有用高性能服務器跑,用的是家裏的一臺普通臺式機,CPU爲AMD 3600,(這裏我要插一句,AMD YES!!!乾死intel)。12個核心全部跑起來,執行效率真的是相當驚人。

好吧,沒圖我說什麼(這是南京地區的高分辨率二值圖影像,感謝南京朋友提供,我也忘記他的名字了。。):

 

 

            圖 1  轉換後的矢量

從這個來看,結果還是不錯的。如果想技術交流或源碼,QQ:1044625113,請備註超大影像處理

最後,我想說幾句心裏話,我其實挺討厭寫那種狗屁論文的,啥用沒有,就在哪裏講故事,吹牛逼,我之前也幹過這種事,包括現在也在幹這種事,唉,沒辦法,其實很多其他東西遠遠比

發論文重要的多,比如這種超大影像轉矢量問題,其實還有很多其他工程問題,有待我們去解決的。比如瀋陽的李國春老師做的事情,其實我很欣賞的,一句話來總結我的觀點:“talk is cheap, show me your code.”

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章