1

I am using a fisheye camera and I would like to calibrate it and correct its barrel distortion using OpenCV or any other library in Python. I have tried different methods using the classic chessboard pattern through different images.

I have been following this approach:

    # Prepare object points, like (0,0,0), (1,0,0), (2,0,0), ...,(7,5,0)
    object_p = np.zeros((self.__ny*self.__nx,3),np.float32)
    object_p[:,:2] = np.mgrid[0:self.__nx,0:self.__ny].T.reshape(-1,2) # s,y coordinates

for image_filename in calibration_filenames:
        # Read in each image
        image = cv2.imread(image_filename)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # RGB is standard in matlibplot

        # Convert to grayscale
        gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

        # Find the chessboard corners
        ret, corners = cv2.findChessboardCorners(gray, (self.__nx, self.__ny), None)

        # If found, draw corners
        if ret == True:
            # Store the corners found in the current image
            object_points.append(object_p) # how it should look like
            image_points.append(corners) # how it looks like

            # Draw and display the corners
            cv2.drawChessboardCorners(image, (self.__nx, self.__ny), corners, ret)
            plt.figure()
            plt.imshow(image)
            plt.show()

    # Do the calibration
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, shape, None, None)

And then this to correct my image:

cv2.undistort(image, mtx, dist, None, mtx)

The main problem is that, though correction performs good with some images, is very susceptible to camera location. A variation of cm in the camera will result in very different corrections (see below). enter image description here enter image description here

Any idea of how could I control this zoom effect to show maintain the grid area always in my corrected image?

I am aware that this question may be similar to the one in here.

Community
  • 1
  • 1
m33n
  • 1,622
  • 15
  • 38

1 Answers1

1
  1. Your calibration is poorly estimated: as you can see, straight lines in the scene grid are not transformed to straight lines in the (allegedly) undistorted image.
  2. Once you have a better calibration, you can compute (using the inverse mapping) the location of the 4 sides of the undistorted image in the original ones. These define your usable image boundaries, and can guide the placement of the camera with respect to the scene.
Francesco Callari
  • 11,300
  • 2
  • 25
  • 40
  • Could you explain a little bit more about your second point? How can I do that? – m33n Nov 04 '17 at 12:39
  • 1
    Un-distorting barrel distortion results in an apparent enlargement of the image. This is because a physical distorting lens projects onto the sensor rays that would be "outside" the image area of the pinhole camera with the same focal length. This is the reason why in a fully undistorted rectangular image, the valid portion has a "butterfly" shape, see e.g. the picture at https://stackoverflow.com/questions/18742679/how-to-get-all-undistorted-image-with-opencv . See also the suggestion there of using getOptimalNewCameraMatrix. – Francesco Callari Nov 05 '17 at 05:18