CvMat* mat;
mat = cvCreateMat(9,10,CV_64FC3);//注意所申請矩陣元素的類型,不同的類型訪問操作方法不同,但類似可推導,以此爲例。
opencv中的多通道矩陣CvMat元素的訪問方法總結如下:
1.
mat(i,j,1): *(mat->data.db + i*(mat->step/8) + 3*j);//.db爲double數據類型,step類型爲int,代表矩陣每行的字節數,因此要處以sizeof(double) =8。
mat(i,j,2): *(mat->data.db + i*(mat->step/8) + 3*j+1);
mat(i,j,3): *(mat->data.db + i*(mat->step/8) + 3*j+2);
2.
mat(i,j,1): ((double*)(mat->data.ptr+i*mat->step))[3*j];//ptr的類型爲uchar*,step類型爲int,代表矩陣每行的字節數。另外指針可以當做數組名,因此可以這樣操作。
mat(i,j,2): ((double*)(mat->data.ptr+i*mat->step))[3*j+1];
mat(i,j,3): ((double*)(mat->data.ptr+i*mat->step))[3*j+2];
3.
mat(i,j,1): *( (double*)(mat->data.ptr+i*mat->step) + 3*j );//根據以上也可以這樣
總之就是C語言中的指針操作啦,要注意指針的類型,以及step的單位是字節就可以了。
對於兩通道矩陣dst_sqe(數據類型是float),使用指針訪問元素的方法如下:
- <pre name="code" class="cpp"> for(int i = 0; i<dst_sqe->rows; i++)
- {
- float *ptr = (float*) (dst_sqe->data.ptr + i * dst_sqe->step);
- for(int j = 0; j<dst_sqe->cols; j++)
- {
- re = *ptr;//訪問的是dst_sqe[i][j]的第1個通道
- ++ptr;
- im = *ptr;//訪問的是dst_sqe[i][j]的第2個通道
- ++ptr;
- //如果有3通道需要再進行一次移位。。。
- }
- }
從結果看,2通道的元素是相鄰放置的,即對於Mat a(3,4,CV_32FC2),每一行共有8個元素,其中每相鄰的兩個元素算作一個element。
cvSet2D, cvGet2D可以用來寫讀雙通道的矩陣,可以參加http://www.opencv.org.cn/forum/viewtopic.php?p=27382
cvGetRow可以提取整行或者某幾行的元素。
float *p = (float*)cvPtr2D(idat, i, 0);
itmp->data.ptr = (uchar *)&(cvGet2D(idat, i, 0));
itmp->data.ptr = idat->data.ptr + i*idat->step;
//float *pnew=new[2*列數];
//pptr=(float *)(mat->data.ptr+求的行*mat->setp);
//
//for(int col=0;col!=列數;col++)
//{
// pnew[2*col]=pptr[2*col];
// pnew[2*col+1]=pptr[2*col+1];
//}
一般的,對於1通道的數組:
CvMat* M = cvCreateMat( 4, 4, CV_64FC1 );
CV_MAT_ELEM( *M, double, row, col ) = 3.0;
注意double要根據數組的數據類型來傳入。
對於兩通道和四通道而言:
CvMat* vector = cvCreateMat( 1, 3, CV_32SC2 );
CV_MAT_ELEM( *vector, CvPoint, 0, 0 ) = cvPoint(100,100);
CvMat* vector = cvCreateMat( 1, 3, CV_64FC4 );
CV_MAT_ELEM( *vector, CvScalar, 0, 0 ) = cvScalar(0,0,0,0);
通用數組:
CvArr* // 僅作爲函數參數,說明函數接受多種類型的數組,例如: // IplImage*, CvMat* 或者 CvSeq*. // 只需通過分析數組頭部的前4字節便可確定數組類型
二、修改單個像素:
1.3通道時:CV_IMAGE_ELEM(image, unsigned char, i, j*3+k) = gray_val; //0<=k<3
2.單通道時:CV_IMAGE_ELEM(image, unsigned char, i, j) = gray_val;
3.通用方法:CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
s.val[0]=111; //單通道就只有這個有效
s.val[1]=111;
s.val[2]=111;
cvSet2D(img,i,j,s);//set the (i,j) pixel value
三、圖像到矩陣
方式一、cvGetMat方式:
CvMat mathdr, *mat = cvGetMat( img, &mathdr );
mathdr只是根據img生成一個矩陣頭,而其數據指向img的數據。
但只是把原來圖像img頭變成了CvMat頭,數據體部分並沒有複製,所以如果此時Release了img,則再訪問mat就會出現錯誤。
方式二、cvConvert方式:
CvMat *mat = cvCreateMat( img->height, img->width, CV_64FC3 );
cvConvert( img, mat );
// #define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 )
四、從一幅圖像中截出一小塊,把它轉成一維向量
cvSetImageROI(srcImg,blockRect);//blockRect爲CvRect類型
cvCopy(srcImg,block);//srcImg爲IplImage類型,block爲CvMat類型
cvResetImageROI(srcImg);
CvMat vecHead,*vec;
vec=cvReshape( block, &vecHead, 0, 1 );//vec是得到的一維向量
數組到矩陣
// 3 channels
CvMat mathdr, *mat;
double data[] = { 111, 112, 113, 121, 122, 123,
211, 212, 213, 221, 222, 223 };
CvMat* orig = &cvMat( 2, 2, CV_64FC3, data );
//(111,112,113) (121,122,123)
//(211,212,213) (221,222,223)