最近了解了下如何存取图像元素,在这里归纳总结下,也是记录下,以后需要的时候可以复习下。
假设需要读取在i行j列像点的第k通道. 其中, 行数i的范围为[0, height-1], 列数j的范围为[0, width-1], 通道k的范围为[0, nchannels-1].
1.间接存取: (比较通用, 但效率低, 可读取任一类型图像数据)
对单通道字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); CvScalar s; s=cvGet2D(img,i,j); // get the (i,j) pixel value printf("intensity=%f\n",s.val[0]); s.val[0]=111; cvSet2D(img,i,j,s); // set the (i,j) pixel value
对多通道浮点或字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); CvScalar s; s=cvGet2D(img,i,j); // get the (i,j) pixel value printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]); s.val[0]=111; s.val[1]=111; s.val[2]=111; cvSet2D(img,i,j,s); // set the (i,j) pixel value
2.直接存取: (效率高, 但容易出错)
对单通道字节图像:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); ((uchar *)(img->imageData + i*img->widthStep))[j]=111;
对多通道字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3); ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +0]=111; // B ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +1]=112; // G ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +2]=113; // R
对多通道浮点图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels +0]=111; // B ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels +1]=112; // G ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels +2]=113; // R
3.用指针直接存取 : (在某些情况下简单高效)
对单通道字节图像:
IplImage* img =cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); int height = img->height; int width = img->width; int step = img->widthStep/sizeof(uchar); uchar* data =(uchar *)img->imageData; data[i*step+j] = 111;
对多通道字节图像:
IplImage* img =cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3); int height = img->height; int width = img->width; int step = img->widthStep/sizeof(uchar); int channels =img->nChannels; uchar* data =(uchar *)img->imageData; data[i*step+j*channels+k] = 111;
对单通道浮点图像(假设用4字节调整):
IplImage* img =cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); int height = img->height; int width = img->width; int step = img->widthStep/sizeof(float); int channels =img->nChannels; float * data =(float *)img->imageData; data[i*step+j*channels+k] = 111;
4.使用 c++ wrapper 进行直接存取: (简单高效)
对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:
template<class T> classImage { private: IplImage* imgp; public: Image(IplImage* img=0){imgp=img;} ~Image(){imgp=0;} void operator=(IplImage*img) {imgp=img;} inline T*operator[](const int rowIndx) { return ((T*)(imgp->imageData + rowIndx*imgp->widthStep));} }; typedef struct{ unsigned char b,g,r; } RgbPixel; typedef struct{ float b,g,r; } RgbPixelFloat; typedef Image<RgbPixel> RgbImage; typedef Image<RgbPixelFloat> RgbImageFloat; typedef Image<unsigned char> BwImage; typedefImage<float> BwImageFloat;
单通道字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); BwImage imgA(img); imgA[i][j] = 111;
多通道字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3); RgbImage imgA(img); imgA[i][j].b = 111; imgA[i][j].g = 111; imgA[i][j].r = 111;
多通道浮点图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); RgbImageFloat imgA(img); imgA[i][j].b = 111; imgA[i][j].g = 111; imgA[i][j].r = 111;