1. 程式人生 > >遙感影像分類(監督分類,最小距離法)

遙感影像分類(監督分類,最小距離法)

在遙感影像中,比較簡單的一種分類方法就是監督分類中的最小距離法,簡單的說,這種方法就是:通過比較影像中各個畫素點與樣本的中心點之間的距離,然後與樣本點進行比較,比較後判斷其屬於哪一類。

由上面介紹可以知道,遙感影像最小距離法監督分類,應該分為兩步:

1、獲取樣本點的值。

2、進行影像分類。

就這兩個步驟進行介紹:

1、獲取樣本點:

在ENVI中,一般選取樣本點使用的是ROI工具;在ERDAS中,一般選取樣本點使用的是AOI工具。由於商業原因,ENVI的ROI檔案是無法直接用記事本(或Notepad)等文字編輯工具開啟的(我只試著用記事本開啟.ROI檔案,沒有嘗試過ERDAS的AOI檔案,所以不清楚ERDAS是怎樣的)。

那麼,怎麼獲取到可以開啟的樣本區呢,我下面就介紹下如何用ENVI的ROI工具拿到可以直接用記事本開啟的樣本區:

1)開啟ENVI軟體,先開啟要分類的影像,為了讓影像中一些地物能夠突出顯示出來,可以選擇不同的波段,我是用5,4,3顯示的,5,4,3看起來容易些。


2)開啟影像之後,在上圖顯示視窗上面又有一串選單,找Tools(工具)下面的Region of Interest(即ROI,就是前面三個單詞的首字母),然後找到它下面的ROI tool...(後面三個省略號很突兀哦,可還是不太明白是幹嘛的,不過不影響操作,所以先忽略掉),這裡怎麼找ROI,我就不詳細敘述了,可以搜尋如何用ENVI選取ROI,

我直接把選取好的樣本點(ENVI教程裡的資料)匯入。


3)下面就將ROI檔案匯出,在上圖中顯示的ROI工具介面中,選擇File,再選擇Outputs ROIs to ASCII,然後儲存出來,就是txt為字尾的可以用編輯器開啟的檔案。開啟之後就是排列非常整齊的描述和數字。


4)下面就是讀取txt檔案了,與普通的讀取txt檔案的方法類似,我們可以通過ROI rgb value後面的花括號裡的數字建立顏色表,從而用來最後區分分類結果。讀取的時候搞清楚每行的關係就可以了,類別的描述是每四行就是一種類別的描述,而樣本點的屬性有ID,X,Y作為空間屬性,B1,B2,B3...Bn表示的是特徵屬性。值得注意的是,樣本點的記錄數字前面沒有分號,可以作為區別的一個標識。

至此,樣本點就讀取完畢了。

因為監督分類中的最小距離分類,是需要知道各類的樣本點中心,所以需要將第1步中的各個類別的樣本點的特徵值求平均,每個波段可以認為是一個特徵。

2、進行影像分類:

在獲取樣本點的時候,使用的還是GDAL中的RasterIO函式。在第1步讀取ROI檔案的時候,就統計出類別數目,然後計算各個畫素點到樣本中心點的距離,判斷各個畫素點到哪個類別的距離最小,即將該畫素點分為哪個類別。那麼就需要用一個標籤記錄各個畫素點的類別,分類完畢後,按照顏色表寫入到影像檔案。

//-------------------------------------開始對影像進行最小距離的分類------------------------------------------------
	
	float *pafScanBlock = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//定義一段用來記錄影象的記憶體值
	float *pafBlockDistancePre = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//定義一段用來記錄與某一個類別的距離
	float *pafBlockDistanceNow = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//記錄與上面距離進行比較的距離

	float *pafScanblockRed = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));		//定義紅色波段的值
	float *pafScanblockGreen = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));		//定義綠色波段的值
	float *pafScanblockBlue = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));		//定義藍色波段的值

	for (int i = 0; i < nImgSizeX*nImgSizeY; i++){
		pafBlockDistanceNow[i] = 0;
		pafBlockDistancePre[i] = 999999999.0;
	}

	int *pafBlockTag = (int *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(int));		//用來標記畫素所屬的類別

	for (int i = 0; i < ClassNumber; i++){
		for (int j = 0; j < BandCount; j++){
			//將某個波段的影像讀取到記憶體裡
			OriginalImg->GetRasterBand(j + 1)->RasterIO(GF_Read, 0, 0, nImgSizeX, nImgSizeY, pafScanBlock, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
			for (int k = 0; k < nImgSizeX*nImgSizeY; k++){
				pafBlockDistanceNow[k] += (pafScanBlock[k] - Average[i][j])*(pafScanBlock[k] - Average[i][j]);
			}
		}
		for (int j_Compare = 0; j_Compare < nImgSizeX*nImgSizeY; j_Compare++){
			if (pafBlockDistanceNow[j_Compare] < pafBlockDistancePre[j_Compare])
			{
				pafBlockTag[j_Compare] = i + 1;
				pafBlockDistancePre[j_Compare] = pafBlockDistanceNow[j_Compare];
				pafBlockDistanceNow[j_Compare] = 0;
			}
		}
	}
	//-----------------------------------------------------------------------------------------------------------------
//----------------------------------輸出分類的結果,將分類的結果輸出到一個影像上---------------------------------------
	float Color[10][3];
	Color[0][0] = 0; Color[0][1] = 139; Color[0][2] = 0;
	Color[1][0] = 0; Color[1][1] = 238; Color[1][2] = 0;
	Color[2][0] = 0; Color[2][1] = 205; Color[2][2] = 0;
	Color[3][0] = 205; Color[3][1] = 104; Color[3][2] = 57;
	Color[4][0] = 255; Color[4][1] = 255; Color[4][2] = 255;
	Color[5][0] = 0; Color[5][1] = 0; Color[5][2] = 200;
	Color[6][0] = 150; Color[6][1] = 0; Color[6][2] = 0;
	Color[7][0] = 0; Color[7][1] = 150; Color[7][2] = 0;
	Color[8][0] = 0; Color[8][1] = 0; Color[8][2] = 150;
	Color[9][0] = 200; Color[3][1] = 0; Color[3][2] = 0;

	for (int i = 0; i < ClassNumber; i++){
		for (int j = 0; j < nImgSizeX*nImgSizeY; j++){
			if (pafBlockTag[j] == i + 1){
				pafScanblockRed[j] = Color[i][0];
				pafScanblockGreen[j] = Color[i][1];
				pafScanblockBlue[j] = Color[i][2];
			}
		}
	}

	GDALDriver *poDriver = (GDALDriver*)GDALGetDriverByName("GTiff");
	GDALDataset *pDstDS = poDriver->Create("Min_DistanceClassify.tif", nImgSizeX, nImgSizeY, 3, GDT_Float32, NULL);

	//定義解析度,方位等空間資訊
	double adfGeoTransform[6] = { 0 };
	OriginalImg->GetGeoTransform(adfGeoTransform);

	pDstDS->SetGeoTransform(adfGeoTransform);				//設定輸出影像的空間資訊
	pDstDS->SetProjection(OriginalImg->GetProjectionRef());		//設定輸出影像的投影資訊


	pDstDS->GetRasterBand(1)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockRed, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
	pDstDS->GetRasterBand(2)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockGreen, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
	pDstDS->GetRasterBand(3)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockBlue, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
至此,遙感影像分類(監督分類,最小距離分類)就介紹完畢,還是比較簡單的分類,想要做的更好,還需要大量的看高手怎麼做,然後模仿,最後再做出自己的方法。


相關推薦

遙感影像分類監督分類距離

在遙感影像中,比較簡單的一種分類方法就是監督分類中的最小距離法,簡單的說,這種方法就是:通過比較影像中各個畫素點與樣本的中心點之間的距離,然後與樣本點進行比較,比較後判斷其屬於哪一類。 由上面介紹可以知道,遙感影像最小距離法監督分類,應該分為兩步: 1、獲取樣本點的值。

【BZOJ2229】[ZJOI2011]網路流割樹

【BZOJ2229】[ZJOI2011]最小割(網路流,最小割樹) 題面 BZOJ 洛谷 題解 戳這裡 那麼實現過程就是任選兩點跑最小割更新答案,然後把點集劃分為和\(S\)聯通以及與\(T\)聯通。 然後再這兩個點集裡面分別任選兩點跑最小割,遞迴下去即可。 #include<iostream

牛客練習賽36 A Rabbit的字符串字符串表示

terminal 一次 har color .com tor mes abc 長度 鏈接:https://ac.nowcoder.com/acm/contest/328/A來源:牛客網 題目描述 Rabbit得到了一個字符串,她的好朋友xxx可以給這個字符串

POJ1422Air Raid二分圖不相交路徑覆蓋

blank cnblogs star with nbsp center 所有 output respond Air Raid Consider a town where all the streets are one-way and each street leads fr

POJ1635 Subway tree systems ——判斷樹的同構樹的表示

systems scan color end cto 同構 while scanf urn   給兩棵有根樹,判斷是否同構。因為同構的樹的最小表示法唯一,那麽用最小表示法表示這兩棵樹,即可判斷同構。順便如果是無根樹的話可以通過選出重心以後套用之前的方法。   AC代碼如下:

【BZOJ2229】[ZJOI2011]網絡流割樹

geo com ext pop != names pro truct str 【BZOJ2229】[ZJOI2011]最小割(網絡流,最小割樹) 題面 BZOJ 洛谷 題解 戳這裏 那麽實現過程就是任選兩點跑最小割更新答案,然後把點集劃分為和\(S\)聯通以及與\(T\)聯

【POJ - 1696】Space Ant 凸包極角排序

題幹: The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet

POJ3258 River Hopscotch 二分值最大化

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The exciteme

Spring框架的事務管理之基於AspectJ的註解方式重點掌握簡單的方式

1. 步驟一:恢復轉賬的開發環境(具體開發環境實現見:https://www.cnblogs.com/wyhluckdog/p/10137283.html)2. 步驟二:applicationContext的基本配置為: <?xml version="1.0" encoding="UTF-8"?

[TJOI2013]攻擊裝置網路流

前言 網路流被hbx吊起來打 Solution 考慮一下這個走法是不是和象棋中馬的走法一模一樣(廢話) 那麼顯然我每一次移動是走三次,如果將棋盤二分圖染色一下,不就是每一次只能走到另一個顏色的嗎? 然後我們題目中求的是最多可以放置多少個裝置,不能夠攻擊,也就是一個裸的二分圖最小割? 直接最大流求一下做個

android動畫之AlphaAnimation漸變動畫簡單的動畫

AlphaAnimation漸變動畫只需要設定從一可見程度,到另一可見程度即可。 示例程式碼: package com.hongchou.www.myalphaanimation; import android.app.Activity; import

2882: 工藝表示

2882: 工藝 Time Limit: 10 Sec Memory Limit: 128 MB Description 小敏和小燕是一對好朋友。 他們正在玩一種神奇的遊戲,叫Minecraft。 他們現在要做一個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的

表示模板洛谷P1368 工藝表示

洛谷題目傳送門 最小表示是指一個字串通過迴圈位移變換(第一個移到最後一個)所能得到的字典序最小的字串。 因為是環狀的,所以肯定要先轉化為序列,把原串倍長。 設決策點為一個表示法的開頭。比較兩個決策點\(i,j\),找到它們的LCP(假設長度為\(k\))。 假設\(s_{i+k}>s_{j+k}

《Oracle PL/SQL開發指南》學習筆記31——原始碼除錯——函式和過程第一部分函式呼叫表示

這節很基礎,卻發現了Oracle的可愛之處,一個函式呼叫就提供了這麼多選項,學起來真夠累的!   1. 在PL/SQL中呼叫函式表示法  SQL> /* Formatted on 2018/12/4 0:08:00 (QP5 v5.256.13226.355

51nod 1282 時鐘 雜湊、字串的表示

題目 題解 要判斷時鐘是否相同,只需將時鐘的指標排序後求出M個距離,然後看距離陣列是否是迴圈同構即可。 迴圈同構: abcd的迴圈同構有:abcd、bcda、cdba、dabc。 要判斷是否迴圈同構,可以求出距離陣列的最小表示。然後對這個最小表示陣

劍指offer第32題把陣列排成的數

題目:輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。 思路: * 考慮到大數問題,先將整型陣列轉換成String陣列,然後將String陣列排序

hdu 5442 Favorite Donutkmp+表示

題意: 有一個len長度的環,問有沒有字典序最大長度為len的串在 這個環裡。 如果有的話,且只有一個 ,輸出其開頭的下標(下標從1 開始) 再輸出0表示順時針(從左至右),1 表示

hdu 1150 Machine Schedule二分圖求點覆蓋

        題意:有兩臺機器,可以分別以n和m種不同的模式執行。有k個任務,每個任務可以在分別在第一臺機器和第二臺機器的兩種模式下完成。每次改變機器的模式需要一定的花費,現在問最少要改變幾次機器

bzoj2882工藝表示

const display 後綴 main while 發現 sam can pen O(nlogn)的做法十分顯然,有三種可以做到O(nlogn)的:1、最容易的想法:把串擴展成兩倍,然後跑一遍SA求後綴數組。2、求後綴同樣也可以用SAM去求解,用map存一下。3、最暴力

史玉柱身邊的打工皇后十二年掙了5個億 那些年我們走過的路每天要處理的事情多如牛毛躲債抵押合作借款很多事情來不及向史玉柱彙報她就必須立刻做出決定把事情分類,先處理重要,最急切的事

  看看這位打工皇后,十二年掙了5個億。1995年20歲的程晨從南京大學畢業加盟了巨人集團。當時巨人集團正好是史玉柱最輝煌的時候,當時產值10個億,史玉柱被福布斯評為內地富豪第八名。 程晨從底層業務員起步,三個月轉正,半年後升為業務主管。她勤奮上進,別人花8小時跑業務