opencvdistortion

Apply relative radial distortion function to image w/o knowing anything about the camera


I've a radial distortion function which gives me relative distortion from 0 (image center) to the relative full image field (field height 1) in percent. For example this function would give me a distortion of up to 5% at the full relative field height of 1.

I tried to use this together with opencv undistort function to apply distortion but don't know how to fill the matrices.

As said, I've a source image only and don't know anything about the camera parameters like focal length, except that I know the distortion function.

How should I set the matrix in cv2.undistort(src_image, matrix, ...) ?


Solution

  • The OpenCv routine that's easier to use in your case is cv::remap, not undistort.

    In the following I assume your distortion purely radial. Similar considerations apply if you have it already decomposed in (x, y).

    So you have a distortion function d(r) of the distance r = sqrt((x - x_c)^2 + (y - y_c)^2) of a pixel (x, y) from the image center (x_c, y_c). The function expresses the relative change of the radius r_d of a pixel in the distorted image from the undistorted one r: (r_d - r) / r = d(r), or, equivalently, r_d = r * (1 - d(r)).

    If you are given a distorted image, and want to remove the distortion, you need to invert the above equation (i.e. solve it analytically or numerically), finding the value of r for every r_d in the range of interest. Then you can trivially create two arrays, map_x and map_y, that represent the mapping from distorted to undistorted coordinates: for a given pair (x_d, y_d) of integer pixel coordinates in the distorted image, you compute the associated r_d = sqrt(((x_d - x_c)^2 + (y_d - y_c)^2), then the corresponding r as function of r_d from solving the equation, go back to (x, y), and assign map_x[y_d, x_d] = x; map_y[y_d, x_d] = y. Finally, you pass those to cv::remap.