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

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 coordinates and one for the 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.