• Opencv Mat的三种常用类型简介



    本系列文章由 @YhL_Leo 出品,转载请注明出处。
    文章链接: http://blog.csdn.net/yhl_leo/article/details/47683127


    本文主要介绍Opencv常用的三种Mat类型:MatMat_Matx

    1. Mat

    1.1 创建与初始化
    int rows = 3, cols = 1;
    cv::Size size(cols, rows);
    
    /* first method */
    cv::Mat myMat( rows, cols, CV_8UC1, cv::Scalar(0) );
    cv::Mat myMat = cv::Mat( rows, cols, CV_8UC1, cv::Scalar(0) );
    
    cv::Mat myMat( size, CV_8UC1, cv::Scalar(0) );
    cv::Mat myMat( cv::Size(cols, rows), CV_8UC1, cv::Scalar(0) );
    
    /* second method */
    cv::Mat myMat2;
    myMat = cv::Mat( rows, cols, CV_8UC1 );
    // initial with other mat or data
    myMat.copyTo(myMat2);         // initial with mat
    
    cv::Point3i pts( 1, 2, 3 );   
    myMat2 = cv::Mat(pts, true);  // initial with other data

    注意:

    1. 使用Mat::Mat(int rows, int cols, int type, const Scalar& s)Mat::Mat(Size size, int type, const Scalar& s)函数进行Mat初始化的时候,一定要注意Size行列存放顺序是(col, row)或者是(width, height)

    2. Mattype种类非常多,可以创建普通的CV_8UC1, ... , CV_64FC41-4通道的矩阵,也可以创建更高通道的矩阵CV_8UC(n), ... , CV_64FC(n),其中最大可以达到CV_CN_MAX通道,Opencv 2.4.11版本中#define CV_CN_MAX 512

    3. 创建多通道Mat时,例如CV_8UC3,使用cv::Scalar(0, 0,0)myMat.setTo(cv::Scalar(0)),其中后者通用于任意通道;

    4. 使用其他Mat拷贝初始化的时候,void Mat::copyTo(OutputArray m) const函数会首先调用m.create(this->size(), this->type())所以会对输入的m进行重新创建(包括sizetype),然后进行数据拷贝。m.copyTo(m)也是允许的,没有任何问题。

    1.2 数据访问

    这里只列举出常用三种方法:

    1.指针数组的方式

    cv::Mat image = cv::imread( "E:\test.JPG", CV_LOAD_IMAGE_GRAYSCALE );
    const int rows = image.rows;
    const int cols = image.cols; 
    
    uchar* data = (uchar*)image.data;
    for ( int i=0; i<rows; i++ )
    {
        for ( int j=0; j<cols; j++ )
        {
            int index = i*cols + j;
            data[index] = 0;
            /*
                if color one: 
                data[index * 3 + 0] = 0;
                data[index * 3 + 1] = 0;
                data[index * 3 + 2] = 0;
            */ 
        }
    }
    /*
        // also can be used as follow:
        for ( int i=0; i<rows; i++ )
        {
            uchar* data = (uchar*)image.data + i*cols;
            for ( int j=0; j<cols; j++ )
            {
                *data++ = 0;
            }
        }
    }
    */
    // cv::imwrite( "E:\test2.JPG", image );

    2..ptr的方式

    /* .ptr with [] */
    for ( int i=0; i<rows; i++ )
    {
        uchar *data = image.ptr<uchar>( i );
        for ( int j=0; j<cols; j++ )
        {
            data[j] = 0;
            /*
                if color one:
                data[j*3 + 0] = 0;
                data[j*3 + 1] = 0;
                data[j*3 + 2] = 0;
            */
        }
    }
    
    /* .ptr with pointer */
    for ( int i=0; i<rows; i++ )
    {
        uchar *data = image.ptr<uchar>( i );
        for ( int j=0; j<cols*image; j++ )
        {
            *data++ = 0;
        }
    }

    3..at的方式

    for ( int i=0; i<rows; i++ )
    {
        for ( int j=0; j<cols; j++ )
        {
             image.at<uchar>(i, j)= 0; // also can be: image.at<uchar>( cv::Point(j, i) ) = 0;
             /*
                 if color one:
                 image.at<uchar>( i, j*3 + 0 ) = 0;
                 image.at<uchar>( i, j*3 + 1 ) = 0;
                 image.at<uchar>( i, j*3 + 2 ) = 0;
             */
        }
    }

    三种方法速度上有一定差异,感兴趣的可以自己测试一下~

    2. Mat_

    Mat_继承于Mat,相比于Mat没有增加任何数据段,但增加了一些更加便捷的功能,表达上也更加精简。

    2.1 创建与初始化
    /* first method */
    cv::Mat_<double> myMat_ = ( cv::Mat_<double>(3, 3) << 
        1.0, 2.0, 3.0,
        4.0, 5.0, 6.0,
        7.0, 8.0, 9.0);
    
    cv::Mat_<double> myMat_ = cv::Mat_<double>::zeros(3, 3); // others: eyes, diag, ones
    
    /* second method */
    cv::Mat_<double> myMat_(3, 1, 0.0); 
    // -> cv::Mat image(3, 1, CV_64FC1, cv::Scalar(0.0));
    
    // create a 100x100 color image and fill it with green(in RGB space)
    cv::Mat_<cv::Vec3b> image( 100, 100, cv::Vec3b(0, 255, 0) );
    
    /* third method */
    cv::Mat myMat( 100, 100, CV_64F1, cv::Scalar(0) );
    cv::Mat_<double>& myMat_ = (cv::Mat_<double>&)myMat; 

    注意:

    1. 使用( cv::Mat_<double>(row, col) << ...) )形式创建并初始化的时候,最外面的( )不能省略;

    2. 使用第二种通过Mat指针或者引用的方式创建与初始化Mat_时,两者的数据类型一定要一致,不然程序虽然编译没问题,但运行就会BUG~

    2.2 数据访问
    /* 
        Note that Mat::at<_Tp>(int y, int x) and 
        Mat_<_Tp>::operator ()(int y, int x) do 
        absolutely the same and run at the same speed
    */ 
    int rows = myMat_.rows;
    int cols = myMat_.cols;
    
    /* first method */ 
    for ( int i=0; i<rows; i++ )
    {
        for ( int j=0; j<cols; j++ )
        {
            std::cout << myMat_(i, j) << std::endl;
        }
    }
    
    // for multi-channel images/matrices:
    for ( int i = 0; i < rows; i++ )
    {
        for( int j = 0; j < cols; j++ )
        {
            // scramble the 2nd (red) channel of each pixel
            image(i, j)[2] ^= (uchar)(i ^ j); // ^: exclusive or operation
        }
    }
    
    /* second method */
    int matCount = rows * cols;
    for ( int idx=0; idx < matCount; idx++ )
    {
        std::cout << myMat_(idx) <<std::endl;
    }

    3. Matx

    Matx主要用于大小、数据类型(浮点型)已知的小矩阵(最大不超过6x6),包括:Matx12f, ... , Matx66fMatx12d, ... , Matx66d

    创建与初始化都很简单,不做过多介绍:

    cv::Matx31d myMatx( 1.0, 2.0, 3.0 );
    
    cv::Matx33d myMatx2 = cv::Matx33d( 0.0, 0.0, 0.0 );

    最后,关于Mat的运算(加,减,乘,求逆,转置,均值,标准差…)三种类型基本差异不大,在文档中也容易找到~

    参考文档:http://www.docs.opencv.org/modules/core/doc/basic_structures.html?highlight=mat

  • 相关阅读:
    增加正则项Regularization to Prevent Overfitting
    feature_column、fc.input_layer以及各种类型的column如何转化
    input_fn如何读取数据
    matplotlib.pyplot如何绘制多张子图
    机器学习之杂乱笔记
    Adobe Flash Player
    LSTM/GRU-讲得非常细致
    anaconda python36 tensorflow virtualenv
    畅通工程-HZNU寒假集训
    食物链-HZUN寒假集训
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332246.html
Copyright © 2020-2023  润新知