獲得人生第一桶金對遙感的一些思考

寫blog的原因

前幾天,一位同僚接了一個處理遙感燈光數據的單子,80塊錢,就2個要求,一個是做一個最大值濾波,一個是把小於0的值改成0。要求是用MATLAB做,我其實一開始並沒有學過MATLAB導入遙感影像的知識,我一開始也明白遙感影像有兩個魂,一個是它背後的矩陣,一個是它的地理參考。而如果僅僅用imread的BIF導入的話會把第二個靈魂給丟掉。所以我想用ENVI進行濾波並用band math寫一個邏輯語句賦值,但是同僚給我的影像我用envi打開的時候傻眼了,對方給的是一個灰度圖像,兩個靈魂同時缺失了。
在這裏插入圖片描述
這很明顯是個珠三角的圖,和我做一個小項目的山東省圖疊一起,竟然會有重疊,那麼地理參考就完全沒意義了,就變成了計算機顯示座標系裏的一張圖了。後來同僚和我說,只要負責把MATLAB代碼寫出來,後續就不管它了。

第一個插曲

其實因爲做一些遙感方面的東西的時間長把也不算長,說短也不短,而且如何獲取數據是一個難題,所以我就想研究研究,我去NOAA(美國國家海洋大氣局)搜了搜,但是有些複雜而且時間比較緊我就沒有繼續嘗試找數據了(之前批量下載MODIS數據和批量重投影給了點經驗和動力所以想試試)。

第二個插曲

與其說是同僚接任務不如說我接下了單子,由於是頭天晚上10:30他才和我說這個單子,我其實算法自己早就寫過了於是第二天寫這個代碼其實花了10分鐘就寫完了。

%交互式的獲取文件名與路徑獲取圖像
[filename,path] = uigetfile    %選擇文件獲取路徑和文件名
str = [path,filename];         %合成路徑名與文件名
[A,R]  = geotiffread(str);    %讀取圖像矩陣與地理座標系
[m.n] = size(A);
%濾波部分
for i = 2:m-1
    for j=2:n-1
        near = [A(i-1,j-1),A(i-1,j),A(i-1,j+1),A(i,j-1),A(i,j+1), A(i+1,j-1),A(i+1,j),A(i+1,j+1)];
        near_max = max(near);
        if A(i,j) > 199.89 
            A(i,j) = near_max;               %把大於閾值的變爲鄰域內的最大值
        end
    end
end
%小於0的部分用0替代
for i = 2:m-1
    for j=2:n-1
        if A(i,j)<0
            A(i,j) = 0;              
        end
    end
end
%輸出圖像
geotiffwrite('dengguang.tif',A,R);

用uigetfile實在是逼不得已,因爲從對面給數據以及一些問題來看就知道連絕對路徑和相對路徑都不知道,於是我就想直接讓甲方點文件自動來拿這個路徑和文件名吧,也算給甲方一點方便吧。否則MATLAB圖像如果不在當前文件夾下就需要絕對路徑來讀取。這個最大值濾波其實就是以前數字圖像處理寫的一個很簡單很低效的代碼,而且當時我沒有意識到我忽略了圖像邊緣。
plus:這個geotiffread和geotiffwrite可以把圖像及地理參考給拿出來,也是這次學到的。

第三個插曲

在某節課的上課的時候我突然發現我做這個遍歷的時候忘記把第一行第一列最後一行最後一列進行操作了,比如這裏面確實有小於0的值,甲方也反應了這個問題,於是我改了改遍歷的範圍。而最大值濾波部分,在邊緣無法處理的部分我則人爲的填充,又寫了4個循環處理。

%第一行
for j = 2:n-1
    near = [A1(1,j-1),A1(1,j+1),A1(m,j-1),A1(m,j),A(m,j+1),A1(2,j-1),A1(2,j),A1(2,j+1)];
    if A(1,j) > 119.89 
        A(1,j) = max(near);
    end
end
%最後一行
for j = 2:n-1
    near = [A1(m,j-1),A1(m,j+1),A1(m-1,j-1),A1(m-1,j),A1(m-1,j+1),A1(1,j-1),A1(1,j),A1(1,j+1)];
    if A(m,j) > 119.89 
        A(m,j) = max(near);
    end
end
%第一列
for i = 2:m-1
    near = [A1(i-1,n),A1(i-1,1),A1(i-1,2),A1(i,n),A1(i,2),A1(i+1,n),A1(i+1,1),A1(i+1,2)];
    if A(i,1) > 119.89
        A(i,1) = max(near);
    end
end
%最後一列
for i = 2:m-1
        near = [A1(i-1,n-1),A1(i-1,n),A1(i-1,1),A1(i,n-1),A1(i,1),A1(i+1,n-1),A1(i+1,n),A1(i+1,1)];
        if A(i,n) > 119.89
            A(i,n) = max(near);
        end
end

這種方法其實和後面要講的岡薩雷斯教授在圖像處理講的padarray method裏的replicate差不多,是一種反鏡像的處理,只不過人爲的處理,加入了更多循環,而且9鄰域選取比較反麻煩。
在這裏插入圖片描述
就比如第一行第二個元素開始,需要這樣取鄰域,把最後一行補上來,同理,處理第一列補最後一列,最後一列補第一列到最後,最後一行補第一行到下一行組成9鄰域,而四個角同樣的理論單獨處理。那麼我濾波就需要3大塊方面了,時間成本一下上去了。於是我思索更簡單的方法。

第一步改進

首先是補充的方面,如果需要補充可以利用岡薩雷斯圖像處理中的padarray函數進行填充。在這裏插入圖片描述
至於method的選擇,就可以自己選了。反正都會引入誤差,我後來採用了’replicate’複製邊界填充,然後這樣就把邊緣都填完了。用我這種全部遍歷的方法做,最後提取圖像矩陣的(2:end-1,2:end-1)就可以得到濾波完的圖像。但是時間成本依舊很高。因爲MATLAB的for循環的代價實在是太高了。

第二步改進

我想起來了MATLAB有一種東西叫向量化,能用向量表示的就用向量表示,於是用起了最熟悉的find函數,在原始的矩陣找那些大於119.89的閾值部分然後利用下標+1即在擴展的矩陣中找鄰域進行濾波。

%處理擴展的矩陣,但是輸出擴展矩陣的2:end-1,2:end-1部分
A = double(A);   %A爲圖像的矩陣轉換爲double型
A1 = padarray(A,[1,1],'replicate','both');
A2 = A1;     %存儲改變的矩陣,濾波過程中濾波的矩陣不能改變
[m,n] = find(A>119,89);    %m,n返回的是在未擴展的矩陣中的下標
k = size(m);
m1 = m+1;                  %爲濾波的鄰域準備,而擴展後的矩陣相對原始矩陣下標+1,
n1 = n+1;                  %否則會若出現1-1=0的情況超出MATLAB索引範圍
for i = 1:1:k
    near = [A2(m1(i)-1,n1(i-1)),A2(m1(i)-1,n1(i)),A2(m1(i)-1,n1(i)+1),A2(m1(i),n1(i)),A2(m1(i),n1(i)+1),A2(m1(i)+1,n1(i)-1),A2(m1(i)+1,n1(i)),A2(m1(i)+1,n1(i)+1)];
    near_max = max(near);
    if A1(m(i),n(i)) > 119.89
        A1(m(i),n(i)) = near_max;
    end
end
%取出要的那部分矩陣
A3 = A1(2:end-1,2:end-1);
   %直方圖的對比
figure;
subplot(1,2,1);
imhist(A);
title('原始圖像的直方圖');
subplot(1,2,2);
imhist(A3);
title('處理後圖像的直方圖');
%輸出圖像
geotiffwrite('m2.tif', A3, R,'GeoKeyDirectoryTag',info.GeoTIFFTags.GeoKeyDirectoryTag);

這種方法少了二次循環而且循環次數也大量的降低,免去了許多沒必要的循環。不過這幾個矩陣的關係需要好好釐清楚。其實還有一種是移動窗口樣的,由於甲方給的要求是找到大於閾值的進行濾波所以這種方法比窗口移動又少了許多。但是窗口移動式的方法對整副影像進行濾波相對較好,後期還會學習搞清楚之後寫blog。

對專業的認識的進程

大一時

大一時,老師總問我們你們認爲遙感是什麼,我心中總會根據我高中刷天利刷名校卷子的經驗不假思索地在心裏說道,遙感就是用來看的,只要注意下臺風中心的移動也是用遙感監測就行了。

大二時

大二時,總在進行測繪,讓我不禁懷疑遙感和測繪並沒有什麼區別。
在這裏插入圖片描述
大二那個暑假開始搞建模,要做數據分析,要敲代碼。

大三時

剛開始時,因爲小項目的原因利用ENVI做一點很簡單的處理,我開始研究遙感影像那時候感覺遙感影像就是許多馬賽克構成的大馬賽克,在我的眼裏遙感影像就是加上地理參考系的一幅圖像(我記得當時有人讓我做過一個土壤分類圖,我也問過對方是否只要那花花綠綠的顏色而不顧參考系,對方也給了我肯定的答覆),外行人看的是那顏色和結論,我們看的是密度分割後的成果和地理參考系。其實最後要看的是加上各種整飾要素的圖。隨着項目的深入,我不在把ENVI當成一種傻瓜式的點擊就行的東西,而是利用自己的方法來計算這種圖像矩陣,遙感影像背後是存儲DN值的數字矩陣,利用band math來寫語句就是來對矩陣進行處理。在這裏插入圖片描述
而直到這次單子之後,遙感影像在我心中成了一個數字矩陣+結構體,那數字矩陣是背後的DN值矩陣,而那結構體就是地理參考系。
在這裏插入圖片描述
這個是當時甲方給我的同僚的圖,缺失了地理參考系的圖就是一幅灰度圖,缺少了重要的靈魂。
真正的遙感影像應該是:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
矩陣+參考系的結合體。在處理的時候它是一個大型的矩陣,而在真正需要的時候,那裏的山川地貌,大江大河能夠直接印在腦海裏。
利用MATLAB處理數字矩陣其實在很大程度上會比ENVI band math快,我也在思索ENVI band math也是對柵格圖像處理的機制是否也是向量化處理。

後續希望的改進

其實本來我希望通過同僚拿到甲方的數據,利用MATLAB tic toc計時器功能計算代碼運行的時間來進行比較效率問題,但是沒有能夠成功。希望能拿到吧。
雖然第一桶金只賺來50多塊錢,這第一桶金背後的鍛鍊以及思想上的轉變是無法形容的的。
在我看來,從獲得影像數據到出圖這一整個生產鏈是都需要付出努力的。有時候影像不好獲得,有時候天氣數據不好獲得,倘若會爬蟲獲取數據,那是一大進步。而倘若會數據分析,則能夠很大程度上解決你只能生產影像卻不能評價以及應用決策的問題。

結語

我記得某一位同僚說過很戲謔的話,計算機的人懂得編程,卻不懂得地學影像處理,而遙感的很多人懂得影像處理卻不懂得編程。其實這話沒什麼錯,這也就造成了很有意思的現象,那就是想要實現實時地圖及座標顯示及分析時,編程的人找不到邏輯,而做地學的人懂邏輯卻不會寫代碼。真正做地學的人應該是一種計算機編程+影像處理+數據後期分析的結合體,最終爲相應的部門進行決策。

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