1. 程式人生 > >影象在Mat,CvMat之間轉換

影象在Mat,CvMat之間轉換

1、CvMat之間的複製

//注意:深拷貝 - 單獨分配空間,兩者相互獨立

CvMat* a;  
CvMat* b = cvCloneMat(a);   //copy a to b  

2、Mat之間的複製

//注意:淺拷貝 - 不復制資料只建立矩陣頭,資料共享(更改a,b,c的任意一個都會對另外2個產生同樣的作用)

Mat a;
Mat b = a; //a "copy" to b
Mat c(a); //a "copy" to c

//注意:深拷貝
Mat a;
Mat b = a.clone(); //a copy to b
Mat c;
a.copyTo( c); //a copy to c


3、CvMat轉Mat

//使用Mat的建構函式:Mat::Mat(const CvMat* m, bool copyData=false);
預設情況下copyData為false

CvMat* a;
//注意:以下三種效果一致,均為淺拷貝
Mat b(a);    //a "copy" to b
Mat b(a, false);    //a "copy" to b
Mat b = a;    //a "copy" to b

//注意:當將引數copyData設為true後,則為深拷貝(複製整個影象資料)
Mat b = Mat(a, true); //a copy to b

4、Mat轉CvMat


//注意:淺拷貝
Mat a;
CvMat b = a; //a "copy" to b

//注意:深拷貝
Mat a;
CvMat *b;
CvMat temp = a; //轉化為CvMat型別,而不是複製資料
cvCopy(&temp, b); //真正複製資料 cvCopy使用前要先開闢記憶體空間


IplImage與上述二者間的轉化和拷貝=

1、IplImage之間的複製

這個不贅述了,就是cvCopy與cvCloneImage使用區別,貼張網上的圖:
在這裡插入圖片描述

2、IplImage轉Mat

//使用Mat的建構函式:Mat::Mat(const IplImage* img, bool copyData=false);
預設情況下copyData為false
IplImage* srcImg = cvLoadImage(“Lena.jpg”);
//注意:以下三種效果一致,均為淺拷貝
Mat M(srcImg);
Mat M(srcImg, false);
Mat M = srcImg;

//注意:當將引數copyData設為true後,則為深拷貝(複製整個影象資料)
Mat M(srcImg, true);
複製程式碼

3、Mat轉IplImage

//注意:淺拷貝 - 同樣只是建立影象頭,而沒有複製資料
Mat M;
IplImage img = M;
IplImage img = IplImage(M);
//深拷貝
cv::Mat img2;
IplImage imgTmp = img2;
IplImage *input = cvCloneImage(&imgTmp);

4、IplImage轉CvMat

//法一:cvGetMat函式
IplImage* img;
CvMat temp;
CvMat* mat = cvGetMat(img, &temp); //深拷貝
//法二:cvConvert函式
CvMat *mat = cvCreateMat(img->height, img->width, CV_64FC3); //注意height和width的順序
cvConvert(img, mat); //深拷貝

5、CvMat轉IplImage

//法一:cvGetImage函式
CvMat M;
IplImage* img = cvCreateImageHeader(M.size(), M.depth(), M.channels());
cvGetImage(&M, img); //深拷貝:函式返回img
//也可寫成
CvMat M;
IplImage* img = cvGetImage(&M, cvCreateImageHeader(M.size(), M.depth(), M.channels()));
//法二:cvConvert函式
CvMat M;
IplImage* img = cvCreateImage(M.size(), M.depth(), M.channels());
cvConvert(&M, img); //深拷貝

6.cv::Mat--->const cvArr*

cvArr * 陣列的指標。就是opencv裡面的一種型別。
Mat img;
const CvArr* s=(CvArr*)&img;

上面就可以了,CvArr是Mat的虛基類,所有直接強制轉換就可以了

void cvResize( src 就是之前的lplimage型別的一個指標變數

7.cvArr(IplImage或者cvMat)轉化為cvMat

方式一、cvGetMat方式:

int coi = 0;
cvMat mat = (CvMat)arr;
if( !CV_IS_MAT(mat) )
{
mat = cvGetMat( mat, &matstub, &coi );
if (coi != 0) reutn; // CV_ERROR_FROM_CODE(CV_BadCOI);
}

寫成函式為:
// This is just an example of function
// to support both IplImage and cvMat as an input
CVAPI( void ) cvIamArr( const CvArr* arr )
{
CV_FUNCNAME( “cvIamArr” );
BEGIN;
CV_ASSERT( mat == NULL );
CvMat matstub, mat = (CvMat)arr;
int coi = 0;
if( !CV_IS_MAT(mat) )
{
CV_CALL( mat = cvGetMat( mat, &matstub, &coi ) );
if (coi != 0) CV_ERROR_FROM_CODE(CV_BadCOI);
}
// Process as cvMat
END;
}

8影象直接操作

方式一:直接陣列操作 int col, row, z;

複製程式碼
uchar b, g, r;
for( row = 0; row < img->height; y++ )
{
for ( col = 0; col < img->width; col++ )
{
b = img->imageData[img->widthStep * row + col * 3]
g = img->imageData[img->widthStep * row + col * 3 + 1];
r = img->imageData[img->widthStep * row + col * 3 + 2];
}
}

方式二:巨集操作:

int row, col;
uchar b, g, r;
for( row = 0; row < img->height; row++ )
{
for ( col = 0; col < img->width; col++ )
{
b = CV_IMAGE_ELEM( img, uchar, row, col * 3 );
g = CV_IMAGE_ELEM( img, uchar, row, col * 3 + 1 );
r = CV_IMAGE_ELEM( img, uchar, row, col * 3 + 2 );
}
}

注:CV_IMAGE_ELEM( img, uchar, row, col * img->nChannels + ch )

9.cvMat的直接操作

陣列的直接操作比較鬱悶,這是由於其決定於陣列的資料型別。

對於CV_32FC1 (1 channel float):

CvMat* M = cvCreateMat( 4, 4, CV_32FC1 );
M->data.fl[ row * M->cols + col ] = (float)3.0;

對於CV_64FC1 (1 channel double):

CvMat* M = cvCreateMat( 4, 4, CV_64FC1 );
M->data.db[ row * M->cols + col ] = 3.0;

一般的,對於1通道的陣列:

CvMat* M = cvCreateMat( 4, 4, CV_64FC1 );
CV_MAT_ELEM( *M, double, row, col ) = 3.0;

OpenCV之CvMat、Mat、IplImage之間相互轉換例項(轉) - 重慶Debug - 部落格園

CvMat,Mat和IplImage之間的轉化和拷貝 - Key_Ky - 部落格園