OpenCV上手有一些基本操作要练习下,其实是想把OpenCV玩的像MATLAB一样熟
照着MATLAB的手册从前到后找了下自己经常用到的东西,要完成的操作有:
// zeros ones eyes
// rand sort sortrows sum transpose 用键盘输入的方式初始化矩阵
// 乘法 det行列式 读取和更改任意位置 元素 一行几行 或几列 部分截取和修改填充
// reshape min max
// 拼接 删除 归一化 A(:) triu tril
// 读取矩阵尺寸 flipud fliplr diag
// 1:5:100步进 linspace repmat length meshgrid
// logical .* ./ strcat num2str rank trace
// 打印矩阵 解方程组 sqrt .^2
// sin cos tan arctan log exp 生成复数矩阵
// abs real angle
// fix floor round mod sign pi NaN的处理 conv2
// input interp interp2
// mean std diff
// fft fft2 ifft ifft2 fftshift ifftshift
// fminunc minFunc quad dblquad 可能没有
// 符号计算sym 可能没有
// 文件读写 目录操作 将一个mat的内容写入到文件中,再在另一个程序中读入
// rgb2gray im2bw imresize imrotate imcrop subplot
// ginput conhull imhist edge
// 作图部分还有一大堆,figure mesh surf 之类的,可能要第三方包
// 子矩阵赋值 矩阵拼接 特定列数、行数的抽取,删除
// find 二维矩阵拼接成三维矩阵
// svd
zeros,ones,eye:
1 Mat A = Mat::zeros(3,3, CV_32F); // zeros 2 3 Mat B = Mat::ones(5,5, CV_8U); // ones 4 5 Mat C = Mat::eye(4,4, CV_32F); // eye
打印矩阵的几种方式:
1 // 第一种,逐行逐列打印 2 for(int i=0; i<A.rows; i++) 3 { 4 for(int j=0; j<A.cols; j++) 5 cout << A.at<float>(i,j) << " "; // 打印矩阵 A 6 cout << endl; 7 } 8 9 // 第二种 10 cout << " " << "A = " << " " << A << " " << endl;
矩阵初始化的几种方式:
1 // 第一种,初始化,然后逐行逐列输入,再打印 2 Mat I = Mat(2,2, CV_64F); 3 cout << "请输入一个" << I.rows << "x" << I.cols << "大小的矩阵" << " "; 4 for(int i=0; i<I.rows; i++) 5 { 6 cout << "请输入第" << i << "行的" << I.cols << "个元素" << endl; 7 for(int j=0; j<I.cols; j++) 8 { 9 cin >> I.at<double>(i,j); // 类型问题真他妈烦 10 //I.at<double>(i,j) = i+j; 11 } 12 } 13 cout << " " << "I = " << " " << I << " " << endl; 14 15 // 第二种 16 Mat L = (Mat_<int>(3,3) << 1, -1, 1, -1, 5, -1, 1, -1, 1); 17 18 // 第三种 19 double b[] = {66, 0, 21, 8}; 20 Mat N = Mat(2, 2, CV_64FC1, b); 21 22 // 第四种 23 Mat K(Matx33d( 24 2759.48, 0, 1520.69, 25 0, 2764.16, 1006.81, 26 0, 0, 1));
生成一个随机数或者随机矩阵:
1 // 随机数 2 RNG rng; // Random number generator 3 double x = rng.uniform( (double)0, (double)1); // 生成一个随机数 double类型,[0,1)之间 4 cout << "x = " << x << " " << endl; 5 6 // 随机矩阵 7 Mat D = Mat(3, 3, CV_32F); 8 randu(D, Scalar::all(0), Scalar::all(1)); // 生成一个随机数矩阵,范围在[0,1)间,float类型 9 cout << " " << "D = " << " " << D << " " << endl; 10 11 Mat E = Mat(3, 3, CV_8UC1); 12 randu(E, Scalar::all(0), Scalar::all(255)); // 生成一个随机数矩阵,范围在[0,255)间,8U类型 13 cout << " " << "E = " << " " << E << " " << endl;
排序,MATLAB中是sort和sortrows,但是没找到OpenCV中实现MATLAB中sortrows这种扩展排序的函数,先跳过:
1 Mat F = Mat(3, 3, CV_8UC1); 2 cv::sort( E, F, CV_SORT_EVERY_COLUMN); // 对每一列排序,注意要添加cv::,不然会认为是std中的sort,E是上面生成的随机矩阵 3 cout << " " << "F = " << " " << F << " " << endl; 4 5 Mat G = Mat(3, 3, CV_8UC1); 6 cv::sortIdx(E,G,CV_SORT_EVERY_COLUMN); // 看不懂,不知道类似MATLAB中的sortrows有没有,先跳过 7 cout << " " << "G = " << " " << G << " " << endl;
对行或列求和:
1 Mat H = Mat(3,3, CV_8UC1); 2 reduce(E, H, 0, CV_REDUCE_SUM, CV_32S); // 0 是对列求和,1是对行求和,dtype参数要注意 3 cout << " " << "H = " << " " << H << " " << endl; 4 // 项目--属性--配置属性--C/C++--常规--多处理器编译--选择 是(/MP) 会让程序更快
矩阵转置,乘法,点乘:
1 A.t() 2 3 Mat J = I*I; // 乘法 4 5 Mat K = J.mul(J); // 点乘
类型转换:
1 Mat L1; 2 L.convertTo(L1,CV_32FC1); // L 转换为 L1 的 CV_32FC1 类型
求矩阵的行列式的值:
double a[] = {2, 0, 0, 2}; Mat Ma = Mat(2, 2, CV_64FC1, a); // 这也是一种矩阵初始化方式 double dst = determinant(Ma); // 小矩阵求行列式的值 cout << " " << "Ma = " << " " << Ma << " " << endl; cout << "det of Ma is :" << dst << endl; //小型方阵直接计算,大型方阵(大于 3 x 3 的)用高斯消去法计算 //如果矩阵正定对称,用奇异值分解的方法解决 SVD; 以后解决
修改矩阵中某些元素或者某行某列的值:
1 // 用 A.at<type>(i,j)修改 2 Mat L = (Mat_<int>(3,3) << 1, -1, 1, -1, 5, -1, 1, -1, 1); 3 cout << " " << "L = " << " " << L << " " << endl; 4 L.at<int>(1,1) = 100; 5 cout << " " << "修改后L = " << " " << L << " " << endl; 6 7 // 修改某些行或者列 8 L(Range(0,2), Range::all()) = 20; 9 // 行号都是从0开始数起,但是都是左闭右开 [0,2) 代表第0和1行, rowRange、colRange类似 10 cout << " " << "修改某些行后的L = " << " " << L << " " << endl; 11 12 // 下面这种方法自己也没搞透,貌似只能scalar,stackoverflow上看到的 13 Mat bigmat = Mat::zeros(5,5, CV_64FC1);; //Full matrix 14 Rect r(1,1,2,2); // Part of the matrix we are interested in 15 Mat roi(bigmat, r); // This submatrix will be a REFERENCE to PART of full matrix, NOT a copy 16 roi = Scalar(1); 17 cout << " " << "bigmat = " << " " << bigmat << " " << endl;
对矩阵的子矩阵赋值是一个经常使用到的重要操作,就算OpenCV中没有诸如MATLAB中[A;B]或者[A B]这种矩阵拼接方式,也可以通过新建一个矩阵
然后再把要拼接的矩阵赋值到子矩阵完成。
还有矩阵中特定行数或者列数的抽取、删除也很重要,以及诸如find函数,二维矩阵拼接成三维矩阵都相当重要。
先练习了下子矩阵赋值,也是stackoverflow上看到的:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 int main() 8 { 9 Mat X = Mat::zeros(5,5,CV_32FC1); 10 //Mat mat43= Mat::eye(2,2,CV_32FC1); 11 float b[] = {66, 0, 21, 8}; 12 Mat mat43 = Mat(2, 2, CV_32FC1, b); 13 14 cout << " " << "X = " << " " << X << " " << endl; 15 cout << " " << "mat43 = " << " " << mat43 << " " << endl; 16 17 Mat aux = X.colRange(0,2).rowRange(0,2); // you are pointing to submatrix 4x3 at X(0,0) 18 cout << " " << "aux = " << " " << aux << " " << endl; 19 mat43.copyTo(aux); 20 cout << " " << "X = " << " " << X << " " << endl; 21 22 system("PAUSE"); 23 24 return 0; 25 }
OpenCV中矩阵拼接:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 Mat cat1(Mat A, Mat B) 8 { 9 if(A.type()==B.type()) 10 { 11 // [A;B] 竖直方向拼接 12 if(A.cols==B.cols) 13 { 14 Mat C = Mat( A.rows + B.rows, A.cols, A.type()); 15 16 Mat Apart = C.rowRange(0, A.rows).colRange(0, A.cols); 17 Mat Bpart = C.rowRange(A.rows, A.rows+B.rows).colRange(0, A.cols); 18 19 A.copyTo(Apart); 20 B.copyTo(Bpart); 21 22 cout << " " << "C = " << " " << C << " " << endl; 23 return C; 24 } 25 else 26 cout << " [A;B] 类型的拼接要求 A 和 B 的列数一致! " << endl; 27 } 28 else 29 cout << " A和B的类型不一致,无法拼接! " << endl; 30 } 31 32 Mat cat2(Mat A, Mat B) 33 { 34 if(A.type()==B.type()) 35 { 36 // [A B] 水平方向拼接 37 if(A.rows==B.rows) 38 { 39 Mat C = Mat( A.rows , A.cols+B.cols, A.type()); 40 41 Mat Apart = C.rowRange(0, A.rows).colRange(0, A.cols); 42 Mat Bpart = C.rowRange(0, A.rows).colRange(A.cols, A.cols+B.cols); 43 44 A.copyTo(Apart); 45 B.copyTo(Bpart); 46 47 cout << " " << "C = " << " " << C << " " << endl; 48 return C; 49 } 50 else 51 cout << " [A B] 类型的拼接要求 A 和 B 的行数一致! " << endl; 52 } 53 else 54 cout << " A和B的类型不一致,无法拼接! " << endl; 55 } 56 57 int main() 58 { 59 //Mat A = Mat::zeros(3,4, CV_64F); 60 //Mat B = Mat::eye(3,4, CV_64F); 61 62 Mat A = (Mat_<double>(3,3) << 63 1, -1, 1, 64 -1, 5, -1, 65 1, -1, 1); 66 Mat B = (Mat_<double>(3,3) << 67 1, 2, 3, 68 4, 5, 6, 69 7, 8, 9); 70 71 cout << " " << "A = " << " " << A << " " << endl; 72 cout << " " << "B = " << " " << B << " " << endl; 73 74 cout << A.type() << endl; 75 cout << B.type() << endl; 76 77 Mat C = cat2(B,A); 78 79 system("pause"); 80 return 0; 81 }
==========================================================================
Mat矩阵保存到xml中,以及从xml中读取数据到Mat中,文件后缀也可以是txt:
1 #include <iostream> 2 #include <fstream> 3 #include <iterator> 4 #include <vector> 5 #include <opencv2/opencv.hpp> 6 7 using namespace std; 8 using namespace cv; 9 10 11 int main() 12 { 13 Mat mat = Mat::eye(5,5,CV_32FC1); 14 FileStorage fs(".\vocabulary.xml", FileStorage::WRITE); 15 fs<<"vocabulary"<<mat; 16 fs.release(); 17 18 FileStorage fs(".\vocabulary.xml", FileStorage::READ); 19 Mat mat_vocabulary; 20 fs["vocabulary"] >> mat_vocabulary; 21 22 return 0; 23 }
==========================================================================
SVD:
在MATLAB中做了下测试
A = ...
[1 0 1;
-1 -2 0;
0 1 -1]
svd后得到
U =
-0.1200 -0.8097 0.5744
0.9018 0.1531 0.4042
-0.4153 0.5665 0.7118
S =
2.4605 0 0
0 1.6996 0
0 0 0.2391
V =
-0.4153 -0.5665 0.7118
-0.9018 0.1531 -0.4042
0.1200 -0.8097 -0.5744
其中:
AA = U*S*V'= A
OpenCV中svd如下:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() 8 { 9 Mat A = (Mat_<float>(3,3) << 1, 0, 1, -1, -2, 0, 0, 1, -1); 10 11 Mat U(3,3,CV_64F), S(3,1,CV_64F), VT(3,3,CV_64F); 12 SVD thissvd(A,SVD::FULL_UV); 13 14 U = thissvd.u; 15 S = thissvd.w; 16 VT = thissvd.vt;// 已经转置了 17 18 cout << " " << "U = " << " " << U << " " << endl; 19 cout << " " << "S = " << " " << S << " " << endl; // 3 x 1 的矩阵,和MATLAB中 3 x 3 的不同 20 cout << " " << "VT = " << " " << VT << " " << endl; 21 22 system("PAUSE"); 23 24 return 0; 25 }
OpenCV中解线性方程组:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() 8 { 9 Mat A(Matx33d( 10 8, 1, 6, 11 3, 5, 7, 12 4, 9, 2)); // 由 MATLAB 中的 magic(3) 产生的矩阵 13 14 Mat B(Matx31d( 15 1, 16 2, 17 3)); 18 19 Mat X = Mat(3,1, CV_64F); 20 21 solve(A, B, X, DECOMP_LU); // AX = B 22 23 cout << " " << "X = " << " " << X << " " << endl; 24 25 system("pause"); 26 return 0; 27 } 28 29 //A = 30 // 8 1 6 31 // 3 5 7 32 // 4 9 2 33 // 34 //B = 35 // 1 36 // 2 37 // 3 38 // 39 //X = 40 // 0.0500 41 // 0.3000 42 // 0.0500
寻找最大最小值并返回索引值:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 8 int main() 9 { 10 double RawData[2][3] = 11 {{ 4.5, 1.1, 1.0 }, 12 { 8.1, 27.2, 19.9 }}; 13 Mat RawDataMat(2,3,CV_64F,RawData); 14 15 cout << " " << "RawDataMat = " << " " << RawDataMat << " " << endl; 16 17 double minv = 0.0, maxv = 0.0; 18 double* minp = &minv; 19 double* maxp = &maxv; 20 21 22 int minidx[2] = {0, 0}, maxidx[2] = {0, 0}; 23 double minval = 0, maxval = 0; 24 minMaxIdx(RawDataMat, &minval, &maxval, minidx, maxidx); 25 26 cout << "minval = " << minval << endl; 27 cout << "maxval = " << maxval << endl; 28 cout << "min value at row: " << minidx[0] << " " << "col: " << minidx[1] << endl; 29 cout << "max value at row: " << maxidx[0] << " " << "col: " << maxidx[1] << endl; 30 31 system("pause"); 32 return 0; 33 }
编辑时间:
2016年8月5日00:15:00
2016年8月8日00:06:35
2016年8月12日13:21:57
2016年8月16日18:50:14
2016年8月16日23:47:02
2016年8月17日17:09:43