影象在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;