OpenCV立体校正:已知原图点求校正后对应点的方法咨询
原图到立体校正后图像的坐标映射实现
在OpenCV立体校正流程中,initUndistortRectifyMap生成的映射表是校正后图像→原图的方向,要实现原图→校正后图像的坐标映射,可通过以下两种方式:
方法一:基于相机参数的逆变换计算
立体校正的正向流程是:原图像素点 → 去畸变 → R1旋转 → P1投影 → 校正图像素点。我们可以逆推这个过程来计算对应点:
- 对原图点进行去畸变,转换为相机坐标系下的归一化点
- 用校正旋转矩阵
R1旋转该归一化点 - 通过投影矩阵
P1将旋转后的点映射到校正后的图像平面
代码示例
cv::Point2f getRectifiedPoint(const cv::Point2f& origPoint, const cv::Mat& K, const cv::Mat& D, const cv::Mat& R1, const cv::Mat& P1) { // 1. 去畸变,得到归一化相机坐标 std::vector<cv::Point2f> src = {origPoint}; std::vector<cv::Point2f> undistorted; cv::undistortPoints(src, undistorted, K, D, cv::Mat(), K); // 2. 转换为齐次坐标并应用R1旋转 cv::Mat homoPoint(3, 1, CV_64F); homoPoint.at<double>(0) = undistorted[0].x; homoPoint.at<double>(1) = undistorted[0].y; homoPoint.at<double>(2) = 1.0; cv::Mat rotated = R1 * homoPoint; // 3. 用P1投影到校正图像平面 cv::Mat rectHomo = P1 * rotated; float u = static_cast<float>(rectHomo.at<double>(0) / rectHomo.at<double>(2)); float v = static_cast<float>(rectHomo.at<double>(1) / rectHomo.at<double>(2)); return cv::Point2f(u, v); }
方法二:预构建反向映射表
如果需要频繁查询,建议预先遍历原图所有像素,计算每个点对应的校正图点并存储为映射表,后续查询直接查表即可:
代码示例
// 生成原图→校正图的映射表 cv::Mat buildReverseMap(const cv::Size& imgSize, const cv::Mat& K, const cv::Mat& D, const cv::Mat& R1, const cv::Mat& P1) { cv::Mat reverseMap(imgSize, CV_32FC2); // 每个元素存储校正后的(x,y) for (int y = 0; y < imgSize.height; ++y) { for (int x = 0; x < imgSize.width; ++x) { cv::Point2f rectPoint = getRectifiedPoint(cv::Point2f(x, y), K, D, R1, P1); reverseMap.at<cv::Vec2f>(y, x) = cv::Vec2f(rectPoint.x, rectPoint.y); } } return reverseMap; } // 查询时直接调用 cv::Point2f queryRectPoint(const cv::Point2f& origPoint, const cv::Mat& reverseMap) { return reverseMap.at<cv::Vec2f>(origPoint.y, origPoint.x); }
注意事项
- 方法一适合少量查询,无需额外内存开销;方法二适合大量查询,预计算后查询效率更高
- 计算得到的校正点可能为浮点数,若需整数像素,可根据需求做四舍五入或插值处理
- 务必保证使用的
K、D、R1、P1参数与立体校正阶段完全一致
内容的提问来源于stack exchange,提问作者Dawson Kiwi
相关产品推荐
相关产品推荐

