1. 程式人生 > >計算異質性H值(運用arcgis和Python進行區域分析)

計算異質性H值(運用arcgis和Python進行區域分析)

最近需要對ecognition分割結果進行統計分析,以此來進一步判斷其分割結果中的欠分割和過分割物件,在看了一篇論文後,發現了可以用一個引數H來判斷每個切割物件的異質性,由於此方法需要用到arcgis和Python來配合,因此記錄下。

公式大概如下:

從中可以看出,如果需要計算出引數H,我們需要先計算出每個物件的歸一化方差和歸一化的莫蘭指數。

在計算必須的引數前,我們需要準備的資料包括:

1.原始遙感影象

2.運用ecognition進行切割後產生的標籤檔案和向量檔案(shp檔案)。

下面開始進行操作:

1.開啟arcgis,匯入向量檔案和標籤檔案,以及原始遙感影象。

2.呼叫分割槽統計工具,輸入引數同上,計算出每個區域對應的標準差,輸出格式為tif格式(也就是標籤圖那樣的形式)。

3.將上一步中生成的標準差的影象檔案路徑輸入到Python程式碼中,進行處理。(這裡一定要記住生成的檔案是帶有空間參考系的,需要用GDAL庫進行讀取儲存操作)。

這裡我在網上找了一個人家編號的讀取和儲存函式,可以進行呼叫:

from osgeo import gdal


class IMAGE:
    # 讀影象檔案
    def read_img(self, filename):
        dataset = gdal.Open(filename)  # 開啟檔案
        im_width = dataset.RasterXSize  # 柵格矩陣的列數
        im_height = dataset.RasterYSize  # 柵格矩陣的行數
        im_bands = dataset.RasterCount  # 波段數
        im_geotrans = dataset.GetGeoTransform()  # 仿射矩陣,左上角畫素的大地座標和畫素解析度
        im_proj = dataset.GetProjection()  # 地圖投影資訊,字串表示
        im_data = dataset.ReadAsArray(0, 0, im_width, im_height)

        del dataset

        return im_width, im_height, im_bands, im_proj, im_geotrans, im_data

    # 寫GeoTiff檔案
    def write_img(self, filename, im_proj, im_geotrans, im_data):

        # 判斷柵格資料的資料型別
        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

        # 建立檔案
        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

Python將標準差轉為平差同時對影象進行歸一化處理程式碼如下:

from service import IMAGE
import copy
import cv2
import numpy as np

std_var_path = 'data/stardvar.tif'
var_path = 'data/var.tif'

rw = IMAGE()
im_width, im_height, im_bands, im_proj, im_geotrans, im_data = rw.read_img(std_var_path)

var = copy.deepcopy(im_data)
rows, cols = im_data.shape

for row in range(rows):
    for col in range(cols):
        var[row][col] = im_data[row][col]**2

var = cv2.normalize(var,var,0,1,norm_type=cv2.NORM_MINMAX)            # 方差歸一化


rw.write_img(var_path,im_proj,im_geotrans,var)

print('transform success!')

4.上面步驟計算出了歸一化的方差資料,剩下的就是計算出歸一化後的莫蘭指數引數,moran指數引數是描述空間相關性的引數,進行計算的時候每個區域都要有一個指標才可以進行計算,本次記錄中,我計算了每個區域的灰度的均值作為這個指標引數。

具體方法為:運用工具箱中的以“表格顯示分割槽統計“工具,以shp檔案為要素區域檔案,原始遙感影像為賦值影象(軟體會自動轉為灰度圖進行處理),選擇欄位為FID,保證唯一性。

5.上述操作最終會生成一個表格形式的檔案,如下圖所示:

我們需要將運用到這個表格中的mean引數,但是對於計算moran指數的工具來說,輸入只能是shp向量檔案,因此我們需要將mean這一欄位放到向量檔案中,可以在向量檔案欄位表格中將兩個表格進行連線操作。

以FID為連線欄位(因為每個物件對應唯一的FID,方便進行確認),連線設定過程以及結果如下:

6.有了以上的帶有均值欄位的向量檔案,我們便可以進行區域性莫蘭指數的計算啦(如果是全域性莫蘭指數見我以前寫的一篇吧),開啟工具箱中的聚類和異常值分析工具,輸入引數如下(記得一定要選擇標準化!!!):

最終會輸出一個記錄莫蘭指數的tif檔案,和記錄歸一化方差的tif圖一樣。

7.完成以上操作,我們所需要的資料便都準備好啦,下面需要的就是開始計算H引數,這一步驟我在Python中執行,同樣,根據程式碼自己修改路徑就行啦。

from service import IMAGE
import copy
import cv2
import numpy as np

# 通過歸一化莫蘭指數和歸一化物件內方差計算H引數
# 後期提高效率可以通過標籤圖來統一修改圖片
moran_path = 'data/moranout.tif'
var_path = 'data/var.tif'
H_path = 'data/H.tif'

rw = IMAGE()
moran_width, moran_height, moran_bands, moran_proj, moran_geotrans, moran_data = rw.read_img(moran_path)

var_width, var_height, var_bands, var_proj, var_geotrans, var_data = rw.read_img(var_path)

'''rows, cols = moran_data.shape
H_data = np.zeros_like(var_data)

for row in range(rows):
    for col in range(cols):
        nV = var_data[row][col]
        nLMI = moran_data[row][col]
        H_data[row][col] = (nV-nLMI)/(nV+nLMI)
        print(H_data[row][col],nV,nLMI)'''

H_data = (var_data-moran_data)/(var_data+moran_data)


rw.write_img(H_path,var_proj,var_geotrans,H_data)

print('H calculate completed!')

最終會生成一個記錄H引數數值的tif標記圖,達成目的。

 

 

以上便是我計算H引數的步驟,如果大家有更好的方法,希望及時告訴