java+widthstep,i*step+j*channels+k 以及widthStep大小计算及原理
一直以为IplImage结构体中的widthStep元素大小等于width*nChannels,大错特错!
查看OpenCV2.1的源码,在src/cxcore/cxarray.cpp文件中,找到cvInitImageHeader函数,函数中对widthStep大小赋值如下:
image->widthStep = (((image->width * image->nChannels *
(image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1)); (1)
其中IPL_DEPTH_SIGN的定义可以在cxtypes.h中找到,定义为:#define IPL_DEPTH_SIGN 0x80000000, align的大小为CV_DEFAULT_IMAGE_ROW_ALIGN,其大小在cxmisc.h中定义为:#define CV_DEFAULT_IMAGE_ROW_ALIGN 4,depth取8位深度。
根据(1)式,已知IPL_DEPTH_SIGN、align、depth 的大小,分别手动计算如下图像的widthStep:
图像宽度 图像通道数 计算得到的widthStep
3 3 12
3 1 4
5 3 16
5 1 8
7 3 24
7 1 8
4 3 12
4 1 4
为了进一步验证手算的正确性,我们编程实现输出widthStep的大小,程序如下:
IplImage *image_33 = cvCreateImage(cvSize(3, 3), 8, 3);
IplImage *image_31 = cvCreateImage(cvSize(3, 3), 8, 1);
IplImage *image_53 = cvCreateImage(cvSize(5, 3), 8, 3);
IplImage *image_51= cvCreateImage(cvSize(5, 3), 8, 1);
IplImage *image_73 = cvCreateImage(cvSize(7, 3), 8, 3);
IplImage *image_71 = cvCreateImage(cvSize(7, 3), 8, 1);
printf("%d, %d, %d, %d, %d, %d", image_33->widthStep,image_31->widthStep,
image_53->widthStep,image_51->widthStep,image_73->widthStep,image_71->widthStep);
运行结果为:12, 4, 16, 8, 24, 8, 与手动计算结果相同。
从网上查阅资料,OpenCV分配的内存按4字节对齐,这样我们对上述计算的结果可以有个合理的解释,如宽度为3、通道数为3的图像,每一行需要的 实际内存长度为3*3,为了内存对齐,OpenCV会在每行末尾自动补上3个字节的内存,内存初始化都为0,所以widthStep变为了12。
widthStep大小对IplImage极为重要,在cxarray.cpp中,我们可以找到如下代码行:
image->imageSize = image->widthStep * image->height;
img->imageData = img->imageDataOrigin =
(char*)cvAlloc( (size_t)img->imageSize );
可见widthStep直接影响到imageData的数据长度。在操作imageData时,我们要避开对OpenCV自动补齐的内存进行操作,如直方图计算等。
写到这里,可能有人会问,我们平常都用widthStep = width * nChannels,怎么就没出错?我之前也一直在疑惑,合理的解释是,一般在实际应用中,图像的宽度一般为128, 256, 240, 320, 356,704等,刚好这些数字都能被4整除,widthStep刚好等于width * nChannels, 所以OpenCV并没有为这些图像分配多的内存,因此我们在对imageData做顺序操作也没出错。但是,请问谁能保证图像的宽度一定会是4的倍数?
纯属个人理解,如有错误,还请大虾多多指出。
经过上面的分析,我已经完全理解了widthStep的计算以及为何data[i * step + j * channels + k]这么计算了
java+widthstep,i*step+j*channels+k 以及widthStep大小计算及原理相关推荐
- 2021-12-08:扑克牌中的红桃J和梅花Q找不到了,为了利用剩下的牌做游戏,小明设计了新的游戏规则: 1) A,2,3,4....10,J,Q,K分别对应1到13这些数字,大小王对应0; 2) 游
2021-12-08:扑克牌中的红桃J和梅花Q找不到了,为了利用剩下的牌做游戏,小明设计了新的游戏规则: A,2,3,4-10,J,Q,K分别对应1到13这些数字,大小王对应0; 游戏人数为2人,轮流 ...
- 使用指针交换i,j,k的值
<程序设计基础-c语言>杨莉 刘鸿翔 ISBN-978-7-03-032903-5 p137 习题5 2.从键盘输入三个数分别赋给变量i.j.k.同时设置三个指针变量p1.p2.p3分别指 ...
- java加载c库阻塞_【死磕Java並發】-----J.U.C之阻塞隊列:DelayQueue
DelayQueue是一個支持延時獲取元素的無界阻塞隊列.里面的元素全部都是"可延期"的元素,列頭的元素是最先"到期"的元素,如果隊列里面沒有元素到期,是不能從 ...
- java.util.UnknownFormatConversionException: Conversion = ‘j‘ || Conversion = ‘D‘ || Conversion = ‘Y‘
执行内容: String a = "select * from j_question j where j.status = %s and j.title like '%java%'" ...
- lintcode 734. 形式为a^i b^j c^k的子序列数量 题解
描述 给一字符串, 对形式为 a^i b^j c^k 的子序列进行计数, 即它由 i 个字符 a, 接着是 j 个字符 b, 然后是 k 个字符 c组成, i >= 1, j >= 1, ...
- USB 2.0 协议中J、K、SE0状态的定义
一.通俗解释 1.J态.K态.SE0 低速设备: J态: D+ ="0",D- ="1" K态: D+ ="1",D- ="0&q ...
- 求赌王的密码 【问题描述】 赌王喜欢“A”,密码由6行6列扑克牌中每行“A”的位置数字组合而成。扑克牌点数由1~9,J,Q,K,A组成,每行的扑克牌中最多只能出现一次“A”;也可能没有“A”,
题头的话:长按点赞可私我赠送50+本C与C++书籍电子书资源 求赌王的密码 [问题描述] 赌王喜欢"A",密码由6行6列扑克牌中每行"A"的位置数字组合而成.扑 ...
- for(j=0,i=0;j6,i10;j++,i++) { k=i+j; } k 值结果是多少?
<script type="text/javascript">function Test(){var k=0;for(j=0,i=0;j<6,i<10;j+ ...
- 道路测量xy坐标表示什么_三坐标(CMM)测量的矢量方向(i,j,k)
三坐标(CMM)测量的矢量方向(i,j,k) 什么是矢量方向? 矢量方向(以下简称矢量)是垂直于零件表面的路径方向.任何特征都需要有矢量,它指导测量探针垂直于测量表面操作.这个复杂的计算工作通常交给测 ...
- Android Studio ---- Cannot resolve symbol 'XXX',java文件 显示蓝色J的图标
问题: 现象1. 我在MsgReceiver.java中 使用Msg2.java , 但是报红,引用失败,无法找到.(之前是好的,不知什么原因导致) Cannot resolve symbol 'XX ...
最新文章
- java验证码(采用struts2实现)转
- Ubuntu 安装 Linux Deepin 截图工具(.deb)
- ospf lesson 3
- Java 程序员中位数薪资达 1.45 万,但面试屡屡被拒?
- 试题10 最大子阵(枚举)
- quartus仿真17:T触发器的时序逻辑电路
- edge浏览器的html文件,手把手解决win10系统利用edge浏览器共享网页的具体方法
- java 围棋_围棋冠军都输了?用Java编写的智能围棋战力惊人?
- HPE comms CTO:我们的单位在增长,即使我们的客户不是
- ant中修改a-switch的大小、修改a-checkbox的大小
- local_listener参数(2)---elaine
- 网络维护工程师的要求是什么?
- 基于JAVA的企业部门报销管理信息系统的设计与实现
- 【CTSC2016】时空旅行
- 新月音标_又一个新月?
- nginx 反向代理及负载均衡策略
- K近邻(KNN)算法总结
- SUMO仿真教程(1) ——安装环境的设置(Windows 10系统)
- 关于IAR安装的注意问题和教训
- centos7 登录到经典桌面_centos7操作系统安装与配置