opencv的矩阵读写

收集了一些关于矩阵以及多通道矩阵的各种访问方法: 

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),使用指针访问元素的方法如下:

  1. <pre name="code" class="cpp"for(int i = 0; i<dst_sqe->rows; i++)  
  2.     {  
  3.         float *ptr = (float*) (dst_sqe->data.ptr + i * dst_sqe->step);  
  4.           
  5.   
  6.         for(int j = 0; j<dst_sqe->cols; j++)  
  7.         {  
  8.             re = *ptr;//访问的是dst_sqe[i][j]的第1个通道  
  9.             ++ptr;  
  10.             im = *ptr;//访问的是dst_sqe[i][j]的第2个通道  
  11.             ++ptr;  

 

  1.                        //如果有3通道需要再进行一次移位。。。  
  2.     }  
  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)

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值