1、利用cvGet2D()函数来访问
该函数系列以返回值类型划分有两种,一种返回double类型数据,另一种返回CvScalar类型数据。cvGet*D系列函数可以用来返回特定位置的数组元素(一般使用cvGet2D)
CvScalar cvGet1D( const CvArr* arr, int idx0 );
CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );
CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );
CvScalar cvGetND( const CvArr* arr, int* idx );
arr输入数组.
idx0元素下标第一个以0为基准的成员
idx1元素下标第二个以0为基准的成员
idx2元素下标第三个以0为基准的成员
idx元素下标数组
例如:
CvScalar p1,p2;
for(int i=0;i<img->height;i++)
{
for (int j=0;j<img->width;j++)
{
p2=cvGet2D(img,i,j);
//此时p2中的值就是当前像素点rgb值,注意此时的p2.val[0]为b通道,p2.val[1]为g通道,p2.val[2]为r通道
//此时可以通过以下方式更改当前像素点的rgb通道值
p1.val[0]=0; //b
p1.val[1]=0; //g
p1.val[2]=0; //r
cvSet2D(img,i,j,p1);
}
}
上述方法速度比较慢。可以通过下面的方法加快速度。
2、直接访问
IplImage成员有许多
typedef struct _IplImage { int nSize; int ID; int nChannels; int alphaChannel; int depth; char colorModel[4]; char channelSeq[4]; int dataOrder; int origin; int align; int width; int height; struct _IplROI *roi; struct _IplImage *maskROI; void *imageId; struct _IplTileInfo *tileInfo; int imageSize; char *imageData; int widthStep; int BorderMode[4]; int BorderConst[4]; char *imageDataOrigin; } IplImage;
比较重要的有两个:char *imagaData 和widthStep。imageData存放图像像素数据,widthStep类似cvmat中的step,表示字节为单位的行数据长度。
多通道(三通道)字节图像中,imageData排列如下所示:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
uchar* data=(uchar*)img->imageData;
int step=img->widthStep/sizeof(uchar); //step即为上图的widthstep
int channels=img->nChannels; //3通道
uchar *b,*g,*r;
for (int i=0;i<img->height;i++)
{
for (int j=0;j<img->width;j++)
{
*b=data[i*step+j*channels+0];
*g=data[i*step+j*channels+1];
*r=data[i*step+j*channels+2];
}
}
i*step 当i=0时,即为上图的第一行
j*channels+0 j*通道数 当j=0时为第一列的第0个通道->b
j*channels+1 当j=1时为第二列的第1个通道->g
IplImage* img; //malloc memory by cvLoadImage or cvCreateImageuchar b,g,r;
for (int row=0;row<img->height;row++)
{
for (int col=0;col<img->width;col++)
{
b=((uchar*)(img->imageData+row*img->widthStep))[col*img->nChannels+0];
g=((uchar*)(img->imageData+row*img->widthStep))[col*img->nChannels+1];
r=((uchar*)(img->imageData+row*img->widthStep))[col*img->nChannels+2];
}
}
当然,也可以调用opencv中的函数:
#define CV_IMAGE_ELEM( image, elemtype, row, col ) (((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)])
for (int i=0;i<img->height;i++)
{
for (int j=0;j<img->width;j++)
{
CV_IMAGE_ELEM(img,uchar,i,j*img->nChannels)=0; //赋值
}
}
例如:IplImage* img; //malloc memory by cvLoadImage or cvCreateImage
for(int row = 0; row < img->height; row++) {for (int col = 0; col < img->width; col++) { b = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 0); g = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 1); r = CV_IMAGE_ELEM(img, UCHAR, row, col * img->nChannels + 2); }}
初始化使用IplImage *,是一个指向结构体IplImage的指针: IplImage * cvLoadImage(const *filename,int //load images from specified image)IplImage * cvCreateImage(CvSize size, int depth, int channels)