公司网站建设升上去,校园网站素材,郫县网站制作,六安钢贴吧一直以为IplImage结构体中的widthStep元素大小等于width*nChannels#xff0c;大错特错#xff01;#xff08;为了快速访问#xff0c;要内存对齐啊#xff09;查看OpenCV2.1的源码#xff0c;在src/cxcore/cxarray.cpp文件中#xff0c;找到cvInitImageHeader函数大错特错为了快速访问要内存对齐啊查看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)); 其中IPL_DEPTH_SIGN的定义可以在cxtypes.h中找到定义为#define IPL_DEPTH_SIGN 0x80000000 align的大小为CV_DEFAULT_IMAGE_ROW_ALIGN其大小在cxmisc.h中定义为#define CV_DEFAULT_IMAGE_ROW_ALIGN 4depth取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 356704等刚好这些数字都能被4整除widthStep刚好等于width * nChannels 所以OpenCV并没有为这些图像分配多的内存因此我们在对imageData做顺序操作也没出错。但是请问谁能保证图像的宽度一定会是4的倍数