本文主要參考 Marc 的 OpenCV 筆記
OpenCV 主要 support C++ 和 Python 兩種 interfaces.
之前主要以 python 為主。不過在某些情況 C++ 的 computation efficiency 有優勢。
因此熟悉基本操作仍有需要。
基本操作 (Base Operation)
- Basic Matrix Operation
- Convert Binary Data to OpenCV Image Format
- Mouse Control on OpenCV GUI
- OpenCV Get Pixel Value from Mat
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