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;

OpenCV 中Iplimage结构详解相关推荐

  1. Linux内核中sk_buff结构详解

    目录 1.sk_buff结构体 1.1 sk_buff在内核中的结构 1.2 重要的长度len的解析 2. sk_buff数据区 2.1 线性数据区 2.2 非线性数据区 -------------- ...

  2. OpenCV中的RANSAC详解

    转载来自:http://blog.csdn.net/laobai1015/article/details/51683076 本文将OpenCV中的RANSAC代码全部挑选出来,进行分析和讲解,以便大家 ...

  3. c语言构造mat型数据类型,视觉SLAM——OpenCV之Mat结构详解 数据成员和构造函数 创建Mat方法 遍历Mat方法...

    前言 OpenCV1时代采用基于C语言接口构建函数库,使用名为IplImage的结构体在内存中存储图像,其问题在于需要用户手动管理内存,如果不手动释放内存会造成内存泄漏. OpenCV2引入面向对象编 ...

  4. OpenCV 中cv2.threshold详解,(大白话版)

    cv2.threshold (src, thresh, maxval, type) cv2.threshold (源图片, 阈值, 填充色, 阈值类型) 函数含义请看这篇博客:https://blog ...

  5. OpenCV中的waitkey()详解

    函数原型: int waitkey(int delay = 0) 其中delay表示延迟时间. 1) 当delay <= 0时,表示如果没有键盘时间,一直处于等待状态.这一般用于程序暂停. 2) ...

  6. Android 8.0学习(32)---Android 8.0源码目录结构详解

    Android 8.0源码目录结构详解 android的移植按如下流程:     (1)android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来.     (2)正确挂载文件系统 ...

  7. ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route

    前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...

  8. Linux中iptraf命令详解(IP局域网监控工具)

    2019独角兽企业重金招聘Python工程师标准>>> Linux中iptraf命令详解(IP局域网监控工具) 发布时间:2017-12-27 20:46:03   作者:佚名    ...

  9. Windows GPT磁盘GUID结构详解

    前一篇 Windows磁盘MBR结构详解 中我们介绍了Basic Disk中的Master Boot Record结构.GPT Disk作为Windows 2003以后引入的分区结构.使用了GUID分 ...

最新文章

  1. Android 反射 换一种方式编程
  2. boost::phoenix::if_else相关的测试程序
  3. 【个人申明】主要发表平台迁至简书和公众号
  4. jquery监听滚动条
  5. 你为什么会沉默,你们为什么又在后退呢?
  6. 单选按钮必填会有红色选中提示吗_为什么单选按钮和复选框不能共存?
  7. offsetParent
  8. 阶段3 2.Spring_03.Spring的 IOC 和 DI_13 课程知识梳理
  9. js获取服务器控件DropDownList所选中的各项属性
  10. Vb与数据库学习总结博客
  11. 测试专业名词总结UT,IT,ST,UAT
  12. 计算机专业研究生读研规划,关于一个计算机研究生人生规划的迷惑
  13. 基于深度强化学习的完全AI自动的俄罗斯方块游戏
  14. 学习神经网络(深度学习)电脑的配置要求
  15. 一日一次 算法 (一) 插入排序
  16. 虚拟opc服务器软件,OPC Server
  17. Alibaba Cloud Linux 3安装MySql8.0过程及配置
  18. sturts2框架知识点(Struts2框架----今天脑子有点炸)
  19. 手机安装ubuntu
  20. 【9122】谈装修:项目与项目群

热门文章

  1. HR面试题(史上最全、持续更新、吐血推荐)
  2. IBM 3650 M3阵列在bios中的WebBios的设置
  3. 【游戏设计】从星露谷物语中学习游戏制作
  4. 韩立刚网络视频—学习记录
  5. 在linux上配置Maven环境变量
  6. java发送微信小程序模版通知
  7. 业务数据相同,用友U8与金蝶K3计算的实际成本相同吗
  8. Kotin学习手记——类、接口、扩展方法、空类型
  9. 微信小程序倒计时,小程序60秒倒计时,小程序倒计时防止重复点击
  10. 信捷PLC与7台三菱变频器485通讯案例