• 在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) << "	";  // 打印矩阵 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

  • 相关阅读:
    Linux编译工具:gcc入门
    Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程
    Socket编程实践(2) Socket API 与 简单例程
    Socket编程实践(1) 基本概念
    数据结构图文解析之:二分查找及与其相关的几个问题解析
    数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
    [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析
    郑重声明!本博客内容皆为原创且首发于博客园
    【原创】面试官:谈谈你对mysql联合索引的认识?
    【原创】为什么Mongodb索引用B树,而Mysql用B+树?
  • 原文地址:https://www.cnblogs.com/shepherd2015/p/5738986.html
Copyright © 2020-2023  润新知