【opencv】相机标定之畸变矫正与反畸变计算

原博客地址:https://www.cnblogs.com/mafuqiang/p/8134617.html

添加使用的例子:
myUndistortPointsFun.h

#if !defined(MYUNDISTORTPOINTSFUN)
#define MYUNDISTORTPOINTSFUN

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

// 去畸变
void myUndistortPoints(const std::vector<cv::Point2d> &src, std::vector<cv::Point2d> &dst,
                       const cv::Mat &cameraMatrix, const cv::Mat &distortionCoeff);

// 使畸变
void myDistortPoints(const std::vector<cv::Point2d> &src, std::vector<cv::Point2d> &dst,
                     const cv::Mat &cameraMatrix, const cv::Mat &distortionCoeff);

#endif // MYUNDISTORTPOINTSFUN

myUndistortPointsFun.cpp

#include "myUndistortPointsFun.h"


//https://www.cnblogs.com/mafuqiang/p/8134617.html 

void myUndistortPoints(const std::vector<cv::Point2d> & src, std::vector<cv::Point2d> & dst,
    const cv::Mat & cameraMatrix, const cv::Mat & distortionCoeff)
{

    dst.clear();
    double fx = cameraMatrix.at<double>(0, 0);
    double fy = cameraMatrix.at<double>(1, 1);
    double ux = cameraMatrix.at<double>(0, 2);
    double uy = cameraMatrix.at<double>(1, 2);

    double k1 = distortionCoeff.at<double>(0, 0);
    double k2 = distortionCoeff.at<double>(0, 1);
    double p1 = distortionCoeff.at<double>(0, 2);
    double p2 = distortionCoeff.at<double>(0, 3);
    double k3 = distortionCoeff.at<double>(0, 4);
    double k4;
    double k5;
    double k6;

    for (unsigned int i = 0; i < src.size(); i++)
    {
        const cv::Point2d & p = src[i];
        // 首先进行坐标转换;
        double xDistortion = (p.x - ux) / fx;
        double yDistortion = (p.y - uy) / fy;

        double xCorrected, yCorrected;

        double x0 = xDistortion;
        double y0 = yDistortion;
        // 这里使用迭代的方式进行求解,因为根据2中的公式直接求解是困难的,所以通过设定初值进行迭代,这也是OpenCV的求解策略;
        for (int j = 0; j < 10; j++)
        {
            double r2 = xDistortion*xDistortion + yDistortion*yDistortion;

            double distRadialA = 1 / (1. + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2);
            double distRadialB = 1. + k4 * r2 + k5 * r2 * r2 + k6 * r2 * r2 * r2;

            double deltaX = 2. * p1 * xDistortion * yDistortion + p2 * (r2 + 2. * xDistortion * xDistortion);
            double deltaY = p1 * (r2 + 2. * yDistortion * yDistortion) + 2. * p2 * xDistortion * yDistortion;

            xCorrected = (x0 - deltaX)* distRadialA * distRadialB;
            yCorrected = (y0 - deltaY)* distRadialA * distRadialB;

            xDistortion = xCorrected;
            yDistortion = yCorrected;
        }
        // 进行坐标变换;
        xCorrected = xCorrected * fx + ux;
        yCorrected = yCorrected * fy + uy;

        dst.push_back(cv::Point2d(xCorrected, yCorrected));
    }

}

void myDistortPoints(const std::vector<cv::Point2d> & src, std::vector<cv::Point2d> & dst,
    const cv::Mat & cameraMatrix, const cv::Mat & distortionCoeff)
{

    dst.clear();
    double fx = cameraMatrix.at<double>(0, 0);
    double fy = cameraMatrix.at<double>(1, 1);
    double ux = cameraMatrix.at<double>(0, 2);
    double uy = cameraMatrix.at<double>(1, 2);

    double k1 = distortionCoeff.at<double>(0, 0);
    double k2 = distortionCoeff.at<double>(0, 1);
    double p1 = distortionCoeff.at<double>(0, 2);
    double p2 = distortionCoeff.at<double>(0, 3);
    double k3 = distortionCoeff.at<double>(0, 4);
    double k4;//
    double k5;//
    double k6;//

    for (unsigned int i = 0; i < src.size(); i++)
    {
        const cv::Point2d & p = src[i];
//      //获取的点通常是图像的像素点,所以需要先通过小孔相机模型转换到归一化坐标系下;
        double xCorrected = (p.x - ux) / fx;
        double yCorrected = (p.y - uy) / fy;

        double xDistortion, yDistortion;
//       //我们已知的是经过畸变矫正或理想点的坐标;
        double r2 = xCorrected*xCorrected + yCorrected*yCorrected;

        double deltaRa = 1. + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2;
        double deltaRb = 1 / (1. + k4 * r2 + k5 * r2 * r2 + k6 * r2 * r2 * r2);
        double deltaTx = 2. * p1 * xCorrected * yCorrected + p2 * (r2 + 2. * xCorrected * xCorrected);
        double deltaTy = p1 * (r2 + 2. * yCorrected * yCorrected) + 2. * p2 * xCorrected * yCorrected;
//      //下面为畸变模型;
        xDistortion = xCorrected * deltaRa * deltaRb + deltaTx;
        yDistortion = yCorrected * deltaRa * deltaRb + deltaTy;
//      //最后再次通过相机模型将归一化的坐标转换到像素坐标系下;
        xDistortion = xDistortion * fx + ux;
        yDistortion = yDistortion * fy + uy;

        dst.push_back(cv::Point2d(xDistortion, yDistortion));
    }

}

main.cpp

#include "myFunction/myUndistortPointsFun.h"

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    Mat background(Size(640, 640), CV_32FC3);
    Mat background2(Size(640, 640), CV_32FC3);
    Mat background3(Size(640, 640), CV_32FC3);

    imshow("background", background);
    vector<Point2d> line1;
    for (int j = 1; j < 9; j++)
    {
        for (int i = 10; i < 595; i++)
        {
            Point2d point(i, j * 50);
            line1.push_back(point);
        }
    }

    for (int i = 0; i < line1.size(); i++)
    {
        circle(background, line1[i], 1, Scalar(0, 0, 255), 1);
    }
    imshow("raw Points", background);

    // 相机内参
    Mat cameraMatrix = (Mat_<double>(3, 3) << 1229.210153358364, 0, 327.2633377834179,
                        0, 1230.528779625332, 214.8751296839213,
                        0, 0, 1);
    // 畸变矩阵
    Mat distCoeffs = (Mat_<double>(1, 5) << 0.8649656251092355, -34.57804001012766, 0.002187083265654973, 0.008358950285400273, 389.8609987216533);

    // 去畸变
    vector<Point2d> line2;
    myUndistortPoints(line1, line2, cameraMatrix, distCoeffs); // 使用去畸变校正函数
    for (int i = 0; i < line2.size(); i++)
    {
        circle(background2, line2[i], 1, Scalar(0, 0, 255), 1);
    }
    imshow("myUndistortPoints Points", background2);

    // 使畸变
    vector<Point2d> line3;
    myDistortPoints(line2, line3, cameraMatrix, distCoeffs); // 使畸变
    cout << line3.size() << endl;
    for (int i = 0; i < line3.size(); i++)
    {
        circle(background3, line3[i], 1, Scalar(0, 0, 255), 1);
    }
    imshow("mydistortPoints Points", background3);

    waitKey(0);
    return 0;
}
posted @ 2022-08-09 14:06  乞力马扎罗山的雪  阅读(1121)  评论(0编辑  收藏  举报