久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

我的OpenCV學(xué)習(xí)筆記(24):詳細(xì)討論OpenCV中的數(shù)據(jù)結(jié)構(gòu)

 mscdj 2014-12-22
  最近在寫自己的算法,,其實就是對一些傳統(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)),下面是一個例子:

  1. int main(void)  
  2. {  
  3.     Mat bg(200,200,CV_8UC3,Scalar(0));  
  4.     imshow("",bg);  
  5.     RotatedRect rRect(Point2f(100,100),Size(100,100),40);   
  6.     Point2f vertices[4];  
  7.     rRect.points(vertices);  
  8.     for(int i = 0; i < 4;++i)  
  9.         line(bg,vertices[i],vertices[(i+1)%4],Scalar(0,255,0));  
  10.     Rect brect = rRect.boundingRect();  
  11.     rectangle(bg,brect,Scalar(255,0,0));  
  12.     imshow("",bg);  
  13.     waitKey();  
  14.     return 0;  
  15. }  

下面介紹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ù)的子序列,。比如矩陣的一部分,比較簡單,,我們直接看定義:

  1. class CV_EXPORTS Range  
  2. {  
  3. public:  
  4.     Range();  
  5.     Range(int _start, int _end);  
  6.     Range(const CvSlice& slice);  
  7.     int size() const;  
  8.     bool empty() const;  
  9.     static Range all();  
  10.     operator CvSlice() const;  
  11.   
  12.     int start, end;  
  13. };  

講完這些簡單的類型之后,,我們看一個非常重要的類型;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ǔ)充,,就是多維情況:

  1. int main(void)  
  2. {  
  3.     int sz[]={4,5,6};  
  4.     Mat img(3,sz,CV_8U);//3維數(shù)組  
  5.     cout<<img.dims<<endl;  
  6.     cout<<img.size[0]<<endl;  
  7.     cout<<img.size[1]<<endl;  
  8.     cout<<img.size[2]<<endl;  
  9.   
  10.     cout<<img.step[0]<<endl;  
  11.     cout<<img.step[1]<<endl;  
  12.     cout<<img.step[2]<<endl;  
  13.     //遍歷每個元素  
  14.     for(int i = 0; i < 4;++i)  
  15.     {  
  16.         for(int j = 0; j < 5;++j)  
  17.         {  
  18.             for(int k = 0; k < 6;++k)  
  19.             {  
  20.                 cout<<(int)*(B.data + B.step[0]*i + B.step[1]*j + B.step[2]*k)<<endl;  
  21.             }  
  22.         }  
  23.     }  
  24.     return 0;  
  25. }  
我們建立了一個3維數(shù)組,,數(shù)組的每一維長度分別為4,5,6。這可以通過size來獲得,。由于每個第一維向量中包含5個第二維的數(shù)組,,而每個第二維數(shù)組中又包含了6個第三維數(shù)組,所以第一維每增加一步,,相當(dāng)于整個地址移動了5*6.所以step[0],等于30.
下面我們主要是看看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

  1. int main(void)  
  2. {  
  3.     Mat A = Mat::eye(5,5,CV_8U);  
  4.   
  5.     Mat B = A(Range::all(),Range(1,3));  
  6.     B.setTo(100);  
  7.     for(int i = 0; i < 5;++i)  
  8.     {  
  9.         for(int j = 0; j < 5;++j)  
  10.         {  
  11.             cout<<(int)A.at<uchar>(i,j)<<endl;  
  12.         }  
  13.     }  
  14.     return 0;  
  15. }  

如果需要深拷貝,則使用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):

  1. void process_video_frame(const unsigned char* pixels,int width, int height, int step)  
  2. {  
  3.     Mat img(height, width, CV_8UC3, pixels, step);  
  4.     GaussianBlur(img, img, Size(7,7), 1.5, 1.5);  
  5. }  
  6.   
  7. double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};  
  8. Mat M = Mat(3, 3, CV_64F, m).inv();  

特別的,,對于與opencv1.X中的IplImage結(jié)構(gòu)的交互:

  1. IplImage* img = cvLoadImage("greatwave.jpg", 1);  
  2. Mat mtx(img); // convert IplImage* -> Mat  
  3. CvMat oldmat = mtx; // convert Mat -> CvMat  

說完了,,構(gòu)造、初始化,,應(yīng)該討論元素訪問的方法,,這個在之前的博客中也有提過《我的OpenCV學(xué)習(xí)筆記(二):操作每個像素》這里就不再重復(fù)了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多