您的位置:首页 > 运维架构

opencv中Mat与IplImage,CVMat类型之间转换

2016-04-11 17:51 531 查看
看程序源码是提高编程技能最直接有效的办法,首先我们来了解一下这三个结构体。由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构。从本质上讲,他是一个CvMat对象,但它还有一些其他成员变量将矩阵解释为图像。IplImage结构来源于Intel的另外一个函数库Intel Image Processing Library (IPL),该函数库主要是针对图像处理。

1 IplImage

typedef struct _IplImage
{
int nSize; // IplImage大小
int ID; // 版本 (=0)
int nChannels; // 大多数OPENCV函数支持1,2,3 或 4 个通道
int alphaChannel; // 被OpenCV忽略
int depth; // 像素的位深度,主要有以下支持格式: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S,
IPL_DEPTH_32F 和IPL_DEPTH_64F
char colorModel[4]; // 被OpenCV忽略
char channelSeq[4]; // 同上
int dataOrder; // 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.
只有cvCreateImage可以创建交叉存取图像
int origin; //图像原点位置: 0表示顶-左结构,1表示底-左结构
int align; // 图像行排列方式 (4 or 8),在 OpenCV 被忽略,使用 widthStep 代替
int width; // 图像宽像素数
int height; // 图像高像素数
struct _IplROI *roi; // 图像感兴趣区域,当该值非空时,
只对该区域进行处理
struct _IplImage *maskROI; // 在 OpenCV中必须为NULL
void *imageId; // 同上
struct _IplTileInfo *tileInfo; //同上
int imageSize; // 图像数据大小(在交叉存取格式下ImageSize=image->height*image->widthStep),单位字节
char *imageData; // 指向排列的图像数据
int widthStep; // 排列的图像行大小,以字节为单位
int BorderMode[4]; // 边际结束模式, 在 OpenCV 被忽略
int BorderConst[4]; // 同上
char *imageDataOrigin; // 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的
} IplImage;

2 CvMat

typedef struct CvMat
{
int type;    //类型(type)
int step;    //行数据长度(step,行的长度用字节表示而不是用整形或者浮点型长度)和一个指向数据的指针构成
int* refcount;
int hdr_refcount;
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data;
union
{
int rows;
int height;    //矩阵高度(width)
};
union
{
int cols;
int width;    //矩阵宽度(width)
};
} CvMat;
Mat是OpenCV最基本的数据结构,Mat即矩阵(Matrix)的缩写,Mat数据结构主要包含2部分:Header和Pointer。Header中主要包含矩阵的大小,存储方式,存储地址等信息;Pointer中存储指向像素值的指针。我们在读取图片的时候就是将图片定义为Mat类型,其重载的构造函数一大堆。

3 Mat

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();
};  

4 Mat与IplImage,CVMat类型之间转换

opencv中对图像的处理是最基本的操作,一般的图像类型为IplImage类型,但是当我们对图像进行处理的时候,多数都是对像素矩阵进行处理,所以这三个类型之间的转换会对我们的工作带来便利Mat类型较CvMat和IplImage有更强的矩阵运算能力,支持常见的矩阵运算(参照Matlab中的各种矩阵运算),所以将IplImage类型和CvMat类型转换为Mat类型更易于数据处理。

Mat类型可用于直接存储图像信息,通过函数imread、imwrite、imshow等实现(与Matlab中的函数相似),似乎在某种程度上可以取代IplImage类型。

(1)将IplImage类型转换到Mat类型

Mat::Mat(const IplImage* img, bool copyData=false);

使用Mat的构造方法,默认情况下,新的Mat类型与原来的IplImage类型共享图像数据,转换只是创建一个Mat矩阵头。当将参数copyData设为true后,就会复制整个图像数据。

例:

IplImage*iplImg = cvLoadImage("greatwave.jpg", 1);

Mat mtx(iplImg); // IplImage* ->Mat 共享数据

// or : Mat mtx = iplImg;

(2)将Mat类型转换到IplImage类型

同样只是创建图像头,而没有复制数据。

例:

IplImage ipl_img = img; // Mat -> IplImage

(3)将CvMat类型转换为Mat类型

与IplImage的转换类似,可以选择是否复制数据。

Mat::Mat(const CvMat* m, bool copyData=false);

(4)将Mat类型转换为CvMat类型

与IplImage的转换类似,不复制数据,只创建矩阵头。

例:

// 假设Mat类型的imgMat图像数据存在

CvMat cvMat = imgMat; // Mat -> CvMat

*/

举例:

#include <iostream>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main(){

IplImage* pImg = cvLoadImage("FreeBamb.jpg");

//将IplImage类型转换到Mat类型
Mat mat1(pImg);
imshow("IplImg2Mat", mat1);

//将Mat类型转换到IplImage类型,只是创建图像头,而没有复制数据。
IplImage pImg2 = mat1;
cvShowImage("Mat2IplImg", &pImg2);

//将CvMat类型转换为Mat类型
CvMat* cvmat = cvCreateMat(2, 2, CV_64FC1);
Mat mat2(cvmat);

//将Mat转化为CvMat与IplImage的转换类似,不复制数据,只创建矩阵头。
CvMat cvmat2 = mat2;

cvWaitKey(0);
system("pause");
return 0;
}

如果在做项目版本更新时我们需要特别注意,在opencv2以后没有对CvvImage这个类的支持,我们需要手工将CvvImage类对应的CvvImage.h和CvvImage.cpp下载添加到我们项目中。下载链接如下:

CSDN:http://download.csdn.net/detail/davebobo/9488047
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: