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, ...) ?
CodePudding user response:
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 to 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.