Skip to content

ccalib/omnidir undistortPoints result differs from undistortImage. #1612

@ftaralle

Description

@ftaralle
System information (version)
  • OpenCV => 3.3.0-dev
  • both in C++ and Python3
Detailed description

We are using omnidir module to correct wide angle fisheye effect on image data.
We first used cv::omnidir::calibrate to get a valid camera model.
We then used this model to undistort both images and points.

We found that applying undistortion methods with exact same parameters on images and points gives different results.
After investigation we think a bug exists in the undistortPoints method.

Steps to reproduce

Code to reproduce (fixed to be working, thanks to @whplh).

# import of modules
import numpy as np
import cv2
import matplotlib.pyplot as plt
#%matplotlib inline

# in/out image size
height, width = (1520, 2048)

# definition of camera model's parameters
K = np.array([[922.676, -6.87115, 1028.38], [0, 921.053, 718.469], [0, 0, 1]], np.float)
D = np.array([[-0.32628, 0.117317, 0.00124854, 0.000268858]], np.float)
X = np.array([[0.772963]], np.float)

# exposes K parameters
(fx, s, cx), (_, fy, cy), _ = K

# Build a list of 'known' distorted points
nPointsPerCirle = 20
fisheyeRadius = 700
circleRadiuses  = range(0, fisheyeRadius, 100)
angle = 2*np.pi * np.array([*range(nPointsPerCirle)], np.float) / nPointsPerCirle
distorted_points = np.vstack((
    np.vstack((cx + r * np.cos(angle), cy + r * np.sin(angle))).T
    for r in circleRadiuses    
))

# Build a distorted image with that known points on it
distorted_frame = np.zeros((height, width, 3), np.uint8)
cv2.circle(distorted_frame, (int(cx), int(cy)), fisheyeRadius, (255,255,255), -1)
# place points
for distorted_point in distorted_points.astype(int):
    cv2.circle(distorted_frame, tuple(distorted_point), 5, (0,0,255), -1)

# undistort image using omnidir
undistorted_frame = cv2.omnidir.undistortImage(distorted_frame, K, D, X, 1, np.eye(3))

# undistort points 
undistorted_points = cv2.omnidir.undistortPoints(
    np.array([distorted_points.tolist()], np.float), 
    K, D, X, np.eye(3))
x,y = undistorted_points.reshape(-1,2).T
undistorted_points = K.dot(np.vstack((x,y,np.ones_like(x)))).T[:,:2]

# print undistorted points ontop of undistorted image
for undistorted_point in undistorted_points.astype(int):
    cv2.circle(undistorted_frame, tuple(undistorted_point), 5, (255,0,0), 3)

# show result
out_frame = np.hstack((distorted_frame, undistorted_frame))
plt.figure(figsize=(np.array(out_frame.shape[:2]) / 100).tolist())
plt.imshow(cv2.cvtColor(out_frame, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()

resulting image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions