日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OPENCV中的数据结构总结

發布時間:2025/5/22 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OPENCV中的数据结构总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在寫自己的算法,其實就是對一些傳統算法的改進。傳統算法可以參考opecv的源代碼。在閱讀源代碼的過程中,我慢慢領會到了opencv的強大之處,并不是因為它實現了各種算法,而是在于它對于基本數據結構的設計,是得其他人可以很方便的使用這些數據結構來實現自己的算法。在幫助手冊中,已經對于這些數據結構有比較詳細的描述了。今天我就為英語不好的孩子們服務一下,簡單的介紹一下它們。


首先介紹2維點對Point_,它的是一個模板類。我們可以直接訪問數據成員x,y。它不僅定了+、-、==、!=這4個基本的操作,還定義了點乘、叉乘等操作。特別的這個類還提供了inside函數來判斷一個點是否在矩形區域內。此外,還定義了一些其他的類型轉化函數,比如轉化為1.X版本的CvPoint。
為了方便使用,opencv又對常用的類型進行了定義:
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函數來求面積。其他的操作基本都是類型轉化函數。


下來介紹Rect_模版類。它是由左上角點和長度、寬度定義的。在opecv中,一般定義為左開右閉區間。有意思的是,這個類竟然也提供了一個Rect+Point的函數,作用是對矩形的偏移,還有一個Rect + Size的函數,在左上角不變的情況下,重新調整矩形的大小。其他的操作還有與&和|,是求兩個矩形的交集和并集。


除了基本的矩形之外,opecv還提供了一個可以旋轉的矩形RotatedRect,它是由中心、變長、旋轉角度決定的。你可以訪問它的這三個成員,也可以使用points函數返回它的4個頂點,使用boundingRect求出它的外接矩形(非旋轉),下面是一個例子:

[cpp]?view plaincopy
  • int?main(void)??
  • {??
  • ????Mat?bg(200,200,CV_8UC3,Scalar(0));??
  • ????imshow("",bg);??
  • ????RotatedRect?rRect(Point2f(100,100),Size(100,100),40);???
  • ????Point2f?vertices[4];??
  • ????rRect.points(vertices);??
  • ????for(int?i?=?0;?i?<?4;++i)??
  • ????????line(bg,vertices[i],vertices[(i+1)%4],Scalar(0,255,0));??
  • ????Rect?brect?=?rRect.boundingRect();??
  • ????rectangle(bg,brect,Scalar(255,0,0));??
  • ????imshow("",bg);??
  • ????waitKey();??
  • ????return?0;??
  • }??

  • 下面介紹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;
    它支持加、減、數乘、相等、不等、求范數等運算。




    Scalar_類其實是用Vec<tp,4>派生下來的,也就是說,它是一個4元組:typedef Scalar_<double> Scalar;
    他通常用來傳遞像素。


    Range類用來指定連續的子序列。比如矩陣的一部分,比較簡單,我們直接看定義:

    [cpp]?view plaincopy
  • class?CV_EXPORTS?Range??
  • {??
  • public:??
  • ????Range();??
  • ????Range(int?_start,?int?_end);??
  • ????Range(const?CvSlice&?slice);??
  • ????int?size()?const;??
  • ????bool?empty()?const;??
  • ????static?Range?all();??
  • ????operator?CvSlice()?const;??
  • ??
  • ????int?start,?end;??
  • };??

  • 講完這些簡單的類型之后,我們看一個非常重要的類型;Mat。Mat是opencv中的一種非常重要的數據結構,當剛開始使用時,我僅僅把它當做一個儲存圖像的數據結構,后來才慢慢理解,它不僅可以儲存二維矩陣,也可以儲存高維矩陣,這在模式識別、機器學習中是非常常用的。對于這類問題,我們就沒有必要自己手動分配內存了,直接使用它們就可以了。這個類的內容很多,但opencv的幫助手冊,很好的幫我們理清的其中的內容。
    其中的核心數據成員data的儲存方式在前一篇博客《我的OpenCV學習筆記(23):Mat中實際數據是如何保存的》中已經討論過了,這里只做一個補充,就是多維情況:

    [cpp]?view plaincopy
  • int?main(void)??
  • {??
  • ????int?sz[]={4,5,6};??
  • ????Mat?img(3,sz,CV_8U);//3維數組??
  • ????cout<<img.dims<<endl;??
  • ????cout<<img.size[0]<<endl;??
  • ????cout<<img.size[1]<<endl;??
  • ????cout<<img.size[2]<<endl;??
  • ??
  • ????cout<<img.step[0]<<endl;??
  • ????cout<<img.step[1]<<endl;??
  • ????cout<<img.step[2]<<endl;??
  • ????//遍歷每個元素??
  • ????for(int?i?=?0;?i?<?4;++i)??
  • ????{??
  • ????????for(int?j?=?0;?j?<?5;++j)??
  • ????????{??
  • ????????????for(int?k?=?0;?k?<?6;++k)??
  • ????????????{??
  • ????????????????cout<<(int)*(B.data?+?B.step[0]*i?+?B.step[1]*j?+?B.step[2]*k)<<endl;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • 我們建立了一個3維數組,數組的每一維長度分別為4,5,6。這可以通過size來獲得。由于每個第一維向量中包含5個第二維的數組,而每個第二維數組中又包含了6個第三維數組,所以第一維每增加一步,相當于整個地址移動了5*6.所以step[0],等于30.
    下面我們主要是看看Mat提供的函數。
    首先是構造函數,光構造函數就有很多種,這里介紹幾種常用的方式:
    1.使用(nrows, ncols, type),初始化2維矩陣
    // 創建一個7*7的2通道浮點矩陣,通常這樣的矩陣用來表示復矩陣
    Mat M(7,7,CV_32FC2,Scalar(1,3));
    //改變為100*60的15通道uchar矩陣,原先的數據將會被釋放
    M.create(100,60,CV_8UC(15));
    創建高維矩陣
    //創建100*100*100的3維矩陣
    int sz[] = {100, 100, 100};
    Mat bigCube(3, sz, CV_8U, Scalar::all(0));


    下面是一些簡單的對整行、整列的操作
    // 第5行*3 + 第3行,這樣的操作在線性代數中很常見
    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);


    用源圖像的一部分創建新圖像
    // 創建一個320*240的圖像
    Mat img(Size(320,240),CV_8UC3);
    // 選擇感興趣區域
    Mat roi(img, Rect(10,10,100,100));
    // 將區域改為綠色,原圖像也會發生修改
    roi = Scalar(0,255,0);


    B是A的[1,3)列,對B的修改會影響A

    [cpp]?view plaincopy
  • int?main(void)??
  • {??
  • ????Mat?A?=?Mat::eye(5,5,CV_8U);??
  • ??
  • ????Mat?B?=?A(Range::all(),Range(1,3));??
  • ????B.setTo(100);??
  • ????for(int?i?=?0;?i?<?5;++i)??
  • ????{??
  • ????????for(int?j?=?0;?j?<?5;++j)??
  • ????????{??
  • ????????????cout<<(int)A.at<uchar>(i,j)<<endl;??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??

  • 如果需要深拷貝,則使用clone方法。


    對于初始化Mat,還有其他的一些方法:
    比如Matlab風格的 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);


    如果是處理“外來”的數據,那么則在構造函數中加上data則會非常方便的將外來數據轉化為Mat結構:

    [cpp]?view plaincopy
  • void?process_video_frame(const?unsigned?char*?pixels,int?width,?int?height,?int?step)??
  • {??
  • ????Mat?img(height,?width,?CV_8UC3,?pixels,?step);??
  • ????GaussianBlur(img,?img,?Size(7,7),?1.5,?1.5);??
  • }??
  • ??
  • double?m[3][3]?=?{{a,?b,?c},?{d,?e,?f},?{g,?h,?i}};??
  • Mat?M?=?Mat(3,?3,?CV_64F,?m).inv();??

  • 特別的,對于與opencv1.X中的IplImage結構的交互:

    [cpp]?view plaincopy
  • IplImage*?img?=?cvLoadImage("greatwave.jpg",?1);??
  • Mat?mtx(img);?//?convert?IplImage*?->?Mat??
  • CvMat?oldmat?=?mtx;?//?convert?Mat?->?CvMat??

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

    總結

    以上是生活随笔為你收集整理的OPENCV中的数据结构总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 三上悠亚在线观看一区二区 | 国产在线不卡av | 国产爆乳无码一区二区麻豆 | 欧美在线视频免费播放 | 成人欧美视频 | 久久超碰av | a√天堂在线 | 国产极品美女高潮无套嗷嗷叫酒店 | 僵尸叔叔在线观看国语高清免费观看 | 美女aaa| 国产午夜精品久久久久久久 | 成年精品| 国产精品免费看片 | 日韩一级欧美 | 亚洲成人av电影在线 | 亚洲精品a区 | 91麻豆成人精品国产免费网站 | 欧美黑人一级爽快片淫片高清 | 美女屁股无遮挡 | 91网在线看 | 日韩免费小视频 | 国产成人亚洲欧洲在线 | 人人爱人人草 | 伊人网亚洲 | 国产一二三四五区 | 亚洲人成无码www久久久 | 久久精品一本 | 天堂男人网| 欧美性大战久久久久xxx | www.欧美视频 | 18pao国产成视频永久免费 | 狂野少女电影在线观看国语版免费 | 看特级黄色片 | 99热这里只有精品久久 | 亚洲福利影院 | 国产精品一品二区三区的使用体验 | 奇米二区 | 性开放耄耋老妇hd | 国产一区二区三区四区三区四 | 国产伦精品一区二区三区高清版禁 | 91丨九色丨蝌蚪丨对白 | 国产精品麻豆一区二区三区 | 国产在线观看a | 国产丝袜美腿一区二区三区 | 日韩电影一区二区三区 | 欧美日韩大片在线观看 | 亚洲无码精品国产 | 久久人妻一区二区 | 成人高清免费 | 日日操日日 | 日批av| 一区二区欧美在线观看 | 国产精品极品白嫩 | 一区二区三区视频免费观看 | 91精品国产综合久久久久久 | 视频在线观看一区 | 成人av在线看 | 少妇紧身牛仔裤裤啪啪 | 日本不卡高清视频 | 成人一级网站 | 日本少妇在线观看 | 国产精品99精品 | 打屁股疼的撕心裂肺的视频 | 欧美情趣视频 | 三级做爰在线观看视频 | 国产熟女一区二区三区四区 | 亚洲免费片| 欧美一级大片 | ,亚洲人成毛片在线播放 | 国产精品伦理一区 | h在线网站 | 亚洲免费在线观看av | 最新成人在线 | 男人的天堂影院 | 中日韩在线视频 | 男男h黄动漫啪啪无遮挡软件 | 99久久久无码国产精品免费麻豆 | 国产毛片毛片毛片毛片毛片 | 黄色片免费在线观看 | 波多野结衣在线视频免费观看 | 欧美亚洲色图视频 | 国产精品综合久久 | 黄色91在线观看 | 欧美熟妇激情一区二区三区 | 少妇高潮久久久久久潘金莲 | 亚洲尤物视频 | 美女扒开粉嫩尿口 | 在线观看自拍 | 日本中文字幕免费观看 | 古装做爰无遮挡三级视频 | 欧美少妇色图 | 日本黄色大片在线观看 | 国产亚洲综合av | 久久精精品久久久久噜噜 | 亚洲精品中文字幕 | 国语对白做受按摩的注意事项 | 天天综合入口 | 日韩少妇av | 国产精品一区二区欧美 |