一、结构解释
IplImage数据结构体中有两个宽度:
1 是width属性,表示图像的每行像素数;
2 是widthStep属性,表示存储一行像素需要的字节数。
在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。所以widthStep不等于width*nChannels。
三通道字节图像中,imageData排列如下,其中BGR分别为每个像素的三个通道值。
举例:如果单通道图像宽度为3,由于不是4的整数倍,所以加一个字节补齐,则widthStep是4。即这个图像的一行需要4个字节,只使用前3个,最后一个空着。也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。
注意,在不知道imageData是四字节对齐的情况下直接读取,会造成错位。空着的那个像素并不是无效的,它仍然可以被操作。
二、去掉补齐位,正常读取
unsigned char* colors1 = (unsigned char*)input->imageData;unsigned char* colors2 = (unsigned char*)test->imageData;//字节对齐int widths = input->width; //每行像素个数int heights = input->height; int widthSteps = input->widthStep; //存储一行像素需要的字节数int cn = input->nChannels;unsigned char* color1 = (unsigned char*)malloc(3* widths * heights *sizeof(unsigned char));unsigned char* color2 = (unsigned char*)malloc(3* widths * heights *sizeof(unsigned char));for (int i = 0; i < heights; i++)for (int j = 0; j < widths; j++){for (int k = 0; k < cn; k++){color1[i*widths*cn + cn*j + k] = colors1[i*widthSteps + j*cn + k];color2[i*widths*cn + cn*j + k] = colors2[i*widthSteps + j*cn + k];}}
理解:
i*widthSteps + j*cn + k中,i*widthSteps计算前几行的字节数,j*cn计算当前行已经占有的字节数,再加上1 2 3.
i*widths*cn + cn*j + k中, i*widths*cn是计算前几行占有的字节数,j*cn计算当前行已经占有的字节数,再加上1 2 3.