重投影误差

本文介绍了归一化平面的齐次坐标概念,将三维空间点坐标除以Z形成单位距离的归一化平面,再通过乘以焦距还原到成像平面。重投影误差定义为在图像平面上,三维点的成像坐标与观测值之间的差异,通过归一化齐次坐标简化计算。

1. 什么是归一化平面的齐次坐标

https://blog.youkuaiyun.com/ouyangandy/article/details/96840781

所谓的归一化的成像平面,就是将三维空间点的坐标都除以Z。
在这里插入图片描述
在这里插入图片描述
所有空间点坐标都转到了相机前单位距离处,这个平面就叫归一化的平面,之后再乘以焦距ff,让归一化平面回到成像平面。以一张别的博主做的图为例说明各个坐标系的转换关系:
在这里插入图片描述
参考:
高翔 视觉SLAM十四讲
https://blog.youkuaiyun.com/weixin_38133509/article/details/85689838

 

归一化齐次坐标的作用?

简单来说,就是方便转换,归一化平面坐标 乘上距离Z,就转换到了世界物理坐标(以相机

重投影误差是在计算机视觉和摄影测量等领域中,将三维空间中的点投影到图像平面后,投影点与实际观测点之间的误差。以下是一些常见的重投影误差补偿方法: #### 相机标定优化 通过更精确的相机标定来减少重投影误差。传统的张正友标定法是一种常用的相机标定方法,它可以估计相机的内参、外参和畸变系数。在标定过程中,使用更多的标定图像和更精确的角点检测算法可以提高标定的精度。例如,在OpenCV中可以使用`cv2.calibrateCamera`函数进行相机标定: ```python import cv2 import numpy as np # 准备标定板的角点坐标 objp = np.zeros((6*7, 3), np.float32) objp[:, :2] = np.mgrid[0:7, 0:6].T.reshape(-1, 2) # 存储对象点和图像点的数组 objpoints = [] # 3d point in real world space imgpoints = [] # 2d points in image plane # 读取标定图像 images = glob.glob('calibration_images/*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 查找棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, (7, 6), None) if ret == True: objpoints.append(objp) # 亚像素级角点检测 corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) imgpoints.append(corners2) # 相机标定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) ``` #### 非线性优化 使用非线性优化算法(如Levenberg - Marquardt算法)来最小化重投影误差。在Bundle Adjustment(光束法平差)中,通过同时优化相机的内参、外参和三维点的坐标,使得所有三维点的重投影误差之和最小。在Python中可以使用`scipy.optimize.least_squares`函数实现非线性优化: ```python from scipy.optimize import least_squares def reprojection_error(params, points_3d, points_2d, camera_matrix): # 解析参数 rotation_vector = params[:3] translation_vector = params[3:6] # 进行投影 projected_points, _ = cv2.projectPoints(points_3d, rotation_vector, translation_vector, camera_matrix, None) projected_points = projected_points.reshape(-1, 2) # 计算重投影误差 error = points_2d - projected_points return error.flatten() # 初始参数估计 initial_params = np.zeros(6) # 进行非线性优化 result = least_squares(reprojection_error, initial_params, args=(points_3d, points_2d, camera_matrix)) optimized_params = result.x ``` #### 滤波方法 使用滤波算法(如卡尔曼滤波、扩展卡尔曼滤波等)对重投影误差进行滤波处理。这些滤波算法可以根据系统的状态模型和观测模型,对重投影误差进行预测和校正,从而减少误差的影响。例如,在卡尔曼滤波中,通过预测和更新两个步骤来估计系统的状态: ```python import numpy as np # 初始化卡尔曼滤波器 kalman = cv2.KalmanFilter(4, 2) kalman.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32) kalman.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32) kalman.processNoiseCov = np.array([[1e-5, 0, 0, 0], [0, 1e-5, 0, 0], [0, 0, 1e-5, 0], [0, 0, 0, 1e-5]], np.float32) kalman.measurementNoiseCov = np.array([[1e-1, 0], [0, 1e-1]], np.float32) # 进行滤波 measurement = np.array([[x], [y]], np.float32) prediction = kalman.predict() kalman.correct(measurement) ``` #### 数据筛选和异常值处理 在计算重投影误差时,可能会存在一些异常值,这些异常值会对误差的计算和补偿产生较大的影响。可以使用一些方法(如RANSAC算法)来筛选出可靠的数据点,排除异常值的干扰。在OpenCV中可以使用`cv2.findFundamentalMat`函数结合RANSAC算法来进行异常值处理: ```python F, mask = cv2.findFundamentalMat(points1, points2, cv2.FM_RANSAC) points1 = points1[mask.ravel() == 1] points2 = points2[mask.ravel() == 1] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值