The description below indicates that the projection using a camera with a hole (which does not distort the lens) is modeled
R_u = f*tan(theta)
and projection using conventional lenses with optical lenses (i.e. distorted) is modeled
R_d = 2*f*sin(theta/2)
You already know R_d and theta, and if you know the focal length of the camera (represented by f), then correcting the image will mean computing R_u in terms of R_d and theta. In other words,
R_u = f*tan(2*asin(R_d/(2*f)))
is the formula you are looking for. An estimate of the focal length f can be solved by calibrating the camera or other means, such as providing the user with feedback on how well the image is corrected or using knowledge from the original scene.
To solve the same problem using OpenCV, you will need to get the cameraβs internal parameters and lens distortion factors. See, for example, Chapter 11 OpenCV Training (Remember to Check Correction ). You can then use a program such as this (written using Python bundles for OpenCV) to cancel lens distortion:
#!/usr/bin/python # ./undistort 0_0000.jpg 1367.451167 1367.451167 0 0 -0.246065 0.193617 -0.002004 -0.002056 import sys import cv def main(argv): if len(argv) < 10: print 'Usage: %s input-file fx fy cx cy k1 k2 p1 p2 output-file' % argv[0] sys.exit(-1) src = argv[1] fx, fy, cx, cy, k1, k2, p1, p2, output = argv[2:] intrinsics = cv.CreateMat(3, 3, cv.CV_64FC1) cv.Zero(intrinsics) intrinsics[0, 0] = float(fx) intrinsics[1, 1] = float(fy) intrinsics[2, 2] = 1.0 intrinsics[0, 2] = float(cx) intrinsics[1, 2] = float(cy) dist_coeffs = cv.CreateMat(1, 4, cv.CV_64FC1) cv.Zero(dist_coeffs) dist_coeffs[0, 0] = float(k1) dist_coeffs[0, 1] = float(k2) dist_coeffs[0, 2] = float(p1) dist_coeffs[0, 3] = float(p2) src = cv.LoadImage(src) dst = cv.CreateImage(cv.GetSize(src), src.depth, src.nChannels) mapx = cv.CreateImage(cv.GetSize(src), cv.IPL_DEPTH_32F, 1) mapy = cv.CreateImage(cv.GetSize(src), cv.IPL_DEPTH_32F, 1) cv.InitUndistortMap(intrinsics, dist_coeffs, mapx, mapy) cv.Remap(src, dst, mapx, mapy, cv.CV_INTER_LINEAR + cv.CV_WARP_FILL_OUTLIERS, cv.ScalarAll(0)) # cv.Undistort2(src, dst, intrinsics, dist_coeffs) cv.SaveImage(output, dst) if __name__ == '__main__': main(sys.argv)
Also note that OpenCV uses a completely different lens distortion model to the one on your web page.