opencv + c++如何实现世界坐标系转像素坐标系

相机标定后得到内参和畸变系数,如何用opencv + c++实现世界坐标系转像素坐标系,代码怎么写,是有对应的函数吗

一般是世界坐标系先转成相机坐标系再都图像坐标系
原理、公式一般的鱼眼图像校正、图像拼接的论文里都有,自然校正方面的代码里也包含了。CSDN上有很多。

  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/194349
  • 这篇博客也不错, 你可以看下opencv-10-图像滤波-噪声添加与均值滤波-含opencv C++ 代码实现
  • 除此之外, 这篇博客: OpenCV两种方法批量读取文件夹下面的图像(万能模板,C++批量读取文件夹下的图片)中的 文件夹下图片有序时,OpenCV读取方法 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 对于文件夹下面的每张图片都是序号.bmp格式 的图像时可以使用如下方法按顺序读取。在这里插入图片描述

    #include<stdio.h>
    #include "opencv2/opencv.hpp"
    #include <opencv2\highgui\highgui.hpp>
    #include<string>
    #include<iostream>
    using namespace cv;
    using namespace std;
    void main(){
    char fileName[500];
     Mat pic;
     for (int i = 0; i < 110; i++) {//文件夹下面一共有110张图片
      printf("start deal:%d\n", i + 1);
      sprintf_s(fileName, ".//picture//%d.bmp", i);//提取出文价夹下面的每张图片路径,放到fileName
      pic = imread(fileName);//读取fileName路径下面的图片
      imshow("tpian", pic);//显示图像
      waitKey(1000);//显示延时
     }
     pic.release();//将Mat释放
    }
    
  • 您还可以看一下 于雄飞老师的OpenCV图像处理基础——基于C++实现课程中的 图像颜色滤镜-连环画滤镜小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    使用OpenCV和C++实现世界坐标系转化为像素坐标系的步骤如下:

    1.获取相机标定的内参和畸变系数,存储为相机的畸变矩阵和内参矩阵。

    2.定义三维点(世界坐标系)和二维点(像素坐标系),并将三维点按照世界坐标系坐标系下的坐标存储。

    std::vector<cv::Point3f> world_point;//存储世界坐标系下的三维点
    std::vector<cv::Point2f> pixel_point;//存储像素坐标系下的二维点
    world_point.push_back(cv::Point3f(0,0,0));//将世界坐标系下的坐标存储到vector中
    pixel_point.push_back(cv::Point2f(0,0));//将相应像素坐标系下的坐标存储到vector中
    

    3.定义相机的畸变矩阵和内参矩阵,并使用相应数据进行实例化。

    Mat camera_distortion_coefficients;//相机畸变系数矩阵
    Mat intrinsic_matrix;//内参矩阵
    intrinsic_matrix = (Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);//将内参元素存入Mat矩阵
    camera_distortion_coefficients = (Mat_<double>(1, 5) << k_1, k_2, p_1, p_2, k_3);//将畸变系数存入Mat矩阵
    

    4.使用函数solvePnP将世界坐标系下的三维点和像素坐标系下的二维点进行转化。

    Mat rvec, tvec;//存储旋转向量和平移向量
    bool ok = solvePnP(world_point, pixel_point, intrinsic_matrix, camera_distortion_coefficients, rvec, tvec, false, cv::SOLVEPNP_IPPE);//求解转化关系
    

    5.使用函数projectPoints将世界坐标系下的三维点转化为像素坐标系下的二维点。

    vector<Point3f> objectPoint;
    vector<Point2f> imagePoints;
    double a = 2.0, b = 3.0, c = 10.0; // 假设一个世界坐标系中的三维点坐标为(2, 3, 10)
    objectPoint.push_back(Point3f(a, b, c));//将世界坐标系下的坐标存储到vector中
    projectPoints(objectPoint, rvec, tvec, intrinsic_matrix, camera_distortion_coefficients, imagePoints);//求解像素坐标系下的对应两维点
    

    完整的代码示例如下:

    #include <iostream>
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        // 相机内参矩阵
        double fx = 1, fy = 1, cx = 1, cy = 1;//相机内参
        double k_1 = 0, k_2 = 0, p_1 = 0, p_2 = 0, k_3 = 0;//畸变系数
        Mat intrinsic_matrix = (Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);//内参矩阵
        Mat camera_distortion_coefficients = (Mat_<double>(1, 5) << k_1, k_2, p_1, p_2, k_3);//相机畸变矩阵
    
        //世界坐标系下的三维点(假设三维点坐标为(1,2,3))
        vector<Point3f> objectPoint;
        objectPoint.push_back(Point3f(1, 2, 3));
    
        // 将三维点以相机坐标系下的形式存放起来(即世界坐标系转为相机坐标系)
        vector<Point2f> imagePoints;
        Mat rvec, tvec;
        bool is_success = solvePnP(objectPoint, imagePoints, intrinsic_matrix, camera_distortion_coefficients, rvec, tvec, false, cv::SOLVEPNP_ITERATIVE);
    
        //将相应世界坐标系下的三维点转为像素坐标系下的二维点
        vector<Point2f> imagePoints2;
        projectPoints(objectPoint, rvec, tvec, intrinsic_matrix, camera_distortion_coefficients, imagePoints2);
    
        return 0;
    }
    

    需要注意的是,世界坐标系的拍摄场景应当是三维的,如拍摄物体等;如果拍摄场景为二维的,如平面图像等,则不需要进行世界坐标系到像素坐标系的转化,只需要进行像素坐标系的处理即可。