利用opencv-python标定后的参数使用
其中对于重投影误差的解读参考博客:
cv2.calibrateCamera()返回的值中,ret也就是重投影误差的计算公式。求的是RMS均方根误差,对所有的点,求二范数,然后求平均再开根号,得到RMS误差。
利用这里的代码是很容易求得标定参数的。但是求出来参数之后,怎么在其他地方使用,需要理解相机标定的原理和opencv对内参数和畸变参数的定义。
参考opencv的源码(\modules\calib3d\src\calibration.cpp)和测试,编写了如下代码:利用标定参数和像点的物方坐标计算理想像点坐标。
#自己实现的cv2.projectPoints;输入要求是一样的。
#v_rot, v_trans, mat_inter, coff_dis直接就是cv2.calibrateCamera
def projectPoints(obj_points, v_rot, v_trans, mat_inter, coff_dis):
img_points_repro = np.zeros((np.shape(obj_points)[0], 2))
for i in np.arange(np.shape(obj_points)[0]):
#把旋转矢量转换成旋转矩阵
R = cv2.Rodrigues(v_rot)
k1,k2,p1,p2,k3 = coff_dis[0,0],coff_dis[0,1],coff_dis[0,2],coff_dis[0,3],coff_dis[0,4]
fx=mat_inter[0,0]
fy=mat_inter[1,1]
cx=mat_inter[0,2]
cy=mat_inter[1,2]
# print(np.shape(v_trans), np.shape(R[0]), np.shape(obj_points[i,:]))
#旋转和平移
v_trans=np.reshape(v_trans, (3,1))
M = np.reshape(obj_points[i,:], (3,1))
xyz= np.dot(R[0],M) + v_trans
# x = R[0]*X + R[1]*Y + R[2]*Z + t[0];
# double y = R[3]*X + R[4]*Y + R[5]*Z + t[1];
# double z = R[6]*X + R[7]*Y + R[8]*Z + t[2];
# print(xyz)
#归一化
x = xyz[0,0]/xyz[2,0]
y = xyz[1,0]/xyz[2,0]
#畸变
r_2 = x*x + y*y;
r_4 = r_2*r_2;
r_6 = r_4*r_2;
# a1 = 2*x*y;
# a2 = r2 + 2*x*x;
# a3 = r2 + 2*y*y;
# cdist = 1 + k1*r2 + k2*r4 + k3*r6;
# icdist2 = 1./(1 + );
# xd0 = x*cdist*icdist2 + p1*a1 + p2*a2 ;
# yd0 = y*cdist*icdist2 + p1*a3 + p2*a1 ;
# // 径向畸变和切向畸变
xdis = x*( 1.0 + k1*r_2 + k2*r_4 + k3*r_6) + 2.0*p1*x*y + p2*(r_2 + 2.0*x*x);
ydis = y*( 1.0 + k1*r_2 + k2*r_4 + k3*r_6) + p1*(r_2 + 2.0*y*y) + 2.0*p2*x*y;
# print(fx*xdis + cx, fy*ydis + cy)
# // 像素距离计算
# fx的 像素 cx的单位是像素
# f的单位式米,f_x=\frac{f}{d_x},其中d_x表示x方向每个像素占多大,即一个像素在相机感光板上的物理长度。
img_points_repro[i, 0] = fx*xdis + cx;
img_points_repro[i, 1] = fy*ydis + cy;
return img_points_repro
如果能够配置一个c++环境,应该很快可以定位源码;直接用python的话,就不太确定标定结果怎么使用和解读了。