В описании , которое вы упоминаете , говорится, что проекция с помощью камеры с точечным отверстием (камеры, которая не вносит искажения в объектив) моделируется
R_u = f*tan(theta)
и проекция на обычные камеры типа «рыбий глаз» (то есть искаженная) моделируется с помощью
R_d = 2*f*sin(theta/2)
Вы уже знаете R_d и theta, и если бы вы знали фокусное расстояние камеры (представленное как f), то исправление изображения будет равносильно вычислению R_u в терминах R_d и theta. Другими словами,
R_u = f*tan(2*asin(R_d/(2*f)))
- формула, которую вы ищете. Оценка фокусного расстояния f может быть решена с помощью калибровки камеры или других средств, таких как предоставление пользователю обратной связи о том, насколько хорошо исправлено изображение, или использование знаний из исходной сцены.
Чтобы решить ту же проблему с помощью OpenCV, вам необходимо получить внутренние параметры камеры и коэффициенты искажения объектива. См., Например, главу 11 Обучение OpenCV (не забудьте проверить исправление ). Затем вы можете использовать программу, подобную этой (написанную с привязками Python для OpenCV), чтобы обратить искажение линзы:
#!/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)
Также обратите внимание, что OpenCV использует модель искажения объектива, совершенно отличную от модели на веб-странице, на которую вы ссылаетесь.