zoukankan      html  css  js  c++  java
  • [OpenCV]Mat类详解

    http://blog.csdn.net/yang_xian521/article/details/7107786

    Preface

    Mat:Matrix

    Mat类可以被看做是opencv中C++版本的矩阵类,通俗的说就是操作矩阵(例如:求逆/转置/加减乘除等等,), 而图片的存储就是矩阵,所以经常用他来处理图片

    Mat最大的优势跟STL很相似,有很多类似于STL的操作。但是Mat远远强于后者;二者都是对内存进行动态的管理,不需要之前用户手动的管理内存

    Mat类的存储和数据类型

    Mat的存储是逐行的存储

    • 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 )

    创建Mat类的对象

    Mat这个类有两部分数据。

      一个是矩阵头(matrix header)这部分大小固定,包含矩阵的大小,存储的方式,矩阵存储的地址等等。

      另一个部分是一个指针: 指向矩阵所包含的像素数据

    // make a 7x7 complex matrix filled with 1+3j.
    Mat M(7,7,CV_32FC2,Scalar(1,3));
    // and now turn M to a 100x60 15-channel 8-bit matrix.
    // The old content will be deallocated
    M.create(100,60,CV_8UC(15));

    创建一个M矩阵,7行7列,类型为CV_32F,C2表示有2个通道。Scalar(1,3)是对矩阵进行初始化赋值。第一个通道全为1,第2个通道全为3。具体见一下:

    scalar是将图像设置成单一灰度和颜色,怪不得叫scalar(标量/纯量)。

    Mat rawImg(600, 500, CV_8UC3, Scalar(255, 0, 0));  

     运行结果:


    Mat类的矩阵操作

    Row 行 Column列操作

    // add the 5-th row, multiplied by 3 to the 3rd row
    M.row(3) = M.row(3) + M.row(5)*3;
    // now copy the 7-th column to the 1-st column
    // M.col(1) = M.col(7); // this will not work
    Mat M1 = M.col(1);
    M.col(7).copyTo(M1);

    注意对列操作时要新建一个Mat,我想应该跟列地址不连续有关

    接收指针指向的数据流

    对于外来的数据,比如你从别的地方接受了一幅图片,但可以不是Mat结构的,而只有一个数据的指针,看看接下来的代码是如何应付的,

    void process_video_frame(const unsigned char* pixels,int width, int height, int step)
    
    {
    
        Mat img(height, width, CV_8UC3, pixels, step);
    
        GaussianBlur(img, img, Size(7,7), 1.5, 1.5);
    
    }

    快速初始化数据

    double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
    Mat M = Mat(3, 3, CV_64F, m).inv();

    也可以把原来的IplImage格式的图片直接用Mat(IplImage)的方式转成Mat结构,

    也可以像Matlab一样调用zeros()、ones()、eye()这样的函数进行初始化。

    内存释放

    如果你需要提前释放数据的指针和内存,可以调用release()。

    数据的获取

    调用at<float>(3, 3)这样的格式为最佳


    需要注意的问题:

    1 很多OpenCV的函数支持的数据深度只有8位和32位的,所以要少使用CV_64F,但是vs的编译器又会把float数据自动变成double型,有些不太爽。

    2 流操作符<<对于Mat的操作,仅限于Mat是2维的情况。

    Mat A, C; // creates just the header parts
    A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we’ll know the method used (allocate matrix)
    Mat B(A); // Use the copy constructor
    C = A; // Assignment operator

    需要注意的是,copy这样的操作只是copy了矩阵的matrix header和那个指针,而不是矩阵的本身,也就意味着两个矩阵的数据指针指向的是同一个地址,需要开发者格外注意。

    比如上面这段程序,A、B、C指向的是同一块数据,他们的header不同,但对于A的操作同样也影响着B、C的结果。

    刚刚提到了内存自动释放的问题,那么当我不再使用A的时候就把内存释放了,那时候再操作B和C岂不是很危险?

    不用担心,OpenCV的大神为我们已经考虑了这个问题,是在最后一个Mat不再使用的时候才会释放内存,咱们就放心用就行了。

    如果想建立互不影响的Mat,是真正的复制操作,需要使用函数clone()或者copyTo()。


  • 相关阅读:
    UVA 10618 Tango Tango Insurrection
    UVA 10118 Free Candies
    HDU 1024 Max Sum Plus Plus
    POJ 1984 Navigation Nightmare
    CODEVS 3546 矩阵链乘法
    UVA 1625 Color Length
    UVA 1347 Tour
    UVA 437 The Tower of Babylon
    UVA 1622 Robot
    UVA127-"Accordian" Patience(模拟)
  • 原文地址:https://www.cnblogs.com/-Mr-y/p/7986056.html
Copyright © 2011-2022 走看看