圖像的空間域(spatial domain)主要指組成圖像的像素點集合。spatial domain process是對空間像素點的直接操做。若是用公式描述爲:git
\( g(x,y) = T{\left[f(x,y)\right]} \)dom
\(f(x,y)\)是輸入圖像,\(g(x,y)\)是輸出圖像,空域處理在輸入圖像上定義了一種操做獲得輸出圖像,每每這種操做對像素點處理,針對像素點\((x,y)\)及其8鄰域像素點的操做處理。也能夠僅對像素點\((x,y)\)操做,此時\(T\)稱爲gray-level transformingation function,灰度變換函數。函數
\(s = T(r)\)測試
經常使用的灰度變換函數:ui
log transformation對數變換,函數形式spa
\(s = clog(1 + r)\)3d
根據函數獲得函數圖像:code
Power-Law transformation指數變換,函數形式:orm
\(s = cr^\gamma\),blog
函數圖像:
對數變換和指數變換均可以將較小範圍的灰度值映射到較大的灰度值區間,也能夠將很大的灰度值區間映射到較小的灰度區間,能夠提升對比度。通常在獲得圖像的傅立葉頻譜圖後,頻譜圖像會處在很大的灰度區間,須要對此做對數或指數變換,圖像可視效果會更好。
還有對比度拉伸變換,函數形式:
\(s = \frac{1}{1+(\frac{m}{r})^E} \),
輸出圖像的灰度值被限制在[0,1]內,該變換函數以m爲閾值,灰度值低於m的被削弱,高於m的被加強,指數E控制了削弱域加強的度,從圖像上看爲曲線的陡峭程度。E越大越陡;
以上三種變換在matlab中均可以用函數 imadjust實現。
g = imadjust(f,[low_in,high_in],[low_out,high_out],gamma) 定義了指定輸入輸出區間上的指數變換,設定不一樣的gamma值有不一樣的映射曲線。
如下是MATLAB對圖像作指數變換,目的是加強必定區域內的灰度顯示效果。
1 >> f = imread('D:\MATLAB\image\DIP3E_Original_Images_CH03\Fig0308(a)(fractured_spine).tif'); 2 >> ff = mat2gray(f); 3 >> g1 = imadjust(ff,[],[],0.6); 4 >> g2 = imadjust(ff,[],[],0.4); 5 >> g3 = imadjust(ff,[],[],0.3); 6 >> subplot(2,2,1); 7 >> imshow(f); 8 >> g1 = im2uint8(g1); 9 >> g2 = im2uint8(g2); 10 >> g3 = im2uint8(g3); 11 >> subplot(2,2,2); 12 >> imshow(g1); 13 >> subplot(2,2,3); 14 >> imshow(g2); 15 >> subplot(2,2,4); 16 >> imshow(g3);
效果圖:
最左邊是源圖像,從作到右依次使用了gamma值爲0.6,0.4,0.3的指數變換,指數圖像是上凸形狀。拉伸了較暗區域的灰度顯示空間,但對明亮區域的變化不大。最終結果是可以發現原圖較暗區域被覆蓋的內容。
1 >> f = imread('D:\MATLAB\image\DIP3E_Original_Images_CH03\Fig0309(a)(washed_out_aerial_image).tif'); 2 >> ff = mat2gray(f); 3 >> g1 = imadjust(ff,[],[],3); 4 >> g2 = imadjust(ff,[],[],4); 5 >> g3 = imadjust(ff,[],[],5); 6 >> subplot(2,2,1); 7 >> imshow(f); 8 >> g1 = im2uint8(g1); 9 >> g2 = im2uint8(g2); 10 >> g3 = im2uint8(g3); 11 >> subplot(2,2,2); 12 >> imshow(g1); 13 >> subplot(2,2,3); 14 >> imshow(g2); 15 >> subplot(2,2,4); 16 >> imshow(g3);
效果圖:
最左邊是原圖,是一張washed-out的圖像,曝光率過大,使用gamma值爲3,4,5的指數變換,壓縮了明亮區域的灰度空間,但只對較暗區域作微調,較好的還原了圖像。但我的認爲,指數變換,或灰度變換都是在灰度或亮度級的變換,可以加強明暗顯示效果,但沒法提升分辨率。但明暗顯示效果加強能夠給邊緣檢測和圖像分割帶來很大的益處。
另外MATLAB下對比度拉伸變換和對數變換能夠直接使用函數形式:
g = im2uint8(mat2gray(log(1+double(f))));
g = 1 ./ (1+(m./(double(f)+eps)).^E)
opencv下可使用函數cvLUT來實現灰度變換。
一個簡單的例子,opencv程序 指數變換:
1 #include "cv.h" 2 #include "highgui.h" 3 #include <math.h> 4 #define GAMMA 5 5 /* 6 指數變換測試:s = c*pow(r,gamma) 7 */ 8 9 int main(int argc,char**argv) 10 { 11 IplImage * img; 12 if(argc ==2 && (img = cvLoadImage(argv[1],0))!=0) 13 { 14 IplImage *dist = cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,1); 15 CvMat *lu_mat = cvCreateMatHeader(1,256,CV_8UC1); 16 uchar lu[256]; 17 float f = 0.0f; 18 int d = 0; 19 for(int i =0;i<256;i++) 20 { 21 f = (float)i/255; 22 d = pow(f,GAMMA)*255; 23 lu[i] = d; 24 } 25 cvSetData(lu_mat,lu,0); 26 cvLUT(img,dist,lu_mat); 27 cvNamedWindow("origin",CV_WINDOW_AUTOSIZE); 28 cvNamedWindow("convert",CV_WINDOW_AUTOSIZE); 29 cvShowImage("origin",img); 30 cvShowImage("convert",dist); 31 cvWaitKey(0); 32 cvReleaseImage(&img); 33 cvReleaseImage(&dist); 34 cvDestroyWindow("origin"); 35 cvDestroyWindow("convert"); 36 } 37 }
效果圖:
Gonzalez在他的Digital Image Processing中提到了另外幾個灰度空間變換的技巧,其實,總結一下,對數,指數等基於函數的灰度空間變換,正如OpenCv中cvLUT的實現同樣,是從已經定義好的映射規則中查詢每一個point的映射,映射規則體現了函數的形式,由於像素和像素點本就離散,因此對函數的連續與平滑沒有嚴格要求,只要能將每個point映射到合適的值便可。Gray-level-slicing是一個分段函數的映射規則,用於加強指定灰度區間的灰度值,有兩種形式,函數圖像以下:
另外,還提到了一個比較有趣的基於point的灰度空間處理,Bit-plane-slicing,不基於函數,而是基於每一個point的比特位,若是8位灰度圖像,每一個像素點有8位二進制值表示其灰度值大小,能夠將8位從高到低分紅8個等級,每一個等級對應一位,全部像素點的同一等級就組成了一個平面,稱爲一個bit-plane,例如對於最高位,若是是1,就將其灰度值映射到255,若是爲0,映射到0;每一個bit-plane就是一個二值圖像,共有8個bit-plane,每一個plane表明了不一樣的信息,高位可能體現了較大的輪廓,而低位可能體現了更多的細節。
如下是Bit-plane-slicing的opencv實現:
1 #include "cv.h" 2 #include "highgui.h" 3 #include <math.h> 4 5 int main(int argc,char ** argv) 6 { 7 IplImage *src = 0; 8 if(argc == 2 && (src = cvLoadImage(argv[1],0))!=0) 9 { 10 IplImage * dist[8]; 11 for(int i = 0;i<8;i++) 12 { 13 dist[i] = cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); 14 } 15 uchar data = 0x01; 16 for(int i = 0;i<8;i++) 17 { 18 cvAndS(src,cvScalar(data),dist[i]); 19 cvDiv(NULL,dist[i],dist[i],pow(2,(float)i)); 20 cvCvtScale(dist[i],dist[i],255,0); 21 data = data << 1; 22 } 23 cvNamedWindow("origin",CV_WINDOW_AUTOSIZE); 24 cvShowImage("origin",src); 25 cvNamedWindow("bitone",CV_WINDOW_AUTOSIZE); 26 cvShowImage("bitone",dist[0]); 27 cvNamedWindow("bittwo",CV_WINDOW_AUTOSIZE); 28 cvShowImage("bittwo",dist[1]); 29 cvNamedWindow("bitthr",CV_WINDOW_AUTOSIZE); 30 cvShowImage("bitthr",dist[2]); 31 cvNamedWindow("bitfour",CV_WINDOW_AUTOSIZE); 32 cvShowImage("bitfour",dist[3]); 33 cvNamedWindow("bitfive",CV_WINDOW_AUTOSIZE); 34 cvShowImage("bitfive",dist[4]); 35 cvNamedWindow("bitsix",CV_WINDOW_AUTOSIZE); 36 cvShowImage("bitsix",dist[5]); 37 cvNamedWindow("bitseven",CV_WINDOW_AUTOSIZE); 38 cvShowImage("bitseven",dist[6]); 39 cvNamedWindow("biteight",CV_WINDOW_AUTOSIZE); 40 cvShowImage("biteight",dist[7]); 41 cvWaitKey(0); 42 cvReleaseImage(&dist[0]); 43 cvReleaseImage(&dist[1]); 44 cvReleaseImage(&dist[2]); 45 cvReleaseImage(&dist[3]); 46 cvReleaseImage(&dist[4]); 47 cvReleaseImage(&dist[5]); 48 cvReleaseImage(&dist[6]); 49 cvReleaseImage(&dist[7]); 50 cvReleaseImage(&src); 51 cvDestroyWindow("bitone"); 52 cvDestroyWindow("bitwo"); 53 cvDestroyWindow("bithr"); 54 cvDestroyWindow("bitfour"); 55 cvDestroyWindow("bitfive"); 56 cvDestroyWindow("bitsix"); 57 cvDestroyWindow("bitseven"); 58 cvDestroyWindow("biteight"); 59 cvDestroyWindow("origin"); 60 } 61 62 }
效果圖:
第一幅爲原圖,接下來是從高位到低位的bit-plane平面圖。