18 #ifndef VISION_COMMON_FOV_DISTORTER_H_
19 #define VISION_COMMON_FOV_DISTORTER_H_
26 #include <opencv2/opencv.hpp>
28 #include <ceres/ceres.h>
37 Eigen::Matrix<T, 2, 1>
Distort(
const T* distortion,
const Eigen::Matrix<T, 3, 3>& intrinsics,
38 const Eigen::Matrix<T, 2, 1>& undistorted_point)
const {
40 const Eigen::Matrix<T, 2, 1> relative_coordinates =
RelativeCoordinates(undistorted_point, intrinsics);
41 const T& relative_x = relative_coordinates[0];
42 const T& relative_y = relative_coordinates[1];
45 const T r2 = relative_x * relative_x + relative_y * relative_y;
46 const T& w = distortion[0];
49 const T a = 2.0 * ceres::tan(w / 2.0);
50 const T b = ceres::atan(r2 * a) / w;
55 const T distorted_relative_x = warping * relative_x;
56 const T distorted_relative_y = warping * relative_y;
57 return AbsoluteCoordinates(Eigen::Matrix<T, 2, 1>(distorted_relative_x, distorted_relative_y), intrinsics);
60 cv::Mat
Undistort(
const cv::Mat& distorted_image,
const Eigen::Matrix3d& intrinsics,
61 const Eigen::VectorXd& distortion)
const final {
62 cv::Mat gray_distorted_image;
63 cv::cvtColor(distorted_image, gray_distorted_image, cv::COLOR_BGRA2GRAY);
64 cv::Mat undistorted_image(distorted_image.size(), CV_8UC1, cv::Scalar(0));
65 for (
int y = 0; y < undistorted_image.rows; ++y) {
66 for (
int x = 0; x < undistorted_image.cols; ++x) {
67 const uchar pixel_val = gray_distorted_image.at<uchar>(y, x);
68 const Eigen::Vector2d undistorted_point =
Undistort(Eigen::Vector2d(x, y), intrinsics, distortion);
69 const Eigen::Vector2i undistorted_rounded_point(std::round(undistorted_point[0]),
70 std::round(undistorted_point[1]));
71 if (undistorted_rounded_point.x() >= undistorted_image.cols || undistorted_rounded_point.x() < 0)
continue;
72 if (undistorted_rounded_point.y() >= undistorted_image.rows || undistorted_rounded_point.y() < 0)
continue;
73 undistorted_image.at<uchar>(undistorted_rounded_point.y(), undistorted_rounded_point.x()) = pixel_val;
76 return undistorted_image;
79 Eigen::Vector2d
Undistort(
const Eigen::Vector2d& distorted_point,
const Eigen::Matrix3d& intrinsics,
80 const Eigen::VectorXd& distortion)
const final {
81 const Eigen::Vector2d relative_distorted_point =
RelativeCoordinates(distorted_point, intrinsics);
82 const double rd = relative_distorted_point.norm();
83 const double a = 2.0 * std::tan(distortion[0] / 2.0);
84 const double ru = std::tan(rd * distortion[0]) / a;
85 const double unwarping = rd > 1e-5 ? ru / rd : 1.0;
86 const Eigen::Vector2d relative_undistorted_point = unwarping * relative_distorted_point;
87 const Eigen::Vector2d undistorted_point =
AbsoluteCoordinates(relative_undistorted_point, intrinsics);
88 return undistorted_point;
93 #endif // VISION_COMMON_FOV_DISTORTER_H_