Ask Your Question

Correct use of fisheye::distortPoints()

asked 2017-08-24 07:32:07 -0500

I am trying to figure out how to distort (not undistort!) an image. This is the code that I am using:

#include <iostream>

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/calib3d.hpp>

using namespace std;

using namespace cv;
using namespace cv::fisheye;

static Mat_<Point2f> GetDistortionMapping(const Size2i &image_size, const array<float, 4> &distortion_vector)
  Mat_<float> empty_camera_matrix = Mat::eye(3, 3, CV_32F);
  empty_camera_matrix(2, 0) = image_size.width / 2.f;
  empty_camera_matrix(2, 1) = image_size.height / 2.f;
  Mat_<Point2f> image_points(image_size);
  for (int y = 0; y < image_size.height; y++)
    for (int x = 0; x < image_size.width; x++)
      image_points(x, y) = Point2f(y, x);
  Mat_<Point2f> distorted_points(image_size);
  distortPoints(image_points, distorted_points, empty_camera_matrix, distortion_vector);
  return distorted_points;

static void ShowImage(const Mat &image)
  const array<float, 4> distortion_vector { 1.f, 0.f, 0.f, 0.f };
  const Mat distortion_mapping = GetDistortionMapping(image.size(), distortion_vector);
  Mat distorted_image;
  remap(image, distorted_image, distortion_mapping, noArray(), INTER_LANCZOS4);
  imshow("Distorted", distorted_image);

int main(const int argc, const char * const argv[])
  if (argc != 2)
    cout << "Illustrates the effect of the distortion vector on a camera." << endl;
    cout << "Usage: " << argv[0] << " <camera image>" << endl;
    return 1;
  const auto filename = argv[1];
  const Mat image = imread(filename);
  if (image.empty())
    cerr << "Could not read input image '" << filename << "'" << endl;
    return 2;
  return 0;

I am using cv::fisheye::distortPoints and pass it a matrix with all image coordinates (0, 0), (0, 1), ... (h - 1, w - 1). Then I use remap to perform the actual remapping of the points. I have worked with initUndistortRectifyMap successfully, but I can't seem to get any meaningful result out of distortPoint (see below for an example with the Lenna image).

image description

I tried different distortion vector values as well as a identity matrix as empty_camera_matrix(i.e., without setting the principal point). Am I using the function incorrectly or is this approach wrong altogether?

edit retag flag offensive close merge delete

1 answer

Sort by » oldest newest most voted

answered 2018-06-15 04:58:05 -0500

As in fisheye::undistortPoints description said: "Note that the function assumes the camera matrix of the undistorted points to be identity. This means if you want to transform back points undistorted with undistortPoints() you have to multiply them with P−1"

This note (not very clear actually) means that cv::fisheye::undistortPoints accepts _normalized_ coordinates as an input. From code above your input points are in unnormalized (i.e. in pixel) coordinates. That way it won't work.

So you should do something like this (variation of of code from my working sw):

vector<Point2f> srcp; //Array of undistorded points
vector<Point2f> dstp; //Array of distorded points
srcp.push_back(Point2f(100,100)); //Adding one point as an example, in pixel coordinates
Matx33d camMat = K; //K is my camera matrix estimated by cv::fisheye::calibrate
Matx33d camMat_inv = camMat.inv(); //Inverting the camera matrix
for(size_t i=0;i<srcp.size();i++) {
    Vec3d srcv = Vec3d(srcp[i].x, srcp[i].y, 1.0); //Creating a vector in homogeneous coords
    Vec3d dstv = camMat_inv*srcv; //Doing martix by vector multiplication
    srcp[i].x = dstv[0]; //Extracting resulting normalised x coord
    srcp[i].y = dstv[1]; //Extracting resulting normalised y coord
cv::fisheye::distortPoints(srcp, dstp, K,D); //Performing distortion. D is distortion vector

//Drawing resulting example point: 
circle(img_dist, Point2f(dstp[0].x, dstp[0].y), 3,CV_RGB(255,0,0), -1);
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower


Asked: 2017-08-24 07:32:07 -0500

Seen: 1,106 times

Last updated: Aug 24 '17