How it works...
The objective of remapping is to produce a new version of an image in which pixels have changed their positions. To construct this new image, we need to know what the original position for each pixel in the destination image is in the source image. The mapping function that is needed is, therefore, the one that will give us the original pixel positions as a function of the new pixel positions. This is called backward mapping because the transformation describes how the pixels of the new images are mapped back to the original image. In OpenCV, backward mapping is described using two maps—one for the x coordinates and one for the y coordinates. They are both represented by floating-point cv::Mat instances:
// the map functions cv::Mat srcX(image.rows,image.cols,CV_32F); // x-map cv::Mat srcY(image.rows,image.cols,CV_32F); // y-map
The size of these matrices will define the size of the destination image. The value of the (i,j) pixel of the destination image can then be read in the source image, by using the following line of code:
( srcX.at<float>(i,j) , srcY.at<float>(i,j) )
For example, a simple image flip effect such as the one we demonstrated in Chapter 1, Playing with Images, can be created by the following maps:
// creating the mapping for (int i=0; i<image.rows; i++) { for (int j=0; j<image.cols; j++) { // horizontal flipping srcX.at<float>(i,j)= image.cols-j-1; srcY.at<float>(i,j)= i; } }
To generate the resulting image, you simply call the OpenCV remap function:
// applying the mapping cv::remap(image, // source image result, // destination image srcX, // x map srcY, // y map cv::INTER_LINEAR); // interpolation method
It is interesting to note that the two maps contain floating-point values. Consequently, a pixel in the destination image can map back to a nonintegral value (that is, a location between pixels). This is very convenient because this allows us to define the mapping function of our choice. For instance, in our remapping example, we used a sinusoidal function to define our transformation. However, this also means that we have to interpolate the value of virtual pixels in between real pixels. There exist different ways of performing pixel interpolation, and the last parameter of the remap function allows us to select the method that will be used. Pixel interpolation is an important concept in image processing; this subject will be discussed in Chapter 6, Filtering the Images.