OpenCV相机校准:x、y参数单位与畸变系数归一化问题问询
OpenCV相机畸变系数的归一化问题及修正方法
核心问题:你直接用像素坐标计算是错的,OpenCV输出的畸变系数是基于归一化坐标的,不是原始像素坐标。
归一化坐标的计算逻辑:
要把像素坐标(x,y)转换到相机坐标系的归一化平面(z=1),公式为:x_norm = (x - cx) / fx y_norm = (y - cy) / fy其中(cx, cy)是光心的像素坐标,(fx, fy)是相机内参的焦距(像素单位)。此时计算的r是归一化坐标到原点的距离:
r = sqrt(x_norm² + y_norm²),这个r的范围通常在0~1之间(对应图像边缘),代入畸变公式后结果才会合理。正确的畸变计算流程:
- 像素坐标转归一化坐标
- 用归一化坐标计算畸变后的归一化坐标(x_dist_norm, y_dist_norm)
- 把畸变后的归一化坐标转回像素坐标:
x_distorted = x_dist_norm * fx + cx y_distorted = y_dist_norm * fy + cy
这样计算出来的像素差值才会符合预期(轻微畸变下小于5像素)。
文档位置:OpenCV官方文档中,
calibrateCamera函数的说明明确标注了畸变系数是针对归一化坐标的;另外在相机校准的官方教程(比如"Camera Calibration and 3D Reconstruction"章节)中,也详细说明了畸变模型的坐标系统。修正后的代码示例:
注意需要传入校准时得到的相机内参焦距fx、fy:import numpy as np def distortion_delta(img, center, fx, fy, dist): k1, k2, p1, p2, k3 = dist distorted_x = np.zeros_like(img, dtype=np.float64) distorted_y = np.zeros_like(img, dtype=np.float64) xc, yc = center h, w = img.shape for i in range(h): for j in range(w): # 像素坐标转归一化坐标(注意j是x方向,i是y方向) x_norm = (j - xc) / fx y_norm = (i - yc) / fy r_sq = x_norm**2 + y_norm**2 # 计算畸变后的归一化坐标 x_dist_norm = x_norm * (1 + k1*r_sq + k2*r_sq**2 + k3*r_sq**3) y_dist_norm = y_norm * (1 + k1*r_sq + k2*r_sq**2 + k3*r_sq**3) # 转回像素坐标并计算与原像素的差值 distorted_x[i,j] = (x_dist_norm * fx + xc) - j distorted_y[i,j] = (y_dist_norm * fy + yc) - i return distorted_x, distorted_y # 替换成你校准得到的实际fx、fy值 fx, fy = 500.0, 500.0 dist = [-1.21094023e+01, 5.08189016e+02, 1.21622025e-01, -2.98076561e-03, 1.13290212e+00] img = np.ones((50, 100)) dx, dy = distortion_delta(img, [50,25], fx, fy, dist)
内容的提问来源于stack exchange,提问作者kai90
相关产品推荐
相关产品推荐

