C++之OpenCV入門到提高004:Mat 物件的使用

可均可可發表於2024-11-08
一、介紹
    今天是這個系列《C++之 Opencv 入門到提高》得第四篇文章。這篇文章很簡單,介紹如何使用 Mat 物件來例項化影像例項,瞭解它的建構函式和常用的方法,這是基礎,為以後的學習做好鋪墊。雖然操作很簡單,但是背後有很多東西需要我們深究,才能做到知其然知其所以然。OpenCV 具體的簡介內容,我就不多說了,網上很多,大家可以自行腦補。
    OpenCV 的官網地址:https://opencv.org/,元件下載地址:https://opencv.org/releases/
    OpenCV 官網學習網站:https://docs.opencv.ac.cn/4.10.0/index.html

    我需要進行說明,以防大家不清楚,具體情況我已經羅列出來。
        作業系統:Windows Professional 10(64位)
        開發元件:OpenCV – 4.10.0
        開發工具:Microsoft Visual Studio Community 2022 (64 位) - Current版本 17.8.3
        開發語言:C++(VC16)

二、知識學習
    如果我們想學習或者使用 OpenCV,它的影像物件 Mat 是繞不過去的。我們對它越熟悉,使用的越靈活。俗話說得好,慾善其事必先利其器。內容很簡單,直接上程式碼,程式碼裡面有註釋。廢話不說了。
  1 #include <opencv2/opencv.hpp>
  2 #include <iostream>
  3 #include <math.h>
  4 
  5 using namespace std;
  6 using namespace cv;
  7 
  8 int main()
  9 {
 10     //1、Mat 物件與 IplImage 物件
 11     // 1.1、IplImage 物件是從 2001 年 OpenCV 釋出之後就一直存在的,它是一個具有 C 語言風格的資料結構,需要開發者自己分配和管理記憶體,在大型專案中容易導致記憶體洩漏。
 12     // 1.2、Mat 物件是在 OpenCV 2.0 之後才引進的影像資料結構,自動分配記憶體,不存在記憶體洩漏的問題,是下物件導向的資料結構。該 Mat 物件分成兩部分,頭部和資料部分。
 13     // 1.3、 Mat 型別建構函式和常用方法。
 14     // 
 15     // 1.3.1、建構函式
 16     // 1.3.1.1、Mat()
 17     // 1.3.1.2、Mat(int rows, int cols, int type);
 18     // 1.3.1.3、Mat(Size size, int type);
 19     // 1.3.1.4、Mat(int rows, int cols, int type, const Scalar& s);
 20     // 1.3.1.5、Mat(Size size, int type, const Scalar& s);
 21     // 1.3.1.6、Mat(int ndims, const int* sizes, int type);
 22     // 1.3.1.7、Mat(int ndims, const int* sizes, int type, const Scalar& s);
 23     // 還有很多,就不列舉了
 24     // 
 25     // 1.3.2、常用方法
 26     // 1.3.2.1、void copyTo( OutputArray m ) const;
 27     // 1.3.2.2、void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
 28     // 1.3.2.3、Mat clone() const; 是完全複製,可以得到一個全新的 Mat 物件。
 29     // 1.3.2.4、int channels() const;
 30     // 1.3.2.5、int depth() const;
 31     // 1.3.2.6、bool empty() const;
 32     // 1.3.2.7、uchar* ptr(int i0=0);
 33     // 還有很多,就不列舉了
 34     // 
 35     // 
 36     //2、Mat 物件使用
 37     // 2.1、部分複製:一般情況下只會複製 Mat 物件的頭部和指標部分,資料部分是不會複製的。
 38     //        Mat a=imread(imagefilePath);
 39     //        Mat b(a); 透過複製構造就不會資料部分。
 40     // 2.2、完全複製:如果想把 Mat 物件的頭部和資料部分一起復制,可以透過 Mat 的 clone() 或者 copyTo() 方法。
 41     // 2.3、使用 Mat 物件的四個要點
 42     //        A、輸出影像的記憶體是自動分配的。
 43     //        B、使用OpenCV的 C++ 介面,不需要考慮記憶體分配的問題。
 44     //        C、賦值操作和複製建構函式只會複製頭部和指標部分,資料部分不會複製。
 45     //        D、使用 clone 和 copyTo 兩個函式可以實現完全複製。
 46     // 
 47     //3、Mat 定義陣列
 48     //建立多維資料 Mat::create
 49     // int sz[3]={2,2,2};
 50     // Mat a(3,sz,CV_8UC1,Scalar::all(0));
 51 
 52 
 53     Mat src;
 54     src = imread("F:\\TestImage\\ZZImage\\psb14.jpg", IMREAD_UNCHANGED);
 55     if (src.empty())
 56     {
 57         cout << "載入影像有錯誤!!" << endl;
 58         return -1;
 59     }
 60 
 61     namedWindow("DemoWindow", WINDOW_AUTOSIZE);
 62     imshow("DemoWindow", src);
 63 
 64 
 65 
 66     /*Mat dst;
 67     dst = Mat(src.size(),src.type());
 68     dst = Scalar(0,255,0);*/
 69 
 70 
 71     //Mat dst;
 72     //dst = Mat(src.size(), src.type());//此語句可省略
 73     //dst = src.clone();
 74 
 75     /*Mat dst;
 76     src.convertTo(dst,src.type());*/
 77 
 78     /*Mat dst;
 79     src.copyTo(dst);*/
 80 
 81     /*Mat dst;
 82 
 83     cvtColor(src, dst, COLOR_BGR2GRAY);
 84     cout << "原圖通道:" << src.channels() << endl;
 85     cout << "目標圖通道:" << dst.channels() << endl;
 86 
 87     int height = dst.rows;
 88     int width = dst.cols;
 89     cout << "行數:" << height << endl;
 90     cout << "列數:" << width << endl;
 91 
 92     const uchar* firstRow = dst.ptr<uchar>(0);
 93     cout << "第一行的值:" << *firstRow << endl;*/
 94 
 95     /*Mat dst(3, 3, CV_8UC1, Scalar(0));
 96 
 97     cout << "dst=" << endl << dst << endl;*/
 98 
 99     //Mat dst;
100     //dst.create(src.size(),src.type());
101     ////透過 create 方法不能直接複製。
102     //dst = Scalar(0,0,255);
103 
104 
105     /*Mat dst = Mat::zeros(src.size(),src.type());*/
106 
107     Mat dst = Mat::eye(2,2,CV_8UC1);
108     cout << "dst=" << endl << dst << endl;
109 
110     namedWindow("DemoWindow2", WINDOW_AUTOSIZE);
111     imshow("DemoWindow2", dst);
112 
113     waitKey(0);
114 
115     return 0;
116 }

    內容很簡單,就不多說了。


三、總結
    這是 C++ 使用 OpenCV 的第四篇文章,其實也沒那麼難,感覺是不是還是很好入門的,那就繼續。初見成效,繼續努力。皇天不負有心人,不忘初心,繼續努力,做自己喜歡做的,開心就好。

相關文章