CV::MAT总结

来源:互联网 发布:中国工具书网络出版 编辑:程序博客网 时间:2024/06/07 05:32

CV::MAT

1 基础知识

MAT是opencv2.X里面新出现配合C++的n-dimensional dense array class。强烈推荐大家使用
我们先看一下结构:

class CV_EXPORTS Mat{public:    // ... a lot of methods ...    ...    /*! includes several bit-fields:         - the magic signature         - continuity flag         - depth               //深度         - number of channels //通道数 彩图rgb 3通道     */    int flags;    //! the array dimensionality, >= 2    int dims; //维度    //! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions    int rows, cols; //行,列    //! pointer to the data    uchar* data;  //数据指针    //! pointer to the reference counter;    // when array points to user-allocated data, the pointer is NULL    int* refcount; //引用次数    // other members    ...};

数据类型属性:
type格式:
表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:

CV_8UC1 CV_8UC2 CV_8UC3 CV_8UC4 CV_8SC1 CV_8SC2 CV_8SC3 CV_8SC4 CV_16UC1 CV_16UC2 CV_16UC3 CV_16UC4 CV_16SC1 CV_16SC2 CV_16SC3 CV_16SC4 CV_32SC1 CV_32SC2 CV_32SC3 CV_32SC4 CV_32FC1 CV_32FC2 CV_32FC3 CV_32FC4 CV_64FC1 CV_64FC2 CV_64FC3 CV_64FC4

其中没有通道信息便是depth:
CV_8U - 8-bit unsigned integers ( 0..255 )
CV_8S - 8-bit signed integers ( -128..127 )
CV_16U - 16-bit unsigned integers ( 0..65535 )
CV_16S - 16-bit signed integers ( -32768..32767 )
CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数,F(float)是浮点数。
step:内存地址

如需更详细信息请进
Mat这个类有两部分数据。一个是matrix header,这部分的大小是固定的,包含矩阵的大小,存储的方式,矩阵存储的地址等等。另一个部分是一个指向矩阵包含像素值的指针。对于Mat数据结构,在对图像进行处理时要
使用OpenCV的C++接口时不需要考虑内存释放问题。赋值运算符和拷贝构造函数( ctor )只拷贝信息头,这样构造出来的Mat共用一个矩阵空间,修改任意Mat的值将互相影响。使用函数 clone() 或者copyTo() 可以复制整个图像的矩阵数据。

创建MAT
构造函数用的比较多的:
C++: Mat::Mat(int rows, int cols, int type, const Scalar& s)
C++: Mat::Mat(const IplImage* img, bool copyData=false)

int main()  {  /*******************************Mat基本操作-创建矩阵*****************************************/      //二维三通道矩阵建立      Mat M(3,3, CV_8UC3, Scalar(0,0,255)); //使用构造函数创建矩阵  /* CV_8UC3 表示使用8位的 unsigned char 型,每个像素由三个元素组成三通道,初始化为(0,0,255) */      cout << "M = " << endl << " " << M << endl << endl; //格式化输出      //三维      int sz[3] = {3,3,3};       Mat L(3,sz, CV_8UC(1), Scalar::all(0));  /* 超过两维的矩阵:指定维数,然后传递一个指向一个数组的指针,这个数组包含每个维度的尺寸;其余的相同 */  /*****************************************Mat基本操作-图像*******************************/     Mat A, C;      // 只创建信息头部分      A=imread("D:\\openCV\\openCVProject\\openCv1\\test.jpg", CV_LOAD_IMAGE_COLOR); // 这里为矩阵开辟内存      Mat B(A);                // 使用拷贝构造函数      C = A;                  // 赋值运算符      /*     拷贝构造函数和赋值函数 只拷贝信息头和矩阵指针     */      Mat D (A, Rect(10, 10, 100, 100) ); //选取A中一个矩形区域,即只访问其矩形区域的信息头,只是创建信息头      Mat E = A(cv::Range::all(), Range(1,3)); // 创建访问边界的信息头。      /*     要创建一个感兴趣区域( ROI ),你只需要创建包含边界信息的信息头     */      Mat F = A.clone();//复制图像,包括数据      Mat G;      A.copyTo(G);      /*     拷贝矩阵本身(不只是信息头和矩阵指针),     */      //测试      namedWindow( "a", CV_WINDOW_AUTOSIZE );      namedWindow( "c", CV_WINDOW_AUTOSIZE );      imshow( "a", D);      imshow( "c", E );      /******************************图像的读取、处理和保存*********************************/        Mat image;       image = imread( "D:\\openCV\\openCVProject\\openCv笔记\\openCv笔记\\test.jpg", CV_LOAD_IMAGE_COLOR);//导入图像       if( !image.data )       {          cout<< " No image data \n " ;          return -1;       }       Mat gray_image;       cvtColor( image, gray_image, CV_BGR2GRAY );//转化为灰度图       imwrite( "../../images/Gray_Image.jpg", gray_image );//写入图像       namedWindow( "source", CV_WINDOW_AUTOSIZE );       namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );       imshow( "source", image );       imshow( "Gray image", gray_image );       /*******************************************************************************************/       waitKey(0);       return 0;  }    

2 用法简介

(1)遍历元素方法

遍历元素的方法很多,但是时间和速度上还是有很大的差别,迭代器是最安全的,指针是速度最快的方式。

#include<cv.h>  #include<highgui.h>  #include<time.h>  #include<iostream>  using namespace cv;  using namespace std;  int main()  {      //Mat img(10,10,CV_8UC3,Scalar(0,0,255));      Mat img,img_gray,img_gray2;      img=imread("D:\\openCV\\openCVProject\\openCv1\\test.jpg", CV_LOAD_IMAGE_COLOR);      cvtColor( img, img_gray, CV_BGR2GRAY );//转化为灰度图      img_gray.copyTo(img_gray2);      //**方式一  .ptr and []或指针 ***推荐方式***速度最快,行列清晰利,不分通道    nr=img_gray.rows;    nc=img_gray.cols*img_gray.channels();    for( int i=0;i<nr;i++)      {          uchar* data = img_gray.ptr<uchar>(i);          for(int j=0;j<nc;j++)          {              data[j] = 255;             //或*data++=255;          }      }      //img.create(10,10,CV_8UC3,Scalar(0,0,255));      //cout << "img = " << endl << " " << img_gray << endl << endl; //格式化输出      //**方式二 W*H的一幅图像看成是一个1*(w*h)的一个一维数组  ***速度较快***不分行列通道    int nc;      if(img_gray.isContinuous())//判断是否被所有的像素填满      {          nc = img_gray.rows*img_gray.cols*img_gray.channels();//行 列 通道的乘积         }      else      {          cout<<"像素未填满,不可用第二种方式"<<endl;          return -1;      }      uchar* data_2 = img_gray.ptr<uchar>(0);//提取第一个像素点指针      for(int i=0;i<nc;i++)//遍历所有的元素      {          data_2[i] = 255;      }      //方式三指针扫描  ***.at<uchar>(0,0)速度较慢***分通道赋值    uchar* data_3 = img.data;//单个元素      img.at<uchar>(0,0)=0;      for(int i=0;i<img.rows;i++)//遍历所有的元素      {          for(int j=0;j<img.cols;j++)          {               data_3 = img.data + i*img.step + j * img.elemSize();                //对各个通道赋值               data_3[0]=100;               data_3[1]=100;               data_3[2]=100;          }      }      /*时间函数     double start = getTickCount();     finish = clock();      duration = (double)(finish - start) / CLOCKS_PER_SEC;      */      //方式四 迭代器iterator扫描图像      Mat_<Vec3b>::iterator it = img.begin<Vec3b>();        Mat_<Vec3b>::iterator itend = img.end<Vec3b>();        for (; it!=itend; it++)        {                 //对各个通道赋值               (*it)[0] = 200;                 (*it)[1] = 200;                (*it)[2] = 200;       }        //测试,根据自己的选择查看结果      namedWindow("sorce",WINDOW_AUTOSIZE);      namedWindow("result",WINDOW_AUTOSIZE);      cv::imshow("sorce",img);      cv::imshow("result",img_gray);      waitKey(0);      return 0;  }  
'using at'不推荐,速度慢,定位一个元素时可以使用Mat H(100, 100, CV_64F);for(int i = 0; i < H.rows; i++)    for(int j = 0; j < H.cols; j++)        H.at<double>(i,j)=1./(i+j+1);'using ptr' 行指针for(int i = 0; i < H.rows; i++)uchar* data = img_gray.ptr<uchar>(i);      for(int j = 0; j < H.cols; j++)

(2)

3 注意事项

1。赋值问题,copyto两矩阵参数必须相同,否则将建立一个新的拷贝独立于共用矩阵。
2。

0 0
原创粉丝点击