轉載網址:http://blog.csdn.net/abcjennifer/article/details/17640195
因爲之前查資料關於opencv幾種坑爹類型CvMat, Mat, IplImage, Cvarr的詳細講解很多,但詳細到多通道元素獲取和涉及到類型轉換的文章極少,還有更坑爹的一些誤導文章,所以本文很簡要地講一下怎樣獲取這幾種類型的元素,及其類型轉換。
1、Mat, IplImage, CvMat, CvArr的關係:
1. opencv文檔中明確聲明,CvMat已經過時了(CvMat is now obsolete, consider using Mat instead)不建議用;
2. 派生關係:CvArr -> CvMat -> IplImage
3. Mat用的一套東西是imread,imshow等,有別於CvArr及其子類的cvLoadImage(),cvShowImage()...
2. 相互轉換
所有代碼已經過測試,但是這裏我就示意一下,真正寫的時候不要忘記初始化轉化過去的變量。
2.1 Mat與IplImage相互轉換
IplImage* src;
某文章說,轉換應該是Mat m(src); 而這不會複製內容,真正能複製內容的是:
Mat -> IplImage:
- Mat m;
- IplImage* transIplimage = cvCloneImage(&(IplImage) m);
IplImage -> Mat
- IplImage* transIplImage;
- Mat m = cvarrToMat(transIplImage,true);
2.2 CvMat與IplImage相互轉換
- IplImage* transIplImage;
- CvMat* cvmat;
- cvGetMat(transIplImage,cvmat);
- cvGetImage(cvmat,transIplImage);
3. (多通道)Mat, IplImage, CvMat的元素獲取
單通道的網上很多,這裏只寫多通道:
3.1 IplImage
- //i is the index of rows
- //j is the index of cols
- //c is the index of channel
- ((uchar*)pImg->imageData+i*pImg->widthStep)[j*3+c]
- CV_IMAGE_ELEM(pImg,uchar,i,3*j+c)
- Mat m;
- int h = m.rows; int w = m.cols;
- int nc = m.channels();
- for (int i = 0;i<h;i++)
- {
- for(int j = 0;j<w;j++)
- {
- Vec3b& elem = m.at<Vec3b>(i,j);
- for (int c = 0; c<nc; c++)
- {
- uchar uc = elem[c] ;//Mat(i,j) of channel c
- }
- }
- }
CV_MAT_ELEM(cvmat,uchar,i,3*j+c)
4. 驗證獲取元素代碼(Mat轉IplImage)
此代碼只用於驗證多通道元素獲取沒有錯誤,具體用的時候最好還是用opencv直接給的吧(見第3小節)
- IplImage* cvcvt_mat2IplImage(Mat m)
- {
- int h = m.rows; int w = m.cols;
- int nc = m.channels();
- IplImage* pImg = cvCreateImage(cvSize(w,h),8,nc);
- for (int i = 0;i<h;i++)
- {
- for(int j = 0;j<w;j++)
- {
- Vec3b& elem = m.at<Vec3b>(i,j);
- for (int c = 0; c<nc; c++)
- {
- //以下兩種都可以
- //((uchar*)pImg->imageData+i*pImg->widthStep)[j*3+c] = elem[c];
- CV_IMAGE_ELEM(pImg,uchar,i,3*j+c) = elem[c];
- }
- }
- }
- return pImg;
- }