cv::solvePnp的使用方法及注意事项(OpenCV/C  )
人民网>>社会·法治

cv::solvePnp的使用方法及注意事项(OpenCV/C )

2025-06-24 08:55:12 | 来源:人民网
小字号

cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, flags);

1、参数说明:

  • objectPoints。:一个 vector,世界坐标系中包含三维点的坐标,至少需要4个点。
  • imagePoints。:一个 vector,坐标࿰包含相应图像上的二维点c;与 objectPoints 中点一一对应。
  • cameraMatrix。:相机内参数矩阵,类型为 cv::Mat,一般为 3x3 浮点数矩阵。
  • distCoeffs。:相机的畸变系数,类型为 cv::Mat,一般为 4x1 或 5x1 浮点数矩阵。
  • rvec。:输出的旋转向量,类型为 cv::Mat,是大小为 3x1 浮点数矩阵。
  • tvec。:输出的平移向量,类型为 cv::Mat,是大小为 3x1 浮点数矩阵。
  • useExtrinsicGuess:一个布尔值󿀌表示初始猜测是否使用可选的旋转和平移向量。默认为 false。
  • flags:控制函数行为的选项标志,默认为 0。

        函数返回:

  • 成功返回 true,失败返回 false。

2、使用说明书:

objectPoints, imagePoints, cameraMatrix, distCoeffs  作为输入参数的四个参数。

rvec, tvec 作为输出参数。

objectPoints是世界坐标系的三维坐标。

imagePoints是图像上的二维点坐标。

例如 用标定的单目相机拍摄矩形物体(已知相机内参&畸变系数),

objectPoints:用量尺测量左上角、右上角、左下角和右下角之间的距离,以任何一点为0点,建立世界坐标系,z值为0,objectPoints࿰获得所有点的坐标c;保存在vector中。

imagePoints:在图像中找到物体的左上角、右上角、左下角和右下角c;imagePoints࿰的所有像素坐标c;保存在vector中。

使用示例:

#include #include #include int main() {    std::vector objectPoints;  // 世界坐标系中的三维点    std::vector imagePoints;   // 图像上的二维点        // 添加 objectPoints 和 imagePoints 的数据        // 在相机中创建参数矩阵    cv::Mat cameraMatrix = (cv::Mat_(3,3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);      // 创建相机畸变系数矩阵    cv::Mat distCoeffs = (cv::Mat_(1,5) << k1, k2, p1, p2, k3;        ///完善内部参数&变形系数参数          cv::Mat rvec;  // 输出的旋转向量    cv::Mat tvec;  // 输出的平移向量        bool success = cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);        if (success) {        // 获得旋转向量和平移向量的结果        cv::Mat rotationMatrix;        cv::Rodrigues(rvec, rotationMatrix);        std::cout << "Rotation Vector:" << std::endl << rvec << std::endl;        std::cout << "Translation Vector:" << std::endl << tvec << std::endl;        std::cout << "Rotation Matrix:" << std::endl << rotationMatrix << std::endl;    }        return 0;}。

3、注意事项:

使用solvePnP时,需注意。3、注意事项:使用solvePnP时,需要注意的是,

objectPoints和imagePoints容器中的点坐标必须一一对应。

,例如,只有四点󿀌容器中࿱按照左上角、右上角、左下角、右下角的顺序存储b;如果顺序不同,最终输出值是错误的。当作者使用solvePnp时,#xff0c;拍摄对象是四个定位圆,通过opencvSimpleBlobDetector识别圆的像素坐标,识别后的圆像素坐标是无序的,不能与objectpoints对应,所以有以下算法󿀌

用于。

对四个二维坐标进行冒泡排序,得到左上角、右上角、左下角、右下角对应的点。

(如果没有需求,这一段)可以忽略;

int main() { std::vector imagePoints; // 存放四点 vector // 假设已经存储了四个点的坐标 imagePoints 中 // 寻找左上角、右上角、右下角和左下角对应的点 cv::Point2f topLeft, topRight, bottomRight, bottomLeft; float minX = FLT_MAX, minY = FLT_MAX; float maxX = FLT_MIN, maxY = FLT_MIN; for (const auto& point : imagePoints) { if (point.x <= minX && point.y <= minY) { topLeft = point; minX = point.x; minY = point.y; } if (point.x >= maxX && point.y <= minY) { topRight = point; maxX = point.x; minY = point.y; } if (point.x >= maxX && point.y >= maxY) { bottomRight = point; maxX = point.x; maxY = point.y; } if (point.x <= minX && point.y >= maxY) { bottomLeft = point; minX = point.x; maxY = point.y; } } // 输出左上角、右上角、右下角和左下角对应点的坐标 std::cout << "左上角坐标: (" << topLeft.x << ", " << topLeft.y << ")" << std::endl; std::cout << "右上角坐标: (" << topRight.x << ", " << topRight.y << ")" << std::endl; std::cout << "右下角坐标: (" << bottomRight.x << ", " << bottomRight.y << ")" << std::endl; std::cout << "左下角坐标: (" << bottomLeft.x << ", " << bottomLeft.y << ")" << std::endl; // 新建vector存储四个点坐标#xff0c;按照objectpoints的存储顺序存储 std::vector imagePoints2; imagePoints2.push_back(topLeft); imagePoints2.push_back(topRight); imagePoints2.push_back(bottomRight); imagePoints2.push_back(bottomLeft); return 0;}。4、补充。

4、补充。

1、旋转向量rvec和平移向量tvec通过solvePnP获得后,可以。

计算相机到被测物体中心的实际距离。#include #include #include #include int main() { std::vector objectPoints; // 世界坐标系中的三维点 std::vector imagePoints; // 图像上的二维点 // 添加 objectPoints 和 imagePoints 的数据 // 在相机中创建参数矩阵 cv::Mat cameraMatrix = (cv::Mat_(3,3) << fx, 0, cx, 0, fy, cy, 0, 0, 1); // 创建相机畸变系数矩阵 cv::Mat distCoeffs = (cv::Mat_(1,5) << k1, k2, p1, p2, k3; ///完善内部参数&畸变系数参数 cv::Mat rvec; // 输出的旋转向量 cv::Mat tvec; // 输出的平移向量 bool success = cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec); if (success) { ///计算相机与被测物体之间的实际距离 float distance = sqrt(tvec.at(0,0) * tvec.at(0,0) + tvec.at(1,0) * tvec.at(1,0) + tvec.at(2,0) * tvec.at(2,0)) / 10; std::cout << "distance = "<< distance << std::endl; } return 0;}。2024年6月25日补充#xff1a;

2、从solvepnp函数中获得。2024年6月25日补充#xff1a;2、为solvepnp函数而获得的平移向量tevc。:。tevc的第三个值。

表示。相机与目标点之间的距离在相机坐标系中。,这个值是相机坐标系中z轴的坐标值,即。相对于相机的深度,目标点。

。tvec所有值平方和开平方。表示了。相机与目标点之间的总距离(实际距离)#xff0;。

(责编:人民网)

分享让更多人看到