最近在寫自己的算法,,其實就是對一些傳統(tǒng)算法的改進(jìn),。傳統(tǒng)算法可以參考o(jì)pecv的源代碼。在閱讀源代碼的過程中,我慢慢領(lǐng)會到了opencv的強(qiáng)大之處,并不是因為它實現(xiàn)了各種算法,,而是在于它對于基本數(shù)據(jù)結(jié)構(gòu)的設(shè)計,是得其他人可以很方便的使用這些數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)自己的算法,。在幫助手冊中,,已經(jīng)對于這些數(shù)據(jù)結(jié)構(gòu)有比較詳細(xì)的描述了。今天我就為英語不好的孩子們服務(wù)一下,,簡單的介紹一下它們,。 首先介紹2維點對Point_,它的是一個模板類,。我們可以直接訪問數(shù)據(jù)成員x,y,。它不僅定了+、-,、==,、!=這4個基本的操作,還定義了點乘,、叉乘等操作,。特別的這個類還提供了inside函數(shù)來判斷一個點是否在矩形區(qū)域內(nèi)。此外,,還定義了一些其他的類型轉(zhuǎn)化函數(shù),,比如轉(zhuǎn)化為1.X版本的CvPoint。 為了方便使用,,opencv又對常用的類型進(jìn)行了定義: typedef Point_<int> Point2i; typedef Point2i Point; typedef Point_<float> Point2f; typedef Point_<double> Point2d; 同理還有Point3_,,只不過它是一個3維點(x,y,z)而已。它的常用類型是: typedef Point3_<int> Point3i; typedef Point3_<float> Point3f; typedef Point3_<double> Point3d; 介紹完點,,就可以介紹Size_了,。它也是模板類。 typedef Size_<int> Size2i; typedef Size2i Size; typedef Size_<float> Size2f Size能夠訪問的成員變量是height和width,。還定義了area函數(shù)來求面積,。其他的操作基本都是類型轉(zhuǎn)化函數(shù)。 下來介紹Rect_模版類,。它是由左上角點和長度,、寬度定義的。在opecv中,,一般定義為左開右閉區(qū)間。有意思的是,,這個類竟然也提供了一個Rect+Point的函數(shù),,作用是對矩形的偏移,,還有一個Rect + Size的函數(shù),在左上角不變的情況下,,重新調(diào)整矩形的大小,。其他的操作還有與&和|,是求兩個矩形的交集和并集,。 除了基本的矩形之外,,opecv還提供了一個可以旋轉(zhuǎn)的矩形RotatedRect,它是由中心,、變長,、旋轉(zhuǎn)角度決定的。你可以訪問它的這三個成員,,也可以使用points函數(shù)返回它的4個頂點,,使用boundingRect求出它的外接矩形(非旋轉(zhuǎn)),下面是一個例子: [cpp] view plaincopy
下面介紹Matx類,,這也是一個模板類,,用來記錄一些小的矩形。這些矩形在編譯前大小就固定了: typedef Matx<float, 1, 2> Matx12f; typedef Matx<double, 1, 2> Matx12d; ... typedef Matx<float, 1, 6> Matx16f; typedef Matx<double, 1, 6> Matx16d; typedef Matx<float, 2, 1> Matx21f; typedef Matx<double, 2, 1> Matx21d; ... typedef Matx<float, 6, 1> Matx61f; typedef Matx<double, 6, 1> Matx61d; typedef Matx<float, 2, 2> Matx22f; typedef Matx<double, 2, 2> Matx22d; ... typedef Matx<float, 6, 6> Matx66f; typedef Matx<double, 6, 6> Matx66d; 如果要使用靈活的矩形,,還是用Mat吧,。 下面介紹Vec類,它其實是元素較少的向量,。 typedef Vec<uchar, 2> Vec2b; typedef Vec<uchar, 3> Vec3b; typedef Vec<uchar, 4> Vec4b; typedef Vec<short, 2> Vec2s; typedef Vec<short, 3> Vec3s; typedef Vec<short, 4> Vec4s; typedef Vec<int, 2> Vec2i; typedef Vec<int, 3> Vec3i; typedef Vec<int, 4> Vec4i; typedef Vec<float, 2> Vec2f; typedef Vec<float, 3> Vec3f; typedef Vec<float, 4> Vec4f; typedef Vec<float, 6> Vec6f; typedef Vec<double, 2> Vec2d; typedef Vec<double, 3> Vec3d; typedef Vec<double, 4> Vec4d; typedef Vec<double, 6> Vec6d; 它支持加,、減、數(shù)乘,、相等,、不等、求范數(shù)等運(yùn)算,。 Scalar_類其實是用Vec<tp,4>派生下來的,,也就是說,它是一個4元組:typedef Scalar_<double> Scalar; 他通常用來傳遞像素,。 Range類用來指定連續(xù)的子序列,。比如矩陣的一部分,比較簡單,,我們直接看定義: [cpp] view plaincopy
講完這些簡單的類型之后,,我們看一個非常重要的類型;Mat,。Mat是opencv中的一種非常重要的數(shù)據(jù)結(jié)構(gòu),,當(dāng)剛開始使用時,我僅僅把它當(dāng)做一個儲存圖像的數(shù)據(jù)結(jié)構(gòu),,后來才慢慢理解,,它不僅可以儲存二維矩陣,,也可以儲存高維矩陣,這在模式識別,、機(jī)器學(xué)習(xí)中是非常常用的,。對于這類問題,我們就沒有必要自己手動分配內(nèi)存了,,直接使用它們就可以了,。這個類的內(nèi)容很多,但opencv的幫助手冊,,很好的幫我們理清的其中的內(nèi)容,。 其中的核心數(shù)據(jù)成員data的儲存方式在前一篇博客《我的OpenCV學(xué)習(xí)筆記(23):Mat中實際數(shù)據(jù)是如何保存的》中已經(jīng)討論過了,這里只做一個補(bǔ)充,,就是多維情況: [cpp] view plaincopy
下面我們主要是看看Mat提供的函數(shù),。 首先是構(gòu)造函數(shù),光構(gòu)造函數(shù)就有很多種,,這里介紹幾種常用的方式: 1.使用(nrows, ncols, type),,初始化2維矩陣 // 創(chuàng)建一個7*7的2通道浮點矩陣,通常這樣的矩陣用來表示復(fù)矩陣 Mat M(7,7,CV_32FC2,Scalar(1,3)); //改變?yōu)?00*60的15通道uchar矩陣,,原先的數(shù)據(jù)將會被釋放 M.create(100,60,CV_8UC(15)); 創(chuàng)建高維矩陣 //創(chuàng)建100*100*100的3維矩陣 int sz[] = {100, 100, 100}; Mat bigCube(3, sz, CV_8U, Scalar::all(0)); 下面是一些簡單的對整行,、整列的操作 // 第5行*3 + 第3行,這樣的操作在線性代數(shù)中很常見 M.row(3) = M.row(3) + M.row(5)*3; // 把第7列拷貝到第1列 // M.col(1) = M.col(7); // 不能這樣寫 Mat M1 = M.col(1); M.col(7).copyTo(M1); 用源圖像的一部分創(chuàng)建新圖像 // 創(chuàng)建一個320*240的圖像 Mat img(Size(320,240),CV_8UC3); // 選擇感興趣區(qū)域 Mat roi(img, Rect(10,10,100,100)); // 將區(qū)域改為綠色,,原圖像也會發(fā)生修改 roi = Scalar(0,255,0); B是A的[1,3)列,,對B的修改會影響A [cpp] view plaincopy
如果需要深拷貝,則使用clone方法,。 對于初始化Mat,,還有其他的一些方法: 比如Matlab風(fēng)格的 zeros(), ones(), eye(): M += Mat::eye(M.rows, M.cols, CV_64F); Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); 如果是處理“外來”的數(shù)據(jù),那么則在構(gòu)造函數(shù)中加上data則會非常方便的將外來數(shù)據(jù)轉(zhuǎn)化為Mat結(jié)構(gòu): [cpp] view plaincopy
特別的,,對于與opencv1.X中的IplImage結(jié)構(gòu)的交互: [cpp] view plaincopy
說完了,,構(gòu)造、初始化,,應(yīng)該討論元素訪問的方法,,這個在之前的博客中也有提過《我的OpenCV學(xué)習(xí)筆記(二):操作每個像素》這里就不再重復(fù)了。 |
|