计算通过姿态估计找到的棋盘的正规方程
Calculate the normal equation for a checkerboard found through pose estimation
我正在从事激光扫描项目。为此,我正在关注此 paper 以进行校准。我目前被卡住了,作者计算了用于校准相机的棋盘平面参数(以及接下来的激光平面)。
为了生成测试数据,我使用了Blender,根据raspberry pi V2. 提供相机数据(焦距、像素大小等)
在 calculating/finding intrinsic camera matrix 与 OpenCv (Python 3)
之后
cv.findChessboardCorners()
cv.cornerSubPix()
在 opencv.org 的 tutorial 之后,我正在使用
cv.solvePnP()
获取平面的旋转和平移矢量的函数。使用以下代码,我现在正在按照作者的公式计算距相机中心的法线距离和符号距离:
normalvector = rotationmatrix * [[0][0][1]]
distance = (normalvector * -1)T * translational vector
(T = 转置向量)
import numpy as np
import cv2 as cv
with np.load("vectorsRT.npz", "r") as file:
rvecs, tvecs = [file[i] for i in ("rotationVectors", "translationVectors")]
rot_matrix = cv.Rodrigues(rvecs)[0]
mult_matrix = np.array([[0],[0],[1]])
normal_vector = np.matmul(rot_matrix, mult_matrix)
normal_vector_neg = normal_vector * -1
normal_vector_neg_transposed = np.transpose(normal_vector_neg)
signed_distance = np.matmul(normal_vector_neg_transposed, tvecs)
print("normal_vector:", normal_vector)
print("signed_distance:", signed_distance)
有了这个,我现在得到了一个法向量和到相机中心的距离,例如:
normal_vector:
[[-0.0604253 ]
[ 0.16923283]
[ 0.98372203]]
signed_distance:
[[[-51.67514398]]]
从搅拌机我得到以下正常
[[-0.00117647]
[-0.00333335]
[-0.01939508]]
法线或多或少是等效的,但是,现在如何将带符号的距离转换为世界坐标系中平面的支持向量,从而得到完整的平面方程?
我想我找到了答案:在这个 post 之后,我引入了符号距离的比例因子 s,以将距离转换为真实世界的距离(以毫米为单位)。
calc_distance_camera_plane = signed_distance * s
这个比例因子是用一个已知的平面距离除以的(例如:棋盘在世界坐标系Z=0,相机固定在一个位置,例如:Z=25mm,向下看)通过那个确切图像的signed_distance
scale_factor = dist_camera_world_orign / signed_distance
利用该比例因子,可以将每个 signed_distance 转换为真实世界距离 (camera-plane) 并获得真实世界距离 (world orign-plane)
dist_world_orign_plane = dist_camera_world_orign - calc_distance_camera_plane
然后我寻找的平面方程由计算出的法线和一个带有
的点给出
(0, 0, dist_world_orign_plane)
因为我有原始平面的精确值(图像是用搅拌机计算的),我可以将 camera_plane 的计算距离与实际距离(实际 distance/calculated 距离)进行比较:
n = 10
mean difference: 1.005
standard deviation: 0.0281
我认为这是进一步测试的良好起点。
希望这个回答也能帮到别人,干杯
我正在从事激光扫描项目。为此,我正在关注此 paper 以进行校准。我目前被卡住了,作者计算了用于校准相机的棋盘平面参数(以及接下来的激光平面)。
为了生成测试数据,我使用了Blender,根据raspberry pi V2.
cv.findChessboardCorners()
cv.cornerSubPix()
在 opencv.org 的 tutorial 之后,我正在使用
cv.solvePnP()
获取平面的旋转和平移矢量的函数。使用以下代码,我现在正在按照作者的公式计算距相机中心的法线距离和符号距离:
normalvector = rotationmatrix * [[0][0][1]]
distance = (normalvector * -1)T * translational vector
(T = 转置向量)
import numpy as np
import cv2 as cv
with np.load("vectorsRT.npz", "r") as file:
rvecs, tvecs = [file[i] for i in ("rotationVectors", "translationVectors")]
rot_matrix = cv.Rodrigues(rvecs)[0]
mult_matrix = np.array([[0],[0],[1]])
normal_vector = np.matmul(rot_matrix, mult_matrix)
normal_vector_neg = normal_vector * -1
normal_vector_neg_transposed = np.transpose(normal_vector_neg)
signed_distance = np.matmul(normal_vector_neg_transposed, tvecs)
print("normal_vector:", normal_vector)
print("signed_distance:", signed_distance)
有了这个,我现在得到了一个法向量和到相机中心的距离,例如: normal_vector:
[[-0.0604253 ]
[ 0.16923283]
[ 0.98372203]]
signed_distance:
[[[-51.67514398]]]
从搅拌机我得到以下正常
[[-0.00117647]
[-0.00333335]
[-0.01939508]]
法线或多或少是等效的,但是,现在如何将带符号的距离转换为世界坐标系中平面的支持向量,从而得到完整的平面方程?
我想我找到了答案:在这个 post 之后,我引入了符号距离的比例因子 s,以将距离转换为真实世界的距离(以毫米为单位)。
calc_distance_camera_plane = signed_distance * s
这个比例因子是用一个已知的平面距离除以的(例如:棋盘在世界坐标系Z=0,相机固定在一个位置,例如:Z=25mm,向下看)通过那个确切图像的signed_distance
scale_factor = dist_camera_world_orign / signed_distance
利用该比例因子,可以将每个 signed_distance 转换为真实世界距离 (camera-plane) 并获得真实世界距离 (world orign-plane)
dist_world_orign_plane = dist_camera_world_orign - calc_distance_camera_plane
然后我寻找的平面方程由计算出的法线和一个带有
的点给出(0, 0, dist_world_orign_plane)
因为我有原始平面的精确值(图像是用搅拌机计算的),我可以将 camera_plane 的计算距离与实际距离(实际 distance/calculated 距离)进行比较:
n = 10
mean difference: 1.005
standard deviation: 0.0281
我认为这是进一步测试的良好起点。 希望这个回答也能帮到别人,干杯