Loading web-font TeX/Main/Regular
OpenCV  
Open Source Computer Vision
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Remapping

Prev Tutorial: Hough Circle Transform

Next Tutorial: Affine Transformations

Goal

In this tutorial you will learn how to:

a. Use the OpenCV function cv::remap to implement simple remapping routines.

Theory

What is remapping?

Code

  • The tutorial code's is shown lines below. You can also download it from here
    #include <iostream>
    using namespace cv;
    void update_map( int &ind, Mat &map_x, Mat &map_y );
    int main(int argc, const char** argv)
    {
    CommandLineParser parser(argc, argv, "{@image |chicky_512.png|input image name}");
    std::string filename = parser.get<std::string>(0);
    Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );
    if (src.empty())
    {
    std::cout << "Cannot read image: " << filename << std::endl;
    return -1;
    }
    Mat dst(src.size(), src.type());
    Mat map_x(src.size(), CV_32FC1);
    Mat map_y(src.size(), CV_32FC1);
    const char* remap_window = "Remap demo";
    namedWindow( remap_window, WINDOW_AUTOSIZE );
    int ind = 0;
    for(;;)
    {
    update_map(ind, map_x, map_y);
    remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
    imshow( remap_window, dst );
    char c = (char)waitKey( 1000 );
    if( c == 27 )
    {
    break;
    }
    }
    return 0;
    }
    void update_map( int &ind, Mat &map_x, Mat &map_y )
    {
    for( int i = 0; i < map_x.rows; i++ )
    {
    for( int j = 0; j < map_x.cols; j++ )
    {
    switch( ind )
    {
    case 0:
    if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 )
    {
    map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;
    map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;
    }
    else
    {
    map_x.at<float>(i, j) = 0;
    map_y.at<float>(i, j) = 0;
    }
    break;
    case 1:
    map_x.at<float>(i, j) = (float)j;
    map_y.at<float>(i, j) = (float)(map_x.rows - i);
    break;
    case 2:
    map_x.at<float>(i, j) = (float)(map_x.cols - j);
    map_y.at<float>(i, j) = (float)i;
    break;
    case 3:
    map_x.at<float>(i, j) = (float)(map_x.cols - j);
    map_y.at<float>(i, j) = (float)(map_x.rows - i);
    break;
    default:
    break;
    } // end of switch
    }
    }
    ind = (ind+1) % 4;
    }

Explanation

Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );
if (src.empty())
{
std::cout << "Cannot read image: " << filename << std::endl;
return -1;
}
Mat dst(src.size(), src.type());
Mat map_x(src.size(), CV_32FC1);
Mat map_y(src.size(), CV_32FC1);
const char* remap_window = "Remap demo";
namedWindow( remap_window, WINDOW_AUTOSIZE );
int ind = 0;
for(;;)
{
update_map(ind, map_x, map_y);
remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
imshow( remap_window, dst );
char c = (char)waitKey( 1000 );
if( c == 27 )
{
break;
}
}

This is expressed in the following snippet. Here, map_x represents the first coordinate of h(i,j) and map_y the second coordinate.

void update_map( int &ind, Mat &map_x, Mat &map_y )
{
for( int i = 0; i < map_x.rows; i++ )
{
for( int j = 0; j < map_x.cols; j++ )
{
switch( ind )
{
case 0:
if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 )
{
map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;
map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;
}
else
{
map_x.at<float>(i, j) = 0;
map_y.at<float>(i, j) = 0;
}
break;
case 1:
map_x.at<float>(i, j) = (float)j;
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
case 2:
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)i;
break;
case 3:
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
default:
break;
} // end of switch
}
}
ind = (ind+1) % 4;
}

Result

  1. After compiling the code above, you can execute it giving as argument an image path. For instance, by using the following image:

    Remap_Tutorial_Original_Image.jpg
  2. This is the result of reducing it to half the size and centering it:

    Remap_Tutorial_Result_0.jpg
  3. Turning it upside down:

    Remap_Tutorial_Result_1.jpg
  4. Reflecting it in the x direction:

    Remap_Tutorial_Result_2.jpg
  5. Reflecting it in both directions:

    Remap_Tutorial_Result_3.jpg