OpenCV中IplImage, CvMat, Mat 基本使用和元素遍历

来源:互联网 发布:阿里云可以挣钱吗 编辑:程序博客网 时间:2024/05/18 02:44

opencv中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage,这三种类型都可以代表和显示图像。在OpenCV的文档中说明Mat类型通过C++面向对象的方法实现的,可以进行Matlab风格的矩阵操作,IplImage类型和CvMat类型用C语言实现的,两者之间存在着类似于面向对象中的继承关系。

一、IplImage

1.1 先上OpenCV中的图像信息头,该结构体的定义如下:

typedef struct _IplImage{    int  nSize;             /* sizeof(IplImage) */    int  ID;                /* version (=0)*/    int  nChannels;         /* Most of OpenCV functions support 1,2,3 or 4 channels */    int  alphaChannel;      /* Ignored by OpenCV */    int  depth;             /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,                               IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported.  */    char colorModel[4];     /* Ignored by OpenCV */    char channelSeq[4];     /* ditto */    int  dataOrder;         /* 0 - interleaved color channels, 1 - separate color channels.                               cvCreateImage can only create interleaved images */    int  origin;            /* 0 - top-left origin,                               1 - bottom-left origin (Windows bitmaps style).  */    int  align;             /* Alignment of image rows (4 or 8).                               OpenCV ignores it and uses widthStep instead.    */    int  width;             /* Image width in pixels.                           */    int  height;            /* Image height in pixels.                          */    struct _IplROI *roi;    /* Image ROI. If NULL, the whole image is selected. */    struct _IplImage *maskROI;      /* Must be NULL. */    void  *imageId;                 /* "           " */    struct _IplTileInfo *tileInfo;  /* "           " */    int  imageSize;         /* Image data size in bytes                               (==image->height*image->widthStep                               in case of interleaved data)*/    char *imageData;        /* Pointer to aligned image data.         */    int  widthStep;         /* Size of aligned image row in bytes.    */    int  BorderMode[4];     /* Ignored by OpenCV.                     */    int  BorderConst[4];    /* Ditto.                                 */    char *imageDataOrigin;  /* Pointer to very origin of image data                               (not necessarily aligned) -                               needed for correct deallocation */}IplImage;
(1)dataOrder这个可以取两个不同的值(0/1),其中交叉存取颜色通道:指颜色数据排列会是BGRBGR....
分开颜色通道:几个颜色通道就分几个颜色平面存储。
(2)roi代表感兴趣区域,是IplROI结构体,包含了xOffset,yOffset,height,width,coi成员变量,分别代表感情兴趣区域的x坐标,y坐标,高,宽。

1.2 访问IplImage中的数据元素
   在访问时,分为间接访问和直接访问,同时当存储的数据元素为浮点型时,将(uchar*)改变为(float*)

    /*间接存取*/      IplImage* img=cvLoadImage("lena.jpg", 1);      CvScalar s;       /*sizeof(s) == img->nChannels*/      s=cvGet2D(img,i,j);  /*get the (i,j) pixel value*/      cvSet2D(img,i,j,s);   /*set the (i,j) pixel value*/            /*宏操作*/      IplImage* img; //malloc memory by cvLoadImage or cvCreateImage      for(int row = 0; row < img->height; row++)      {          for (int col = 0; col < img->width; col++)          {              b = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 0);               g = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 1);               r = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 2);          }      }            /*直接存取*/      IplImage* img; //malloc memory by cvLoadImage or cvCreateImage      uchar b, g, r; // 3 channels      for(int row = 0; row < img->height; row++)      {          for (int col = 0; col < img->width; col++)          {              b = ((uchar *)(img->imageData + row * img->widthStep))[col * img->nChannels + 0];               g = ((uchar *)(img->imageData + row * img->widthStep))[col * img->nChannels + 1];               r = ((uchar *)(img->imageData + row * img->widthStep))[col * img->nChannels + 2];          }      }  

二、CvMat

2.1 先上OpenCV中的图像信息头,该结构体的定义如下:

typedef struct CvMat{    int type;    int step;    /* for internal use only */    int* refcount;    int hdr_refcount;    union    {        uchar* ptr;        short* s;        int* i;        float* fl;        double* db;    } data;#ifdef __cplusplus    union    {        int rows;        int height;    };    union    {        int cols;        int width;    };#else    int rows;    int cols;#endif}CvMat;
2.2 访问CvMat中的数据元素

    /*间接访问*/      /*访问CV_32F1和CV_64FC1*/      cvmSet( CvMat* mat, int row, int col, double value);      cvmGet( const CvMat* mat, int row, int col );            /*访问多通道或者其他数据类型: scalar的大小为图像的通道值*/      CvScalar cvGet2D(const CvArr * arr, int idx0, int idx1); //CvArr只作为函数的形参void cvSet2D(CvArr* arr, int idx0, int idx1, CvScalar value);                  /*直接访问: 取决于数组的数据类型*/      /*CV_32FC1*/      CvMat * cvmat = cvCreateMat(4, 4, CV_32FC1);      cvmat->data.fl[row * cvmat->cols + col] = (float)3.0;            /*CV_64FC1*/      CvMat * cvmat = cvCreateMat(4, 4, CV_64FC1);      cvmat->data.db[row * cvmat->cols + col] = 3.0;            /*一般对于单通道*/      CvMat * cvmat = cvCreateMat(4, 4, CV_64FC1);      CV_MAT_ELEM(*cvmat, double, row, col) = 3.0; /*double是根据数组的数据类型传入,这个宏不能处理多通道*/            /*一般对于多通道*/      if (CV_MAT_DEPTH(cvmat->type) == CV_32F)          CV_MAT_ELEM_CN(*cvmat, float, row, col * CV_MAT_CN(cvmat->type) + ch) = (float)3.0; // ch为通道值      if (CV_MAT_DEPTH(cvmat->type) == CV_64F)          CV_MAT_ELEM_CN(*cvmat, double, row, col * CV_MAT_CN(cvmat->type) + ch) = 3.0; // ch为通道值                  /*多通道数组*/      /*3通道*/      for (int row = 0; row < cvmat->rows; row++)      {              p = cvmat ->data.fl + row * (cvmat->step / 4);          for (int col = 0; col < cvmat->cols; col++)             {                      *p = (float) row + col;                      *(p+1) = (float)row + col + 1;                      *(p+2) = (float)row + col + 2;                      p += 3;              }      }      /*2通道*/      CvMat * vector = cvCreateMat(1,3, CV_32SC2);CV_MAT_ELEM(*vector, CvPoint, 0, 0) = cvPoint(100,100);      /*4通道*/      CvMat * vector = cvCreateMat(1,3, CV_64FC4);CV_MAT_ELEM(*vector, CvScalar, 0, 0) = CvScalar(0, 0, 0, 0);  

三、Mat

Mat是opencv2.0推出的处理图像的新的数据结构,现在越来越有趋势取代之前的cvMat和lplImage,相比之下Mat最大的好处就是能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放。opencv2.3中提到Mat是一个多维的密集数据数组,可以用来处理向量和矩阵、图像、直方图等等常见的多维数据。
3.1 先上OpenCV中的图像信息头,该类的定义如下:

class CV_EXPORTS Mat{public:    //! default constructor    Mat();    //! 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);    //! constructs n-dimensional matrix    Mat(int ndims, const int* sizes, int type);    Mat(int ndims, const int* sizes, int type, const Scalar& s);    //! copy constructor    Mat(const Mat& m);    //! constructor for matrix headers pointing to user-allocated data    Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);    Mat(Size size, int type, void* data, size_t step=AUTO_STEP);    Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);    //! creates a matrix header for a part of the bigger matrix    Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());    Mat(const Mat& m, const Rect& roi);    Mat(const Mat& m, const Range* ranges);    //! converts old-style CvMat to the new matrix; the data is not copied by default    Mat(const CvMat* m, bool copyData=false);    //! converts old-style CvMatND to the new matrix; the data is not copied by default    Mat(const CvMatND* m, bool copyData=false);    //! converts old-style IplImage to the new matrix; the data is not copied by default    Mat(const IplImage* img, bool copyData=false);    //! builds matrix from std::vector with or without copying the data    template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false);    //! builds matrix from cv::Vec; the data is copied by default    template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true);    //! builds matrix from cv::Matx; the data is copied by default    template<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true);    //! builds matrix from a 2D point    template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);    //! builds matrix from a 3D point    template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);    //! builds matrix from comma initializer    template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);    //! download data from GpuMat    explicit Mat(const gpu::GpuMat& m);    //! destructor - calls release()    ~Mat();    //! assignment operators    Mat& operator = (const Mat& m);    Mat& operator = (const MatExpr& expr);    //! returns a new matrix header for the specified row    Mat row(int y) const;    //! returns a new matrix header for the specified column    Mat col(int x) const;    //! ... for the specified row span    Mat rowRange(int startrow, int endrow) const;    Mat rowRange(const Range& r) const;    //! ... for the specified column span    Mat colRange(int startcol, int endcol) const;    Mat colRange(const Range& r) const;    //! ... for the specified diagonal    // (d=0 - the main diagonal,    //  >0 - a diagonal from the lower half,    //  <0 - a diagonal from the upper half)    Mat diag(int d=0) const;    //! constructs a square diagonal matrix which main diagonal is vector "d"    static Mat diag(const Mat& d);    //! returns deep copy of the matrix, i.e. the data is copied    Mat clone() const;    //! copies the matrix content to "m".    // It calls m.create(this->size(), this->type()).    void copyTo( OutputArray m ) const;    //! copies those matrix elements to "m" that are marked with non-zero mask elements.    void copyTo( OutputArray m, InputArray mask ) const;    //! converts matrix to another datatype with optional scalng. See cvConvertScale.    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;    void assignTo( Mat& m, int type=-1 ) const;    //! sets every matrix element to s    Mat& operator = (const Scalar& s);    //! sets some of the matrix elements to s, according to the mask    Mat& setTo(InputArray value, InputArray mask=noArray());    //! creates alternative matrix header for the same data, with different    // number of channels and/or different number of rows. see cvReshape.    Mat reshape(int cn, int rows=0) const;    Mat reshape(int cn, int newndims, const int* newsz) const;    //! matrix transposition by means of matrix expressions    MatExpr t() const;    //! matrix inversion by means of matrix expressions    MatExpr inv(int method=DECOMP_LU) const;    //! per-element matrix multiplication by means of matrix expressions    MatExpr mul(InputArray m, double scale=1) const;    //! computes cross-product of 2 3D vectors    Mat cross(InputArray m) const;    //! computes dot-product    double dot(InputArray m) const;    //! Matlab-style matrix initialization    static MatExpr zeros(int rows, int cols, int type);    static MatExpr zeros(Size size, int type);    static MatExpr zeros(int ndims, const int* sz, int type);    static MatExpr ones(int rows, int cols, int type);    static MatExpr ones(Size size, int type);    static MatExpr ones(int ndims, const int* sz, int type);    static MatExpr eye(int rows, int cols, int type);    static MatExpr eye(Size size, int type);    //! allocates new matrix data unless the matrix already has specified size and type.    // previous data is unreferenced if needed.    void create(int rows, int cols, int type);    void create(Size size, int type);    void create(int ndims, const int* sizes, int type);    //! increases the reference counter; use with care to avoid memleaks    void addref();    //! decreases reference counter;    // deallocates the data when reference counter reaches 0.    void release();    //! deallocates the matrix data    void deallocate();    //! internal use function; properly re-allocates _size, _step arrays    void copySize(const Mat& m);    //! reserves enough space to fit sz hyper-planes    void reserve(size_t sz);    //! resizes matrix to the specified number of hyper-planes    void resize(size_t sz);    //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements    void resize(size_t sz, const Scalar& s);    //! internal function    void push_back_(const void* elem);    //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat)    template<typename _Tp> void push_back(const _Tp& elem);    template<typename _Tp> void push_back(const Mat_<_Tp>& elem);    void push_back(const Mat& m);    //! removes several hyper-planes from bottom of the matrix    void pop_back(size_t nelems=1);    //! locates matrix header within a parent matrix. See below    void locateROI( Size& wholeSize, Point& ofs ) const;    //! moves/resizes the current matrix ROI inside the parent matrix.    Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );    //! extracts a rectangular sub-matrix    // (this is a generalized form of row, rowRange etc.)    Mat operator()( Range rowRange, Range colRange ) const;    Mat operator()( const Rect& roi ) const;    Mat operator()( const Range* ranges ) const;    //! converts header to CvMat; no data is copied    operator CvMat() const;    //! converts header to CvMatND; no data is copied    operator CvMatND() const;    //! converts header to IplImage; no data is copied    operator IplImage() const;    template<typename _Tp> operator vector<_Tp>() const;    template<typename _Tp, int n> operator Vec<_Tp, n>() const;    template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;    //! returns true iff the matrix data is continuous    // (i.e. when there are no gaps between successive rows).    // similar to CV_IS_MAT_CONT(cvmat->type)    bool isContinuous() const;    //! returns true if the matrix is a submatrix of another matrix    bool isSubmatrix() const;    //! returns element size in bytes,    // similar to CV_ELEM_SIZE(cvmat->type)    size_t elemSize() const;    //! returns the size of element channel in bytes.    size_t elemSize1() const;    //! returns element type, similar to CV_MAT_TYPE(cvmat->type)    int type() const;    //! returns element type, similar to CV_MAT_DEPTH(cvmat->type)    int depth() const;    //! returns element type, similar to CV_MAT_CN(cvmat->type)    int channels() const;    //! returns step/elemSize1()    size_t step1(int i=0) const;    //! returns true if matrix data is NULL    bool empty() const;    //! returns the total number of matrix elements    size_t total() const;    //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise    int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;    //! returns pointer to i0-th submatrix along the dimension #0    uchar* ptr(int i0=0);    const uchar* ptr(int i0=0) const;    //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1    uchar* ptr(int i0, int i1);    const uchar* ptr(int i0, int i1) const;    //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2    uchar* ptr(int i0, int i1, int i2);    const uchar* ptr(int i0, int i1, int i2) const;    //! returns pointer to the matrix element    uchar* ptr(const int* idx);    //! returns read-only pointer to the matrix element    const uchar* ptr(const int* idx) const;    template<int n> uchar* ptr(const Vec<int, n>& idx);    template<int n> const uchar* ptr(const Vec<int, n>& idx) const;    //! template version of the above method    template<typename _Tp> _Tp* ptr(int i0=0);    template<typename _Tp> const _Tp* ptr(int i0=0) const;    template<typename _Tp> _Tp* ptr(int i0, int i1);    template<typename _Tp> const _Tp* ptr(int i0, int i1) const;    template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);    template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const;    template<typename _Tp> _Tp* ptr(const int* idx);    template<typename _Tp> const _Tp* ptr(const int* idx) const;    template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);    template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;    //! the same as above, with the pointer dereferencing    template<typename _Tp> _Tp& at(int i0=0);    template<typename _Tp> const _Tp& at(int i0=0) const;    template<typename _Tp> _Tp& at(int i0, int i1);    template<typename _Tp> const _Tp& at(int i0, int i1) const;    template<typename _Tp> _Tp& at(int i0, int i1, int i2);    template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;    template<typename _Tp> _Tp& at(const int* idx);    template<typename _Tp> const _Tp& at(const int* idx) const;    template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);    template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;    //! special versions for 2D arrays (especially convenient for referencing image pixels)    template<typename _Tp> _Tp& at(Point pt);    template<typename _Tp> const _Tp& at(Point pt) const;    //! template methods for iteration over matrix elements.    // the iterators take care of skipping gaps in the end of rows (if any)    template<typename _Tp> MatIterator_<_Tp> begin();    template<typename _Tp> MatIterator_<_Tp> end();    template<typename _Tp> MatConstIterator_<_Tp> begin() const;    template<typename _Tp> MatConstIterator_<_Tp> end() const;    enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, SUBMATRIX_FLAG=CV_SUBMAT_FLAG };    /*! includes several bit-fields:         - the magic signature         - continuity flag         - depth         - number of channels     */    int flags;    //! the matrix dimensionality, >= 2    int dims;    //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions    int rows, cols;    //! pointer to the data    uchar* data;    //! pointer to the reference counter;    // when matrix points to user-allocated data, the pointer is NULL    int* refcount;    //! helper fields used in locateROI and adjustROI    uchar* datastart;    uchar* dataend;    uchar* datalimit;    //! custom allocator    MatAllocator* allocator;    struct CV_EXPORTS MSize    {        MSize(int* _p);        Size operator()() const;        const int& operator[](int i) const;        int& operator[](int i);        operator const int*() const;        bool operator == (const MSize& sz) const;        bool operator != (const MSize& sz) const;        int* p;    };    struct CV_EXPORTS MStep    {        MStep();        MStep(size_t s);        const size_t& operator[](int i) const;        size_t& operator[](int i);        operator size_t() const;        MStep& operator = (size_t s);        size_t* p;        size_t buf[2];    protected:        MStep& operator = (const MStep&);    };    MSize size;    MStep step;protected:    void initEmpty();};
3.2 访问Mat中的数据元素

    /*对某行进行访问*/      Mat M;      M.row(3) = M.row(3) + M.row(5) * 3; /*第5行扩大三倍加到第3行*/            /*对某列进行复制操作*/      Mat M1 = M.col(1);      M.col(7).copyTo(M1); /*第7列复制给第1列*/            /*对某个元素的访问*/      Mat M;      M.at<double>(i,j); /*double*/      M.at(uchar)(i,j);  /*CV_8UC1*/      Vec3i bgr1 = M.at(Vec3b)(i,j) /*CV_8UC3*/      Vec3s bgr2 = M.at(Vec3s)(i,j) /*CV_8SC3*/      Vec3w bgr3 = M.at(Vec3w)(i,j) /*CV_16UC3*/            /*遍历整个二维数组*/      double sum = 0.0f;      for(int row = 0; row < M.rows; row++)      {              const double * Mi = M.ptr<double>(row);           for (int col = 0; col < M.cols; col++)                    sum += std::max(Mi[j], 0.);      }            /*STL iterator*/      double sum=0;      MatConstIterator<double> it = M.begin<double>(), it_end = M.end<double>();      for(; it != it_end; ++it)          sum += std::max(*it, 0.);  

0 0