OpenCV 第二課 認識圖像的存儲結構
Mat 類包含兩部分,矩陣頭和矩陣體。矩陣頭包含矩陣的大小,存儲方式和矩陣體存儲空間的指針。因此,Mat中矩陣頭的大小是固定的,矩陣體大小是不定的。
為了減少矩陣拷貝產生的計算消耗,opencv中一般使用引用計數方式處理矩陣,比如下面三種創建Mat的形式
- Mat A,C; //這里僅僅創建了矩陣頭,具體矩陣體還沒創建
- A=imread(argv[1],CV_LOAD_IMAGE_COLOR); //給矩陣分配空間,並將首地址給了A
- Mat B(A); //拷貝構造函數,B是A的拷貝,只是矩陣頭不同
- C=A; //賦值操作仍然指向的是同一塊矩陣體地址。
這時候使用任何一個Mat對象修改數據,其他的對象也會跟着變化。
如果想拷貝矩陣體,那么可以使用clone()和copyTo()函數。
- Mat F=A.clone();
- Mat G;
- A.copyTo(G)
為什么稱為reference counting system呢,因為每次拷貝矩陣拷貝次數都加1,當一個拷貝結束時,拷貝次數減一,最后一個引用決定了這塊地址什么時候釋放。
需要注意的點:
Output image allocation for OpenCV functions is automatic (unless specified otherwise).
You do not need to think about memory management with OpenCVs C++ interface.
The assignment operator and the copy constructor only copies the header.
The underlying matrix of an image may be copied using the clone() and copyTo() functions
Mat的結構
- class CV_EXPORTS Mat
- {
- public:
- int flags;//標志位
- int dims;//維度>=2
- int rows,cols;//行和列或者(-1,-1),此時數組超過了2維
- uchar * data;//矩陣數據塊的指針
- int *refcount;//指針引用計數器
- }
Mat的構造函數
- #include "opencv2/imgproc/imgproc.hpp"
- #include "opencv2/highgui/highgui.hpp"
- #include <iostream>
- #include<stdlib.h>
- using namespace cv;
- using namespace std;
-
- int main()
- {
- Mat image1; //創建無初始化的矩陣
- Mat image2(6, 6, CV_8UC1);//創建大小為6*6,8位unsigned單通道矩陣
- Mat image3(Size(7, 7), CV_8UC3);//創建7*7的size,8位無符號3通道矩陣
- Mat image4(8, 8, CV_32FC2, Scalar(1, 3));//創建8*8,32位浮點型2通道矩陣,賦值1+3j
- Mat image5(Size(9, 9), CV_8UC3, Scalar(1, 2, 3));//創建9*9大小的矩陣,3通道,8位無符號型,每一個位置三個通道初始化值為(1,2,3)
- Mat image6(image2);//使用已經創建的矩陣創建矩陣,這時候僅拷貝矩陣頭,矩陣值指針是相同的
- cout << image1 << endl;
- cout << image2 << endl;
- cout << image3 << endl;
- cout << image4 << endl;
- system("PAUSE");
-
- }

1474894045162.jpg
看輸出結果可以看出,Mat數據在存儲時首先向同一個位置的多個通道值存儲了再存儲別的位置元素。
Mat的基本操作
- #include "opencv2/imgproc/imgproc.hpp"
- #include "opencv2/highgui/highgui.hpp"
- #include <iostream>
- #include<stdlib.h>
- using namespace cv;
- using namespace std;
-
- int main()
- {
-
- Mat image1(10, 8, CV_8UC1, Scalar(5));
- cout << "Image1 rows:" << image1.rows << endl; //行數
- cout << "Image1 col:" << image1.cols << endl;//列數
- cout << "Image channel:" << image1.channels ()<< endl;//通道,方法
-
- cout << image1.rowRange(1, 3) << endl; //取1,2兩行
- cout << image1.colRange(1, 4) << endl;//取1,2,3列
-
- Mat image2(8, 8, CV_32FC2, Scalar(1, 5));
- image2.create(10, 10, CV_8UC3);//create重建舉着數據
-
- //cout << image2 << endl;
- image2.convertTo(image2, CV_32F);//類型轉換
- cout << "Image2 depth:" << image2.depth() << endl;//深度,方法
-
- Mat image3 = Mat::zeros(image1.rows, image1.cols, CV_8UC1);//全零矩陣
- Mat image4 = Mat::ones(image2.rows, image2.cols, CV_8UC1);//全一矩陣
- image4.row(1) = image4.row(2) * 5; //矩陣行操作,列操作可以使用row(),col()函數直接操作
- cout << image4 << endl;
-
- Mat image5 = image2.row(2);
- image1.row(1).copyTo(image5);//第一行拷貝到image5
- cout << image5 << endl;
-
- system("PAUSE");
-
- }
-