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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何用burpsuite抓包[通俗易懂]

    如何用burpsuite抓包[通俗易懂]首先:使用火狐浏览器,并下载插件proxy点击上图右边的按钮并选择附加组件查询并下载插件配置代理点击options,然后add需要抓包时点击绿色的就行了burpsuite首先我们来到proxy界面在开启插件代理和interceptison的情况下点击某个链接即可抓取数据包需要改包发包的话可以直接在这里修改后直接forward或者同时按ctrl和r在下图…

    2022年5月20日
    64
  • opkg软件源设置[通俗易懂]

    opkg软件源设置[通俗易懂]opkg软件源定义在/etc/opkg/distfeeds.conf(更新/etc/opkg.conf并没有什么卵用)文件中,包含软件源索引的目录路径。分为base,luci,management,packages,routeing,telephony多个目录。每个目录存放对应的packages和索引文件。如果想更新base部分的包,请在添加相应的目录名称:vim/etc/o

    2022年5月22日
    192
  • 测试用例编写_功能测试用例自动生成

    测试用例编写_功能测试用例自动生成前言写用例之前,我们应该熟悉API的详细信息。建议使用抓包工具Charles或AnyProxy进行抓包。har2case我们先来了解一下另一个项目har2case他的工作原理就是将当前主流的抓

    2022年8月6日
    6
  • MFC + CxImage 实现自绘半透明按钮

    MFC + CxImage 实现自绘半透明按钮

    2021年8月27日
    59
  • JAVA——Tess4J简单的图像识别DEMO

    JAVA——Tess4J简单的图像识别DEMO基本概念TesseractOpenSourceOCREngine:包含一个OCR引擎-libtesseract和一个命令行程序-tesseract。Tesseract4添加了一个新的基于LSTM的OCR引擎,该引擎专注于行识别,但仍支持Tesseract3的传统TesseractOCR引擎,该引擎通过识别字符模式进行工作。通过使用传统OCR引擎模式(–oem0),可以与Tesseract3兼容。它还需要训练有素的数据文件来支持旧式引擎,例如tessdata存储库中的文件。…

    2022年6月5日
    79
  • excel怎么只打印某页?excel怎么只打印某几页

    excel怎么只打印某页?excel怎么只打印某几页

    2021年11月9日
    166

发表回复

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

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