OpenCV 中Iplimage结构详解

Iplimage数据结构

主要困扰我许久的就是其中的widthStep与width*nChannels是否相等,事实上我们可以在源码opencv\modules\core\src\array.cpp中找到

其中IPL_DEPTH_SIGN是0x800000000,align大小为CV_DEFAULT_IMAGE_ROW_ALIGN,定义为4,由此可见当图像为3*5,通道为3通道时,widthStep为12;同时经过分析可以知道事实上是widht*nChannels按4整数倍内存对齐的结果。

如宽度为3、通道数为3的图像,每一行需要的实际内存长度为3*3,为了内存对齐,OpenCV会在每行末尾自动补上3个字节的内存,内存初始化都为0,所以widthStep变为了12。

widthStep大小对IplImage极为重要,在array.cpp中,我们可以找到如下代码行:

image->imageSize = image->widthStep * image->height;

img->imageData = img->imageDataOrigin =
          (char*)cvAlloc( (size_t)img->imageSize );

可见widthStep直接影响到imageData的数据长度。

下面是Iplimage数据结构

IplImage
  |-- int  nChannels;     // 色彩通道数(1,2,3,4)
  |-- int  depth;         // 象素色深:
  |                       //   IPL_DEPTH_8U, IPL_DEPTH_8S,
| // IPL_DEPTH_16U,IPL_DEPTH_16S,
  |                       //   IPL_DEPTH_32S,IPL_DEPTH_32F,
  |                       //   IPL_DEPTH_64F
  |-- int  width;         // 图像宽度(象素点数)
  |-- int  height;        // 图像高度(象素点数)

  |-- char* imageData;    // 指针指向成一列排列的图像数据
  |                       // 注意色彩顺序为BGR
  |-- int  dataOrder;     // 0 - 彩色通道交叉存取 BGRBGRBGR,
  |                       // 1 - 彩色通道分隔存取 BBBGGGRRR
  |                       // 函数cvCreateImage只能创建交叉存取的图像
  |-- int  origin;        // 0 - 起点为左上角,
  |                       // 1 - 起点为右下角(Windows位图bitmap格式)
  |-- int  widthStep;     // 每行图像数据所占字节大小
  |-- int  imageSize;     // 图像数据所占字节大小 = 高度*每行图像数据字节大小
  |-- struct _IplROI *roi;// 图像ROI. 若不为NULL则表示需要处理的图像
  |                       // 区域.
  |-- char *imageDataOrigin; // 指针指向图像数据原点
  |                          // (用来校准图像存储单元的重新分配)
  |
  |-- int  align;         // 图像行校准: 4或8字节校准
  |                       // OpenCV不采用它而使用widthStep
  |-- char colorModel[4]; // 图像色彩模型 - 被OpenCV忽略

下面看一个图像数据存取的例子

例子转自:http://blog.csdn.net/to_utopia/article/details/4856171

1.直接存取: (效率高, 但容易出错)

  • 对单通道字节图像:
    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


2.用指针直接存取 : (在某些情况下简单高效)


  • 对单通道字节图像:
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;


3.使用 c++ wrapper 进行直接存取: (简单高效)

 

  • 对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:
    template<class T> class Image
    {
      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;
    typedef Image<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;
发布了79 篇原创文章 · 获赞 61 · 访问量 24万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览