在OpenCV中要练习的一些基本操作

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) << "\t";  // 打印矩阵 A
 6     cout << endl;
 7 }
 8 
 9 // 第二种
10 cout << "\n" << "A = " << "\n" << A << "\n" << endl;

 

矩阵初始化的几种方式:

 1 // 第一种,初始化,然后逐行逐列输入,再打印
 2 Mat I = Mat(2,2, CV_64F);
 3 cout << "请输入一个" << I.rows << "x" << I.cols << "大小的矩阵" << "\n";
 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 << "\n" << "I = " << "\n" << I << "\n" << 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 << "\n" << 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 << "\n" << "D = " << "\n" << D << "\n" << endl;
10 
11 Mat E = Mat(3, 3, CV_8UC1);
12 randu(E, Scalar::all(0), Scalar::all(255));   // 生成一个随机数矩阵,范围在[0,255)间,8U类型
13 cout << "\n" << "E = " << "\n" << E << "\n" << 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 << "\n" << "F = " << "\n" << F << "\n" << endl;
4 
5 Mat G = Mat(3, 3, CV_8UC1);
6 cv::sortIdx(E,G,CV_SORT_EVERY_COLUMN);    //  看不懂,不知道类似MATLAB中的sortrows有没有,先跳过
7 cout << "\n" << "G = " << "\n" << G << "\n" << endl;

 

对行或列求和:

1 Mat H = Mat(3,3, CV_8UC1);
2 reduce(E, H, 0, CV_REDUCE_SUM, CV_32S);    // 0 是对列求和,1是对行求和,dtype参数要注意
3 cout << "\n" << "H = " << "\n" << H << "\n" << 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 << "\n" << "Ma = " << "\n" << Ma << "\n" << 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 << "\n" << "L = " << "\n" << L << "\n" << endl;
 4 L.at<int>(1,1) = 100;
 5 cout << "\n" << "修改后L = " << "\n" << L << "\n" << endl;
 6 
 7 // 修改某些行或者列
 8 L(Range(0,2), Range::all()) = 20;  
 9 // 行号都是从0开始数起,但是都是左闭右开 [0,2) 代表第0和1行, rowRange、colRange类似
10 cout << "\n" << "修改某些行后的L = " << "\n" << L << "\n" << 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 << "\n" << "bigmat = " << "\n" << bigmat << "\n" << 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 << "\n" << "X = " << "\n" << X << "\n" << endl;
15     cout << "\n" << "mat43 = " << "\n" << mat43 << "\n" << endl;
16 
17     Mat aux = X.colRange(0,2).rowRange(0,2); // you are pointing to submatrix 4x3 at X(0,0)
18     cout << "\n" << "aux = " << "\n" << aux << "\n" << endl;
19     mat43.copyTo(aux);
20     cout << "\n" << "X = " << "\n" << X << "\n" << 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 << "\n" << "C = " << "\n" << C << "\n" << endl;
23             return C;
24         }
25         else
26             cout << "\n[A;B] 类型的拼接要求 A 和 B 的列数一致!\n" << endl;
27     }
28     else
29         cout << "\n A和B的类型不一致,无法拼接!\n" << 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 << "\n" << "C = " << "\n" << C << "\n" << endl;
48             return C;
49         }
50         else
51             cout << "\n[A B] 类型的拼接要求 A 和 B 的行数一致!\n" << endl;
52     }
53     else
54         cout << "\n A和B的类型不一致,无法拼接!\n" << 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 << "\n" << "A = " << "\n" << A << "\n" << endl;
72     cout << "\n" << "B = " << "\n" << B << "\n" << 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 << "\n" << "U = " << "\n" << U << "\n" << endl;
19     cout << "\n" << "S = " << "\n" << S << "\n" << endl;  // 3 x 1 的矩阵,和MATLAB中 3 x 3 的不同
20     cout << "\n" << "VT = " << "\n" << VT << "\n" << 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 << "\n" << "X = " << "\n" << X << "\n" << 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 << "\n" << "RawDataMat = " << "\n" << RawDataMat << "\n" << 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] << "\t" << "col:  " << minidx[1] << endl;
29     cout << "max value at     row:  " << maxidx[0] << "\t" << "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

posted on 2016-08-05 00:15  菠菜僵尸  阅读(1002)  评论(0编辑  收藏  举报