Search code examples
c++opencvcamera-calibrationremap

How does the remap function in OpenCV for undistorting images work?


for debugging purposes I tried to reimplement the remap function of OpenCV. Without considering interpolation, it should look something like this:

for( int j = 0; j < height; j++ )
{
    for( int i = 0; i < width; i++ )
    {
        undistortedImage.at<double>(mapy.at<float>(j,i),mapx.at<float>(j,i)) = distortedImage.at<double>(j,i);
    }
}

To test this, I used following maps to mirror the image around the y-axis:

int width = distortedImage.cols;
int height = distortedImage.rows;
cv::Mat mapx = Mat(height, width, CV_32FC1);
cv::Mat mapy = Mat(height, width, CV_32FC1);
for( int j = 0; j < height; j++)
{
    for( int i = 0; i < width; i++)
    {
        mapx.at<float>(j,i) = width - i - 1;
        mapy.at<float>(j,i) = j;
    }
}

But the interpolation it works exactly like

cv::remap( distortedImage, undistortedImage, mapx, mapy, CV_INTER_LINEAR);

Now I tried to apply this function on maps created by the OCamCalib Toolbox for undistorting images. This is basicly the same as what is done by the OpenCV undistortion as well. My implementation now obviously does not consider that several pixels from the source image are mapped to the same pixel in the destination image. But it is worse. Actually, it looks like my source image appears three times in smaller versions in the destination image. Otherwise the remap command works perfectly.

After exhaustive debugging I decided to ask you guys for some help. Can anyone explain me what I am doing wrong or provide a link to the implementation of remap in OpenCV?


Solution

  • I figured it out myself. My original implementation has two fundamental mistakes:

    1. Misunderstanding on how the maps are used.
    2. Misunderstanding on how to extract intensity values.

    How to do it correctly:

    for( int j = 0; j < height; j++ )
    {
        for( int i = 0; i < width; i++ )
        {
            undistortedImage.at<uchar>(mapy.at<float>(j,i),mapx.at<float>(j,i)) = distortedImage.at<uchar>(j,i);
        }
    }
    

    I want to highlight that the intensity values from the images are now extracted using .at<uchar> instead of .at<double>. Furthermore, the indices for the maps are switched.