widthstep

widthstep简言之:image->widthStep=(int(image->width*image->nChannels+3)/4)*4,既图像宽度*图像通道数,再向上取最近的4的倍数,因为每行是按4的倍数分配内存的做直方图计算时要注意空的内存。灰度图的width和widthstep不相等。前者是表示图像的每行像素数,后者指表示存储一行像素需要的字节数。  在Op

大家好,又见面了,我是你们的朋友全栈君。



简言之:image->widthStep = (int(image->width * image->nChannels+3)/4)*4,既图像宽度*图像通道数,再向上取最近的4的倍数,因为每行是按4的倍数分配内存的

做直方图计算时要注意空的内存。

灰度图的width和widthstep不相等。前者是表示图像的每行像素数,后者指表示存储一行像素需要的字节数。
  在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。如果8U单通道图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空着。也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。

一直以为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                             12

                   1                             4

                   3                            16

                   1                             8

                   3                             24

                   1                             8

                   3                             12

                   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的倍数? 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/131612.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CentOS7 下rpm安装jdk1.8「建议收藏」

    CentOS7 下rpm安装jdk1.8「建议收藏」【1】查看并卸载自带的openjdk查看系统中默认安装的jdk:rpm-qa|grepjdk卸载JDK相关文件:yum-yremovejava-1.7.0-openjdk*“*”表示卸载掉java1.7.0的所有openjdk相关文件。或者如下卸载jdk:yum-yremovejava-1.8.0-openjdk-headless-1.8.0.65-3.b17.el7.x86_64

    2022年6月7日
    52
  • JavaScript 基本知识

    JavaScript 基本知识bilibiliJS视频链接:https://www.bilibili.com/video/BV1W54y1J7Ed?p=2&spm_id_from=pageDrivervscode配置html:https://blog.csdn.net/caohongxing/article/details/108632859目录JS来源JavaScript核心由三部分组成书写位置:行内式,内嵌式,外链式变量:var准备一个容器,变量名有规格且区分大小写JS中的数据:基本数据类型和引用数据类型.

    2022年10月20日
    0
  • docker的端口映射_docker swarm 网络

    docker的端口映射_docker swarm 网络docker网络端口映射

    2022年10月7日
    0
  • 舆情分析系统技术解决方案及作用论文_网络舆情解决方案

    舆情分析系统技术解决方案及作用论文_网络舆情解决方案网络舆情分析工作的开展最先需要做好的就是网络舆情的搜集工作,由于互联网信息内容庞杂多样,舆情信息搜集起来困难,所以要进行舆情分析更是难上加难。但若舆情信息收集的不全,就极易导致舆情分析不正确。那么,到底舆情分析工作要怎么做呢?针对此问题,提供了以下舆情分析系统技术解决方案,供各位参考。在了解方案的前,先来说说为什么要采用舆情分析系统进行监测分析。一、使用舆情分析系统进行监测分析的意义网络信息化时代,信息数据量庞大,若一味采用人工进行舆情信息分析,容易出现收集的舆情不全、舆情分析不正确等问题。而通过利用

    2022年9月20日
    0
  • 思科和华为交换机命令的区别(思科交换机和华为交换机的异同)

    思科和华为交换机常用命令对比一、调试命令思科:Switch#showrun显示所有配置命令Switch#showipinterbrief显示所有接口状态Switch#showvlanbrief显示所有VLAN的信息Switch#showversion显示版本信息华为:[Quidway]discur显示所有配置命令[Quidway…

    2022年4月16日
    75
  • mac 安装ll命令[通俗易懂]

    mac 安装ll命令[通俗易懂]mac安装ll命令mac-bash:ll:commandnotfound在linux系统下我们经常使用ll、la命令。但在mac系统时缺没有。提示:-bash:ll:commandnotfound。这是因为ll、la不是真的命令,而是一些常用命令和参数搭配的别名。所以我们在MacOS下配置下就好了。1、跳到个人目录下面localhost:~huangfy20$cdlocalhost:~huangfy20$pwd/Users/huangfy202、打开.bash

    2022年9月2日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号