一映像基礎
1 數位影像 又稱數位映像或數位元影像像,是二維映像用有限數字數值像素的表示。數位影像是由類比映像數字化得到的、以像素為基本元素的、可以用數字電腦或數字電路儲存和處理的映像。
2. 像素 像素(或像元,Pixel)是數位影像的基本元素,像素是在類比映像數字化時對連續空間進行離散化得到的。每個像素具有整數行(高)和列(寬)位置座標,同時每個像素都具有整數灰階值或顏色值。 通常,像素在電腦中儲存為二維整數數阻的光柵映像,這些值經常用壓縮格式進行傳輸和儲存。
3.通道 基本上,描述一個像素點,如果是灰階,那麼只需要一個數值來描述它,就是單通道。如果一個像素點,有RGB三種顏色來描述它,就是三通道.。windows的bmp有時候是一個四通道映像,R、G、B加上一個A通道,表示透明度。
4.解析度 影象清晰度或濃度的度量標準。舉例來說,解析度代表垂直及水平顯示的每英寸點(dpi)的數量。BitWare 可以用普通或標準(100 乘 200 dpi)及精細解析度(200 乘 200 dpi)發送及接收傳真文檔。解析度是一個表示平面映像精細程度的概念,通常它是以橫向和縱向點的數量來衡量的,表示成水平點數×垂直點數的形式。在一個固定的平面內,解析度越高,意味著可使用的點數越多,映像越細緻。
二 映像的分類
灰階映像: 單色數位影像,其中每個像素只有一個強度值
多普映像:二維映像,在每個空間點或像素位置存在一個強度值向量。如果是一幅彩色映像,則該向量有三個元素
二值映像:所有像素值要麼為0要麼為1的數位影像。
標記映像:數位影像,其中的像素值是有限的字元標記。像素的字元值表示該像素做某個判定的結果。
三 映像的資料結構
1.矩陣
1.1基本概念:底層映像表示的最普通的資料結構,矩陣元素是整型的數值,對應於採樣柵格中的相應像素的亮度或其他屬性。這類映像資料通常是映像裝置的直接輸出。矩陣中的映像資訊可以通過像素的座標得到,座標組應於行和列的標號,矩陣映像是一個完整的表示,與映像資料的內容無關。
1.2矩陣表示的映像:二值映像:用僅含0和1的矩陣表示;多光譜映像:可以用幾個矩陣來表示,每個矩陣含有一個頻帶的映像;分層映像資料結構:用不同解析度的矩陣來獲得。映像的這種分層表示對於處理機陣列結構的並行電腦會是非常的方便。
2.鏈
2.1鏈碼:常用來描述物體的邊界,或者映像中一個像素寬度的線條。邊界由其參考像素的座標和一序號序列來定義,符號對應於幾個事先定義好了方向的單位長度的線段。注意,鏈碼本身是相對的,資料是相對於某個參考點來表示的。用鏈碼錶示映像適合基於形式語言理論的句法模式識別。
2.2行程編碼:通常用於映像矩陣中符號串的表示。
3拓撲資料結構
3.1賦值圖:是指弧、節點或兩者都帶有數值的圖。
3.2地區鄰接圖:其中節點賭贏與地區,相鄰的地區用弧串連起來。
4分層資料結構
分層資料結構可以使特殊的演算法在相對較小的資料量基礎上決定處理策略,只對映像中實質部分進行最精細的解析度工作。
4.1金字塔:屬於最簡單的分層資料結構。有M型金字塔和T型金字塔。主要是描述多個映像解析度的資料結構。
4.2四叉樹:是對T型金字塔的改進。映像中的選擇地區比其他地區在跟高的解析度上儲存,允許選擇性的提取細節。
四 openCV中的基本結構
對於openCv中的資料結構,這裡這討論三個cvArr,cvMat和IplImage
4.1CvArr:一個抽象基類,CvArr* 僅僅是被用於作函數的參數,用於指示函數接收的數群組類型可以不止一個,如 IplImage*, CvMat* 甚至 CvSeq*. 最終的數群組類型是在運行時通過分析數組頭的前4 個位元組判斷。
4.2CvMat:多通道矩陣,以下是其結構體
typedef struct CvMat
{
int type; /* CvMat 標識 (CV_MAT_MAGIC_VAL), 元素類型和標記 */
int step; /* 以位元組為單位的行資料長度*/
int* refcount; /* 資料引用計數 */
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data; /* data 指標 */
#ifdef __cplusplus
union
{
int rows;
int height;
};
union
{
int cols;
int width;
};
#else
int rows; /* 行數 */
int cols; /* 列數*/
#endif
} CvMat;
CvMat這個類有兩部分資料。一個是matrix header,這部分的大小是固定的,包含矩陣的大小,儲存的方式,矩陣儲存的地址等等,如以上結構。另一個部分是一個指向矩陣包含像素值的指標。
4.2.1CvMat的建立和訪問
CvMat* cvCreateMat(int rows,int cols,int type)//建立二維矩陣,其中type可以為以下幾種類型(摘自http://blog.csdn.net/yang_xian521/article/details/7107786#)
說到資料的儲存,這一直就是一個值得關注的問題,Mat_<uchar>對應的是CV_8U,Mat_<uchar>對應的是CV_8U,Mat_<char>對應的是CV_8S,Mat_<int>對應的是CV_32S,Mat_<float>對應的是CV_32F,Mat_<double>對應的是CV_64F,對應的資料深度如下:
CV_8U - 8-bit unsigned integers ( 0..255 )
CV_8S - 8-bit signed integers ( -128..127 )• CV_16U - 16-bit unsigned integers ( 0..65535 )
CV_16S - 16-bit signed integers ( -32768..32767 )
CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
執行個體代碼
#include<cv.h>#include<highgui.h>#include<iostream>//using namespace cv;using namespace std;int main(){ //矩陣的建立CvMat* mat1=cvCreateMat(2,2,CV_32FC1);//建立矩陣 /* CV32FC1-有n行三列;CV32FC3 n行一列*/*((float *)CV_MAT_ELEM_PTR(*mat1,0,0))=0.1;*((float *)CV_MAT_ELEM_PTR(*mat1,0,1))=0.2;*((float *)CV_MAT_ELEM_PTR(*mat1,1,0))=0.3;*((float *)CV_MAT_ELEM_PTR(*mat1,1,1))=0.4; CvMat* mat2 = cvCreateMatHeader(5,5,CV_32FC1);//建立矩陣頭資訊CvMat mat3;float valus[] = {0.1,0.2,0.3,0.4};cvInitMatHeader(&mat3,2,2,CV_32FC1,valus);//矩陣中簡單得到元素——1float mat1_elem = CV_MAT_ELEM(*mat1,float,0,0);float mat3_elem = CV_MAT_ELEM(mat3,float,1,1);cout<<mat1_elem<<endl;cout<<mat3_elem<<endl; //矩陣中恰當得到元素——2//累加通道中的所有元素 float s=0.0f;for(int row =0;row<mat1->rows;row++){const float* ptr = (const float *)(mat1->data.ptr+row*mat1->step);//切換行for(int col=0;col<mat1->cols;col++)//每行的累加和{cout<<*ptr<<" ";s+=*ptr++;}cout<<endl;} // float elem = CV_MAT_ELEM(*mat,float,3,2);//cout<<elem<<endl;return 0;}
對於以上的CvMat現在已經推出Mat類,功能強大。。。,在下一篇中介紹
4.3 IplImge
typedef struct _IplImage{int nSize; /* IplImage大小 */int ID; /* 版本 (=0)*/int nChannels; /* 大多數OPENCV函數支援1,2,3 或 4 個通道 */int alphaChannel; /* 被OpenCV忽略 */int depth; /* 像素的位元深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支援 */char colorModel[4]; /* 被OpenCV忽略 */char channelSeq[4]; /* 同上 */int dataOrder; /* 0 - 交叉存取色彩通道, 1 - 分開的色彩通道.cvCreateImage只能建立交叉存取映像 */int origin; /* 0 - 頂—左結構,1 - 底—左結構 (Windows bitmaps 風格) */int align; /* 映像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */int width; /* 映像寬像素數 */int height; /* 映像高像素數*/struct _IplROI *roi;/* 映像感興趣地區. 當該值非空只對該地區進行處理 */struct _IplImage *maskROI; /* 在 OpenCV中必須置NULL */void *imageId; /* 同上*/struct _IplTileInfo *tileInfo; /*同上*/int imageSize; /* 映像資料大小(在交叉存取格式下imageSize=image->height*image->widthStep),單位位元組*/char *imageData; /* 指向排列的映像資料 */int widthStep; /* 排列的映像行大小,以位元組為單位 */int BorderMode[4]; /* 邊際結束模式, 被OpenCV忽略 */int BorderConst[4]; /* 同上 */char *imageDataOrigin; /* 指標指向一個不同的映像資料結構(不是必須排列的),是為了糾正映像記憶體配置準備的 */}
IplImage;
IplImage結構來自於 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支援其中的一個子集:
alphaChannel 在OpenCV中被忽略。
colorModel 和channelSeq 被OpenCV忽略。OpenCV色彩轉換的唯一函數 cvCvtColor把原映像的色彩空間的靶心圖表像的色彩空間作為一個參數。
dataOrder 必須是IPL_DATA_ORDER_PIXEL (色彩通道是交叉存取),然而平面映像的被選擇通道可以被處理,就像COI(感興趣的通道)被設定過一樣。
align 是被OpenCV忽略的,而用 widthStep 去訪問後繼的映像行。
不支援maskROI 。處理MASK的函數把他當作一個分離的參數。MASK在 OpenCV 裡是 8-bit,然而在 IPL他是 1-bit。
tileInfo 不支援。
BorderMode和BorderConst是不支援的。每個 OpenCV 函數處理像素的鄰近的像素,通常使用單一的固定代碼邊際模式。
除了上述限制,OpenCV處理ROI有不同的要求。要求原映像和靶心圖表像的尺寸或 ROI的尺寸必須(根據不同的操作,例如cvPyrDown 靶心圖表像的寬(高)必須等於原映像的寬(高)除以2 ±1)精確匹配,而IPL處理交叉地區,像的大小或ROI大小可能是完全獨立的。
以上摘自文檔。
#include<cv.h>#include<highgui.h>#include<iostream>//using namespace cv;using namespace std;int main(){//遍曆映像,將三通道的HSV映像,在色度保持不變的情況下,設定每個點的飽和度和高度為255.IplImage* imge = cvLoadImage("test.jpg");if(!imge){}IplImage* imge_result=cvCreateImage(cvGetSize(imge),imge->depth,imge->nChannels) ;cvCopyImage(imge,imge_result);for(int y=0;y<imge_result->height;y++){uchar* ptr = (uchar *)(imge_result->imageData + y*imge_result->widthStep);for(int x=0;x<imge_result->width;x++){ptr[3*x+1] = 255;ptr[3*x+2] = 255;}}cvNamedWindow("原圖"); cvNamedWindow("result");cvShowImage("原圖",imge);cvShowImage("result",imge_result);cvWaitKey(0); cvReleaseImage(&imge);cvReleaseImage(&imge_result);cvDestroyWindow("原圖");cvDestroyWindow("result");return 0;}
可以說,這種方式是遍曆最快的,但是要單獨的找去哪一個元素效率就不行了。
其實,些這些東西,基本上全是參考的。對於結構的瞭解還是不行,還要繼續努力呀