OpenCV 4 Computer Vision Application Programming Cookbook(Fourth Edition)
上QQ阅读APP看书,第一时间看更新

How it works...

In a color image, the first three bytes of the image's data buffer give values of the upper-left pixel to the three-color channel. The next three bytes are the values of the second pixel of the first row, and so on (remember that OpenCV uses, by default, the BGR channel order). An image of width W and height H would then require a memory block of WxHx3uchars. However, for efficiency reasons, the length of a row can be padded with a few extra pixels. This is because some multimedia processor chips (for example, the Intel MMX architecture) can process images more efficiently when their rows are multiples of four or eight. Obviously, these extra pixels are not displayed or saved; their exact values are ignored. OpenCV designates the length of a padded row as the effective width. Obviously, if the image has not been padded with extra pixels, the effective width will be equal to the real image width. We have already learned that the cols and rows attributes give you the image's width and height; similarly, the step data attribute gives you the effective width in the number of bytes. Even if your image is of a type other than uchar, the step data will still give you the number of bytes in a row. The size of a pixel element is given by the elemSize method (for example, for a three-channel short integer matrix (CV_16SC3), elemSize will return 6). Recall that the number of channels in the image is given by the nchannels method (which will be 1 for a gray-level image and 3 for a color image). Finally, the total method returns the total number of pixels (that is, the matrix entries) in the matrix.

The number of pixel values per row is then given by the following code:

     int nc= image.cols * image.channels();  

To simplify the computation of the pointer arithmetic, the cv::Mat class offers a method that gives you the address of an image row directly. This is the ptr method. It is a template method that returns the address of row j:

     uchar* data= image.ptr<uchar>(j); 

Note that in the processing statement, we could have equivalently used the pointer arithmetic to move from column to column. So, we could have written the following code:

     *data= *data/div*div + div2; data++;