绪:
在OpenCV中,widthStep是相对于IplImage*进行图像像素拜候操作的;
而step是相对于Mat进行图像像素拜候操作的;
widthStep:存储一行像素需要的字节数;
step:每一行中所有元素的字节总量,单元字节;
本文本家儿要介绍:
widthStep界说;widthStep在IplImage中的感化;widthStep在图像像素拜候中的应用;
widthStep总结;
step在Mat类中的感化;step在图像像素拜候中的应用;

东西/原料
- OpenCV 2410
方式/步调
- 1
widthStep界说:
①OpenCV中,默认图像原点为图像左上角,img->origin=IPL_ORIGIN_TL;若是想更改图像原点坐标也可以,如img->origin=IPL_ORIGIN_BL,将图像原点更改为左下角;
一般采用默认的图像原点;
②OpenCV用imread或者cvLoadImage获得的图像数据都是unsigned char类型的;
③IplImage布局体中的widthStep元素巨细纷歧心猿意马等于width*nChannels,
④在cxcore/cxarray.cpp文件中,cvInitImageHeader对widthStep巨细赋值:
image->widthStep =
(((image->width * image->nChannels *(image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
此中,
cxtypes.h界说IPL_DEPTH_SIGN为:#define IPL_DEPTH_SIGN 0x80000000;
cxmisc.h中界说align为:#define CV_DEFAULT_IMAGE_ROW_ALIGN 4;
depth取8位深度;
则可计较图像的widthStep;
一些图像的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。
- 2
widthStep在IplImage*中的感化:
如下:
typedef struct _IplImage{
int nSize; /* sizeof(IplImage) */
int ID; /* version (=0)*/
int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */
int alphaChannel; /* Ignored by OpenCV */
int depth; /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */
char colorModel[4]; /* Ignored by OpenCV */
char channelSeq[4]; /* ditto */
int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels.
cvCreateImage can only create interleaved images */
int origin; /* 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style). */
int align; /* Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead. */
int width; /* Image width in pixels. */
int height; /* Image height in pixels. */
struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */
struct _IplImage *maskROI; /* Must be NULL. */
void *imageId; /* " " */
struct _IplTileInfo *tileInfo; /* " " */
int imageSize; /* Image data size in bytes (==image->height*image->widthStep in case of interleaved data)*/
char *imageData; /* Pointer to aligned image data. */
int widthStep; /* Size of aligned image row in bytes. */
int BorderMode[4]; /* Ignored by OpenCV. */
int BorderConst[4]; /* Ditto. */
char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned) -
needed for correct deallocation */
}IplImage;
- 3
IplImage*拜候图像像素:widthStep
对8bit,单通道,unsigned char类型的图像I---IplImage* img:
I(x, y)~((unsigned char*)(img->imageData+img->widthStep*y))[x];
对8bit,3通道,unsigned char类型的图像I---IplImage* img:
I(x, y)blue~((unsigned char*)(img->imageData+img->widthStep*y))[x*3];
I(x, y)green~((unsigned char*)(img->imageData+img->widthStep*y))[x*3+1];
I(x, y)red~((unsigned char*)(img->imageData+img->widthStep*y))[x*3+2];
或者
unsigned char* ptr=&((unsigned char*)(img->imageData+img->widthStep*y))[x*3];
I(x, y)blue ~ ptr[0];
I(x, y)green~ ptr[1];
I(x, y)red ~ ptr[2];
对32bit,1通道,float*类型的图像I---IplImage* img:
I(x, y)~((float*)(img->imageData+img->widthStep*y))[x];
对32bit,3通道,float*类型的图像I---IplImage*img;
I(x, y) blue ~((float*)(img->imageData+img->widthStep*y))[3*x];
I(x, y) green ~(( float *)(img->imageData+img->widthStep*y))[x*3+1];
I(x, y) red ~(( float *)(img->imageData+img->widthStep*y))[x*3+2];
对64bit,3通道,double*类型的图像数据I--- IplImage*img;
image=cvCreateImage(cvSize(111,113),IPL_DEPTH_64F,3);
这里widthstep=(111*3*sizeof(double)+3)/4*4=2664;因为111*3*sizeof(double)=2664已经正好是4的倍数了,是以无需弥补字节。
若是用指针拜候第31行、51列的图像数据,
则这个数据为double类型的,image->imageData为unsigned char类型,
是以可以转换当作double,经由过程double指针来拜候:
①
double *data=(double*)image->imageData;
double val=*(data+31*width+51);
②或者经由过程unsigned char指针找到(31,51)处的地址,
然后转换当作double指针进行拜候:
unsigned char* data=image->imageData;
double val=*(double*)(data+31*image->widthStep+51*sizeof(double));
对于IplImage,指针拜候可以参考以上两种体例,其实这素质就是数据类型的转换罢了。
一般,拜候图像像素方式,格局:
对于N通道,T类型的图像,
I(x,y)c~((T*)(img->imageData+img->widthStep*y))[x*N+c];
- 4
widthStep常识总结:
width暗示图像的每行像素数,
widthStep暗示存储一行像素需要的字节数,widthStep必需是4的倍数,从而实现字节对齐,有利于提高运算速度。
若是8U单通道图像宽度为3,那么widthStep是4,加一个字节补齐。
这个图像的一行需要4个字节,只利用前3个,最后一个空着。
也就是一个宽3高3的图像的imageData数据巨细为4*3=12字节。
【注】:分歧数据类型长度的图像,widthStep也不不异;
widthStep的值的计较有两种环境:
①当(width*3)%4=0,这时width*3=widthStep;
②当(width*3)%4 !=0,此时widthStep=(width/4+1)*3。
Mat的数据并不是字节对齐的;
直接将cv::Mat转换为IplImage类型,并不会将字节对齐,只是加了个文件头罢了;
是以需要如下操作:
- 5
BYTE*与IplImage*之间的转换:
IplImage* iplImage:opencv中图像数据头;
BYTE* data:内存中的图像数据,一般为工业相机采集的图像数据;
①由IplImage*转BYTE*图像数据:
data = iplImage->imageDataOrigin; //未对齐的原始图像数据
或者
data = iplImage->imageData; //已对齐的图像数据
②BYTE*转IplImage*图像数据
iplImage = cvCreateImageHeader(cvSize(width,height),depth,channels);
cvSetData(iplImage,data,step);
起首,由cvCreateImageHeader()建立IplImage图像头,设置图像尺寸、深度和通道数;
然后,由cvSetData()按照BYTE*图像数据指针设置IplImage图像头的数据,
此中,step指心猿意马该IplImage图像,每行占的字节数,对于1通道的 IPL_DEPTH_8U图像,step可以等于width。
- 6
Mat拜候图像像素---step:
data:unsigned char类型的指针,指标的目的Mat数据矩阵的首地址;
dims:Mat矩阵的维度;
rows:Mat矩阵的行数;
cols:Mat矩阵的列数;
size():是一个布局体,有image.size().width==image.cols; image.size().height==image.rows
channels():Mat矩阵元素拥有的通道数;
depth:怀抱每一个像素中每一个通道的精度,但它自己与图像的通道数无关!depth数值越年夜,精度越高。在Opencv中,Mat.depth()获得的是一个0~6的数字,别离代表分歧的位数,如下:{CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6}
elemSize:暗示矩阵中每一个元素的数据巨细,单元字节,若是Mat中的数据类型是CV_8UC1,那么elemSize==1;若是是CV_8UC3或CV_8SC3,那么elemSize==3;若是是CV_16UC3或者CV_16SC3,那么elemSize==6;即elemSize是以8位(一个字节)为一个单元,乘以通道数和8位的整数倍;
elemSize1:
暗示Mat矩阵中每一个元素单个通道的数据巨细,单元字节,elemSize1=elemSize/channels;
step:为Mat矩阵中每一行的“步长”,以字节为根基单元,每一行中所有元素的字节总量;
step1():以字节为根基单元,Mat矩阵中每一个像素的巨细step1==step/elemSize1;
type:Mat矩阵的类型,包含有矩阵中元素的类型、通道数信息,type的定名格局为CV_(位数)+(数据类型)+(通道数),如下:
- 7
Mat拜候图像像素---step
step:为Mat矩阵中每一行的“步长”,以字节为根基单元,每一行中所有元素的字节总量;
经常应用在拜候图像像素操作中;如下:
对8bit,单通道,unsigned char类型的图像I---Mat img:
unsigned char* pData=(unsigned char*)img.data;
I(x, y)~pData[img.step*y+x];//
对8bit,3通道,unsigned char类型的图像I---IplImage* img:
I(x, y)blue~((unsigned char*)(img.data+img.step*y))[x*3];
I(x, y)green~((unsigned char*)(img.data+img.step*y))[x*3+1];
I(x, y)red~((unsigned char*)(img.data+img.step*y))[x*3+2];
对32bit,1通道,float*类型的图像I---Mat img:
I(x, y)~((float*)(img.data+img.step*y)[x];
对32bit,3通道,float*类型的图像I--- Mat img;
I(x, y) blue ~((float*)(img.data+img.step*y))[3*x];
I(x, y) green ~((float*)(img.data+img.step*y))[x*3+1];
I(x, y) red ~((float*)(img.data+img.step*y) )[x*3+2];
对64bit,1通道,double*类型的图像I---Mat img:
I(x, y)~((double*)(img.data+img.step*y)[x];
对64bit,3通道,double*类型的图像数据I--- Mat img;
I(x, y) blue ~(( double *)(img.data+img.step*y))[3*x];
I(x, y) green ~(( double *)(img.data+img.step*y))[x*3+1];
I(x, y) red ~(( double *)(img.data+img.step*y))[x*3+2];
一般,拜候图像像素方式,格局:
对于N通道,T类型的图像,
I(x,y)c~((T*)(img.Data+img.step *y))[x*N+c];
注重事项
- step拜候图像像素的形式;
- widthStep拜候图像像素的形式;
来源:百闻(微信/QQ号:9397569),转载请保留出处和链接!
本文链接:https://www.ibaiwen.com/web/236892.html
- 上一篇: PS中操控变形怎么用
- 下一篇: 制作qq皮肤透明教程
- 热门文章
-
WB蒙特利尔(WB Montreal)——欧美十大最差视频游戏开发商
迅猛龙(Velociraptor)——欧美史前十大死亡动物
什么是果酱猫(What Marmalade Cats)?
神奇蜘蛛侠2(The Amazing Spider-Man 2)——欧美最佳蜘蛛侠电影
希瑟(Heather)——欧美十大最佳柯南灰歌
二人梭哈
faceu激萌怎么把瘦脸开到最大
奥兹奥斯本(Ozzy Osbourne)——欧美十大高估歌手
什么是小脑前下动脉(Anterior Inferior Cerebellar Artery)?
我应该知道康涅狄格州的什么(What Should I Know About Connecticut)?
- 热评文章
- 最新评论
-
- 最近访客
-
- 站点信息
-
- 文章总数:200248
- 页面总数:9
- 分类总数:1
- 标签总数:0
- 评论总数:0
- 浏览总数:497