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;
OpenCV 中Iplimage结构详解相关推荐
- Linux内核中sk_buff结构详解
目录 1.sk_buff结构体 1.1 sk_buff在内核中的结构 1.2 重要的长度len的解析 2. sk_buff数据区 2.1 线性数据区 2.2 非线性数据区 -------------- ...
- OpenCV中的RANSAC详解
转载来自:http://blog.csdn.net/laobai1015/article/details/51683076 本文将OpenCV中的RANSAC代码全部挑选出来,进行分析和讲解,以便大家 ...
- c语言构造mat型数据类型,视觉SLAM——OpenCV之Mat结构详解 数据成员和构造函数 创建Mat方法 遍历Mat方法...
前言 OpenCV1时代采用基于C语言接口构建函数库,使用名为IplImage的结构体在内存中存储图像,其问题在于需要用户手动管理内存,如果不手动释放内存会造成内存泄漏. OpenCV2引入面向对象编 ...
- OpenCV 中cv2.threshold详解,(大白话版)
cv2.threshold (src, thresh, maxval, type) cv2.threshold (源图片, 阈值, 填充色, 阈值类型) 函数含义请看这篇博客:https://blog ...
- OpenCV中的waitkey()详解
函数原型: int waitkey(int delay = 0) 其中delay表示延迟时间. 1) 当delay <= 0时,表示如果没有键盘时间,一直处于等待状态.这一般用于程序暂停. 2) ...
- Android 8.0学习(32)---Android 8.0源码目录结构详解
Android 8.0源码目录结构详解 android的移植按如下流程: (1)android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来. (2)正确挂载文件系统 ...
- ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route
前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...
- Linux中iptraf命令详解(IP局域网监控工具)
2019独角兽企业重金招聘Python工程师标准>>> Linux中iptraf命令详解(IP局域网监控工具) 发布时间:2017-12-27 20:46:03 作者:佚名 ...
- Windows GPT磁盘GUID结构详解
前一篇 Windows磁盘MBR结构详解 中我们介绍了Basic Disk中的Master Boot Record结构.GPT Disk作为Windows 2003以后引入的分区结构.使用了GUID分 ...
最新文章
- Android 反射 换一种方式编程
- boost::phoenix::if_else相关的测试程序
- 【个人申明】主要发表平台迁至简书和公众号
- jquery监听滚动条
- 你为什么会沉默,你们为什么又在后退呢?
- 单选按钮必填会有红色选中提示吗_为什么单选按钮和复选框不能共存?
- offsetParent
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_13 课程知识梳理
- js获取服务器控件DropDownList所选中的各项属性
- Vb与数据库学习总结博客
- 测试专业名词总结UT,IT,ST,UAT
- 计算机专业研究生读研规划,关于一个计算机研究生人生规划的迷惑
- 基于深度强化学习的完全AI自动的俄罗斯方块游戏
- 学习神经网络(深度学习)电脑的配置要求
- 一日一次 算法 (一) 插入排序
- 虚拟opc服务器软件,OPC Server
- Alibaba Cloud Linux 3安装MySql8.0过程及配置
- sturts2框架知识点(Struts2框架----今天脑子有点炸)
- 手机安装ubuntu
- 【9122】谈装修:项目与项目群