Opencv 例程讲解 4 ----图片容器Mat

来源:互联网 发布:java简历工作经历 编辑:程序博客网 时间:2024/05/22 08:11

     在前面的几个例程中,我们都有用到一个类 Mat,它作为opencv中图像数据,特征点,查表数组,直方图等数据的容器,可能是opencv中运用最普遍的一个类,几乎大多数的API都为这一数据类型留有接口。这次例程中,我们将看下opencv例程中是怎样展示这样一个强大的类的。对应的例程为 (TUTORIAL) mat_the_basic_image_container。

源代码如下:

/*  For description look into the help() function. */#include "opencv2/core/core.hpp"#include <iostream>using namespace std;using namespace cv;static void help(){    cout    << "\n--------------------------------------------------------------------------" << endl    << "This program shows how to create matrices(cv::Mat) in OpenCV and its serial"    << " out capabilities"                                                            << endl    << "That is, cv::Mat M(...); M.create and cout << M. "                            << endl    << "Shows how output can be formated to OpenCV, python, numpy, csv and C styles." << endl    << "Usage:"                                                                       << endl    << "./cvout_sample"                                                               << endl    << "--------------------------------------------------------------------------"   << endl    << endl;}int main(int,char**){    help();    // create by using the constructor    Mat M(2,2, CV_8UC3, Scalar(0,0,255));    cout << "M = " << endl << " " << M << endl << endl;    // create by using the create function()    M.create(4,4, CV_8UC(2));    cout << "M = "<< endl << " "  << M << endl << endl;    // create multidimensional matrices    int sz[3] = {2,2,2};    Mat L(3,sz, CV_8UC(1), Scalar::all(0));    // Cannot print via operator <<    // Create using MATLAB style eye, ones or zero matrix    Mat E = Mat::eye(4, 4, CV_64F);    cout << "E = " << endl << " " << E << endl << endl;    Mat O = Mat::ones(2, 2, CV_32F);    cout << "O = " << endl << " " << O << endl << endl;    Mat Z = Mat::zeros(3,3, CV_8UC1);    cout << "Z = " << endl << " " << Z << endl << endl;    // create a 3x3 double-precision identity matrix    Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);    cout << "C = " << endl << " " << C << endl << endl;    Mat RowClone = C.row(1).clone();    cout << "RowClone = " << endl << " " << RowClone << endl << endl;    // Fill a matrix with random values    Mat R = Mat(3, 2, CV_8UC3);    randu(R, Scalar::all(0), Scalar::all(255));    // Demonstrate the output formating options    cout << "R (default) = " << endl <<        R           << endl << endl;    cout << "R (python)  = " << endl << format(R,"python") << endl << endl;    cout << "R (numpy)   = " << endl << format(R,"numpy" ) << endl << endl;    cout << "R (csv)     = " << endl << format(R,"csv"   ) << endl << endl;    cout << "R (c)       = " << endl << format(R,"C"     ) << endl << endl;    Point2f P(5, 1);    cout << "Point (2D) = " << P << endl << endl;    Point3f P3f(2, 6, 7);    cout << "Point (3D) = " << P3f << endl << endl;    vector<float> v;    v.push_back( (float)CV_PI);   v.push_back(2);    v.push_back(3.01f);    cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;    vector<Point2f> vPoints(20);    for (size_t i = 0; i < vPoints.size(); ++i)        vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));    cout << "A vector of 2D Points = " << vPoints << endl << endl;    return 0;}

可以看出,这个例程首先介绍了Mat 的几种基本的创建方法,包括利用构造函数创建,利用create函数创建;创建N-dimensional矩阵的方法等;接着展示了以不同风格输出mat数据的方法,包括默认风格,python风格,numpy风格,csv风格和c风格;最后,展示了opencv中二位点,三维点,序列以及序列点的数据的创建和输出。下面给出上述代码各自对应的输出结果。

1.利用构造函数创建,函数原型为 Mat(int rows, int cols, int type, const Scalar& s);   Scalar 为一个四通道的double序列。CV_8UC3表示通道数位3,数据类型为CV_8U,还有其他几种类似的构造函数,有Scalar 参数的以Scalar的值进行初始化,没有设定初始化值的,初始化值不确定,但似乎有一定的规律,见下面create的结果。

    //! constructs 2D matrix of the specified size and type    // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)    Mat(int rows, int cols, int type);    Mat(Size size, int type);    //! constucts 2D matrix and fills it with the specified value _s.    Mat(int rows, int cols, int type, const Scalar& s);    Mat(Size size, int type, const Scalar& s);

    // create by using the constructor    Mat M(2,2, CV_8UC3, Scalar(0,0,255));    cout << "M = " << endl << " " << M << endl << endl;

M =
 [0, 0, 255, 0, 0, 255;
  0, 0, 255, 0, 0, 255]

2.利用create 函数创建,函数原型为void create(int rows, int cols, int type); 第一个参数为列数,第二个参数为函数,第三参数为type,CV_8UC(2) 表示通道数位2,数据类型为CV_8U的type

  // create by using the create function()    M.create(4,4, CV_8UC(2));    cout << "M = "<< endl << " "  << M << endl << endl;
M =
 [205, 205, 205, 205, 205, 205, 205, 205;
  205, 205, 205, 205, 205, 205, 205, 205;
  205, 205, 205, 205, 205, 205, 205, 205;
  205, 205, 205, 205, 205, 205, 205, 205]

3创建n-维的矩阵,注意这种Mat 不支持 cout<<输出,函数原型为Mat(int ndims, const int* sizes, int type, const Scalar& s); 同样存在一个不带初始化值的版本

Mat(int ndims, const int* sizes, int type);

    // create multidimensional matrices    int sz[3] = {2,2,2};    Mat L(3,sz, CV_8UC(1), Scalar::all(0));

4 创建matlab风格的矩阵,不详细介绍了,一看就明白

    // Create using MATLAB style eye, ones or zero matrix    Mat E = Mat::eye(4, 4, CV_64F);    cout << "E = " << endl << " " << E << endl << endl;    Mat O = Mat::ones(2, 2, CV_32F);    cout << "O = " << endl << " " << O << endl << endl;    Mat Z = Mat::zeros(3,3, CV_8UC1);    cout << "Z = " << endl << " " << Z << endl << endl;
E =
 [1, 0, 0, 0;
  0, 1, 0, 0;
  0, 0, 1, 0;
  0, 0, 0, 1]

O =
 [1, 1;
  1, 1]

Z =
 [0, 0, 0;
  0, 0, 0;
  0, 0, 0]

5. 通过模板类Mat_创建,它是Mat 的派生模板类,两者之间可以相互隐式转换。Mat_主要实现对Mat 数据的迭代访问,可以利用坐标自己对像素进行操作,如果看过上一个例程的话,应该会对这个类型有影响。这里是用这个类型读入数据。

    // create a 3x3 double-precision identity matrix    Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);    cout << "C = " << endl << " " << C << endl << endl;
C =
 [0, -1, 0;
  -1, 5, -1;
  0, -1, 0]

6. 展示了Mat 对列数据的操作

    Mat RowClone = C.row(1).clone();    cout << "RowClone = " << endl << " " << RowClone << endl << endl;
RowClone =
 [-1, 5, -1]

7. 利用随机数函数randu 初始化数据,函数原型为 void randu(InputOutputArray dst, InputArray low, InputArray high); 值的范围为[low, high)

    // Fill a matrix with random values    Mat R = Mat(3, 2, CV_8UC3);    randu(R, Scalar::all(0), Scalar::all(255));
 

8 展示了几种风格的输出

    // Demonstrate the output formating options    cout << "R (default) = " << endl <<        R           << endl << endl;    cout << "R (python)  = " << endl << format(R,"python") << endl << endl;    cout << "R (numpy)   = " << endl << format(R,"numpy" ) << endl << endl;    cout << "R (csv)     = " << endl << format(R,"csv"   ) << endl << endl;    cout << "R (c)       = " << endl << format(R,"C"     ) << endl << endl;
R (default) =
[91, 2, 79, 179, 52, 205;
  236, 8, 181, 239, 26, 248;
  207, 218, 45, 183, 158, 101]

R (python)  =
[[[91, 2, 79], [179, 52, 205]],
  [[236, 8, 181], [239, 26, 248]],
  [[207, 218, 45], [183, 158, 101]]]

R (numpy)   =
array([[[91, 2, 79], [179, 52, 205]],
  [[236, 8, 181], [239, 26, 248]],
  [[207, 218, 45], [183, 158, 101]]], type='uint8')

R (csv)     =
91, 2, 79, 179, 52, 205
  236, 8, 181, 239, 26, 248
  207, 218, 45, 183, 158, 101

R (c)       =
{91, 2, 79, 179, 52, 205,
  236, 8, 181, 239, 26, 248,
  207, 218, 45, 183, 158, 101}

9 2维点,3维点,序列,点序列,比较简单,就不多加介绍了。注意序列不支持直接用cout<<输出,但可以转换成Mat进行输出。

   Point2f P(5, 1);    cout << "Point (2D) = " << P << endl << endl;    Point3f P3f(2, 6, 7);    cout << "Point (3D) = " << P3f << endl << endl;    vector<float> v;    v.push_back( (float)CV_PI);   v.push_back(2);    v.push_back(3.01f);    cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;    vector<Point2f> vPoints(20);    for (size_t i = 0; i < vPoints.size(); ++i)        vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));    cout << "A vector of 2D Points = " << vPoints << endl << endl;

Point (2D) = [5, 1]

Point (3D) = [2, 6, 7]

Vector of floats via Mat = [3.1415927; 2; 3.01]

A vector of 2D Points = [0, 0; 5, 1; 10, 2; 15, 3; 20, 4; 25, 5; 30, 6; 35, 0; 40, 1; 45, 2; 50, 3; 55, 4; 60, 5; 65, 6; 70, 0; 75, 1; 80, 2; 85, 3; 90, 4; 95, 5]


0 0
原创粉丝点击