Opencv: distort back

后端 未结 7 698
清歌不尽
清歌不尽 2021-02-02 02:53

I have the cameraMatrix and the distCoeff needed to undistort an image or a vector of points. Now I\'d like to distort them back.

Is it poss

7条回答
  •  后悔当初
    2021-02-02 03:06

    The OCV camera model (see http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html) describes how a 3D point first maps to an immaginary ideal pinhole camera coordinate and then "distorts" the coordinate so that it models the image of the actual real world camera.

    Using the OpenCV distortion coefficients (= Brown distortion coefficients), the following 2 operations are simple to calculate:

    • Calculate the pixel-coordinate in the original camera image from a given pixel-coordinate in the distortion-free (i.e. undistorted image). AFAIK there is no explicit OpenCV function for this. But the code in Joan Charmant's answer does exactly this.
    • Calculate the distortion-free image from the original camera image. This can be done using cv::undistort(....) or alternatively a combination of cv::initUndistortRectifyMap(....) and cv::remap(....).

    However the following 2 operations are computionally much more complex:

    • Calculate the pixel coordinate in the distortion-free image from a pixel coordinate in the original camera image. This can be done using cv::undistortPoints(....).
    • Calculate the original camera image from the distortion-free image.

    This may sound counter intuitive. More detailed explanation:

    For a given a pixel coordinate in the distortion-free image it is easy to calculate the corresponding coordinate in the original image (i.e. "distort" the coordinate).

    x = (u - cx) / fx; // u and v are distortion free
    y = (v - cy) / fy;
    
    rr = x*x + y*y
    distortion = 1 + rr  * (k1 + rr * (k2 + rr * k3))
    # I ommit the tangential parameters for clarity
    
    u_ = fx * distortion * x + cx
    v_ = fy * distortion * y + cy
    // u_ and v_ are coordinates in the original camera image
    

    Doing it the other way round is much more difficult; basically one would need to combine all the code lines above into one big vectorial equation and solve it for u and v. I think for the general case where all 5 distortion coefficients are used, it can only be done numerically. Which is (without looking at the code) probably what cv::undistortPoints(....) does.

    However, using the distortion coefficients, we can calculate an undistortion-map (cv::initUndistortRectifyMap(....)) which maps from the distortion-free image coordinates to the original camera image coordinates. Each entry in the undistortion-map contains a (floating point) pixel position in the original camera image. In other words, the undistortion-map points from the distorion-free image into the original camera image. So the map is calculated by exactly the above formula.

    The map can then be applied to get the new distortion-free image from the original (cv::remap(....)). cv::undistort() does this without the explicit calculation of the undistorion map.

提交回复
热议问题