2016年7月2日 星期六

OpenCV 筆記 - Basic Operation

本文主要參考 Marc 的 OpenCV 筆記

OpenCV 主要 support C++ 和 Python 兩種 interfaces.

之前主要以 python 為主。不過在某些情況 C++ 的 computation efficiency 有優勢。

因此熟悉基本操作仍有需要。

基本操作 (Base Operation)

OpenCV 最重要的 data format 是 (2-D) matrix.  因為這是多數影像的型態。  

 

Basic Matrix Operation:  OpenCV 常會用到 cv::Mat 陣列。

如何建立矩陣? 直接宣告矩陣大小和型態。

Mat image(240, 320, CV_8UC3);

image size 是 240x320.  格式是 CV_8UC3 -> CV_<bit-depth> {U|S|F}C(<number of channels>)

U 是 unsigned integer type, S 是 signed integer type, and F 是 float type.

所以 8UC3 就是 8bit, unsigned integer, 3 channels (e.g. RGB or actually BGR image).

 

重新分配矩陣大小

image.create(480, 640, CV_8UC3);

 

宣告矩陣並設定初始值 (下例都初始化為 5), 和 matlab 類似

Mat A33(3, 3, CV_32F, Scalar(5));

另一種方式是用 ones matrix

Mat B33 = Mat::ones(3, 3, CV_32F)*5.;

或是用 zeros matrix

Mat C33 = Mat::zeros(3, 3, CV_32F) + 5.;

以上的方法似乎只用於 1 channel case.

如果宣告 3 channels.  只有 channel 1 有初始值。

 

如果要 3 channels 都有初始值。可以用以下的方法:

Mat img1(5, 5, CV_8UC1, Scalar(9) );

Mat dst;

cvtColor(img1, dst, CV_GRAY2RGB);

此是 dst 會是 CV_8UC3 且初始化為 9.

 

宣告指定數值的矩陣

Mat A22 = Mat_<float>(2,2) << 5, -15, 20, -15);

或是

float B22data[] = { 5, -15, 20, -15};

Mat B22 = Mat(2, 2, CV_32F, B22data).clone();

註: 用 clone 會複製到新的 memory.

如果不用 clone 也可以。但變成 pointer 而非 memory copy.

如果 B22data 改變,也會改變 B22.

 

 

轉移矩陣但不複製 memory

cv::Mat 轉換成 cv::Mat

Mat image_alias = image

 

將一般陣列轉換成 cv::Mat

float* Idata = new float[480*640*3];

Mat I(480, 640, CV_32FC3, Idata); 

 

vector陣列轉換成cv::Mat

vector<Point> iptvec(10); Mat dstMat(iptvec); 

IplImage轉換成cv::Mat

IplImage* iMG = cvCreateImage(cvSize(320,240), 16, 1); Mat dstMat = cvarrToMat(iMG);

cv::Mat轉換成IplImage

Mat srcMat; IplImage iMG = srcMat; 

cv::Mat轉換成CvMat

Mat srcMat; CvMat dstCvMat = srcMat;

轉移矩陣且複製 memory

IplImage複製給cv::Mat

IplImage* iMG = cvCreateImage(cvSize(320,240), 16, 1); Mat dstMat = cvarrToMat(iMG).clone();

cv::Mat複製給vector

Mat srcMat; vector<Point2f> ptvec = Mat_<Point2f>(srcMat);

cv::Mat 合併、插入、移除

cv::Mat hMat(5,1,CV_8UC1,cv::Scalar(2)); cv::Mat sMat(5,1,CV_8UC1,cv::Scalar(5)); cv::Mat tmpMat(5,2, CV_8UC1 ); hMat.copyTo( tmpMat.col(0) ); sMat.copyTo( tmpMat.col(1) ); /* 25 25 25 25 25 */

合併cv::Mat

cv::Mat mat1(1,3, CV_8UC1,cv::Scalar(2)); cv::Mat mat2(2,3, CV_8UC1,cv::Scalar(3)); cv::Mat matM; matM.push_back(mat1); matM.push_back(mat2); /* 222 333 333 */

型態轉換(int、float、double)

** CV_8UC1 to CV_32FC1

cv::Mat mat8U(3,2,CV_8UC1,cv::Scalar(2)); cv::Mat mat32F; mat8U.convertTo(mat32F, CV_32FC1);

陣列運算cv::Mat

計算陣列中非0值的數量

cv::Mat src(5,3,CV_8UC1, cv::Scalar(3)); int total = cv::countNonZero(src); std::cout<<total; //15

 

 

 

追蹤者