-
坐标系示意图
-
像素坐标系与图像坐标系
- 像素坐标轴为uv,图像坐标轴为xy
- 参数为:dx, dy, u0, v0
-
-
图像坐标系与相机坐标系
-
-
相机坐标系与世界坐标系
-
- 旋转矩阵R
-
-
像素坐标系映射到世界坐标系
-
-
各坐标系转换代码实现
-
import sys import os sys.path.append(os.getcwd()) import numpy as np camera_intrinsic = { # R,旋转矩阵 "R": [[-0.91536173, 0.40180837, 0.02574754], [0.05154812, 0.18037357, -0.98224649], [-0.39931903, -0.89778361, -0.18581953]], # t,平移向量 "T": [1841.10702775, 4955.28462345, 1563.4453959], # 焦距,f/dx, f/dy "f": [1145.04940459, 1143.78109572], # principal point,主点,主轴与像平面的交点 "c": [512.54150496, 515.45148698] } class CoordinateConvert: @staticmethod def convert_wc_to_cc(joint_world): # joint_world: n*3 """ 世界坐标系 -> 相机坐标系: R * pt + T :return: """ joint_world = np.asarray(joint_world) R = np.asarray(camera_intrinsic["R"]) T = np.asarray(camera_intrinsic["T"]) joint_num = len(joint_world) # 世界坐标系 -> 相机坐标系 # [R|t] world coords -> camera coords joint_cam = np.zeros((joint_num, 3)) # joint camera for i in range(joint_num): # joint i joint_cam[i] = np.dot(R, joint_world[i]) + T # R * pt + T return joint_cam @staticmethod def __cam2pixel(cam_coord, f, c): """ 相机坐标系 -> 像素坐标系: (f / dx) * (X / Z) = f * (X / Z) / dx cx,ppx=260.166; cy,ppy=205.197; fx=367.535; fy=367.535 将从3D(X,Y,Z)映射到2D像素坐标P(u,v)计算公式为: u = X * fx / Z + cx v = Y * fy / Z + cy D(v,u) = Z / Alpha ===================================================== camera_matrix = [[428.30114, 0., 316.41648], [ 0., 427.00564, 218.34591], [ 0., 0., 1.]]) fx = camera_intrinsic[0, 0] fy = camera_intrinsic[1, 1] cx = camera_intrinsic[0, 2] cy = camera_intrinsic[1, 2] ===================================================== :param cam_coord: :param f: [fx,fy] :param c: [cx,cy] :return: """ # 等价于:(f / dx) * (X / Z) = f * (X / Z) / dx # 三角变换, / dx, + center_x u = cam_coord[..., 0] / cam_coord[..., 2] * f[0] + c[0] v = cam_coord[..., 1] / cam_coord[..., 2] * f[1] + c[1] d = cam_coord[..., 2] return u, v, d @staticmethod def convert_cc_to_ic(joint_cam): """ 相机坐标系 -> 像素坐标系 :param joint_cam: :return: """ # 相机坐标系 -> 像素坐标系,并 get relative depth # Subtract center depth # 选择 Pelvis骨盆 所在位置作为相机中心,后面用之求relative depth root_idx = 0 center_cam = joint_cam[root_idx] # (x,y,z) mm joint_num = len(joint_cam) f = camera_intrinsic["f"] c = camera_intrinsic["c"] # joint image,像素坐标系,Depth 为相对深度 mm joint_img = np.zeros((joint_num, 3)) joint_img[:, 0], joint_img[:, 1], joint_img[:, 2] = CoordinateConvert.__cam2pixel(joint_cam, f, c) # x,y joint_img[:, 2] = joint_img[:, 2] - center_cam[2] # z: 相对图片某个点的深度信息 return joint_img if __name__ == "__main__": joint_world = [[-91.679, 154.404, 907.261], [-223.23566, 163.80551, 890.5342], [-188.4703, 14.077106, 475.1688], [-261.84055, 186.55286, 61.438915], [39.877888, 145.00247, 923.98785], [-11.675994, 160.89919, 484.39148], [-51.550297, 220.14624, 35.834396], [-132.34781, 215.73018, 1128.8396], [-97.1674, 202.34435, 1383.1466], [-112.97073, 127.96946, 1477.4457], [-120.03289, 190.96477, 1573.4], [25.895456, 192.35947, 1296.1571], [107.10581, 116.050285, 1040.5062], [129.8381, -48.024918, 850.94806], [-230.36955, 203.17923, 1311.9639], [-315.40536, 164.55284, 1049.1747], [-350.77136, 43.442127, 831.3473], [-102.237045, 197.76935, 1304.0605]] joint_world = np.asarray(joint_world) # show in 世界坐标系 coordinate_convert = CoordinateConvert() # show in 相机坐标系 joint_cam = coordinate_convert.convert_wc_to_cc(joint_world) joint_img = coordinate_convert.convert_cc_to_ic(joint_cam)
-
-
内参外参总结
- 相机的内参数是六个分别为:1/dx、1/dy、r、u0、v0、f。
- r表示径向畸变量级,r为负值,畸变为桶型畸变,r为正值,畸变为枕型畸变,初始值为0。
- dx、dy表示图像传感器上水平和垂直方向上相邻像素之间的距离。
- u0,v0表示图像坐标系原点在像素坐标系中位置。
- opencv1里说的内参数是4个其为fx、fy、u0、v0。(fx=f/dx、fy=f/dy、r=0)
- 畸变参数:(k1、k2、p1、p2、k3)
- 相机的内参数是六个分别为:1/dx、1/dy、r、u0、v0、f。
-
求取内参外参方法
-
OpenCV SolvePnP原理解释
相机坐标系转换总结
最新推荐文章于 2024-02-19 09:34:22 发布