【笔记】关于OpenCV中的去畸变代码

https://zhuanlan.zhihu.com/p/137053640

https://xgyopen.github.io/2018/12/06/2018-12-06-imv-calibrate-camera/

在opencv中,有关图像或像素点(角点)去畸变的函数有
cv::undistort(),
cv::getOptimalNewCameraMatrix(),
cv::initUndistortRectifyMap(),
cv::remap()
cv::undistortPoints()。

  • 其中undistort可以直接对图像去畸变,
  • getOptimalNewCameraMatrix、initUndistortRectifyMap和remap配合也可以对图像去畸变,他们之间有相同之处,又有各自特性
  • 而undistortPoints是只针对像素点去畸变。

下面就使用方法及细节进行梳理,并给出代码示例,以便加深印象。

通用畸变去除流程:

步骤:
cv::getOptimalNewCameraMatrix()(根据根据比例因子返回相应的新的相机内参矩阵)
-----> cv::initUndistortRectifyMap()(计算原始图像和矫正图像之间的转换关系)
-----> cv::remap()(把原始图像中某位置的像素映射到矫正后的图像指定位置)

一步到位

cv::getOptimalNewCameraMatrix()
----> cv::undistort()(其内部调用了initUndistortRectifyMap和remap函数。)

代码示例

使用 undistort 矫正图像

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

using namespace std;

int main()
{
    const cv::Mat K = ( cv::Mat_<double> ( 3,3 ) << 931.73, 0.0, 480.0, 0.0, 933.16, 302.0, 0.0, 0.0, 1.0 );
    const cv::Mat D = ( cv::Mat_<double> ( 5,1 ) << -1.7165e-1, 1.968259e-1, 0.0, 0.0, -3.639514e-1 );

    const string str = "/home/jiang/4_learn/WeChatCode/ImageUndistort/data/";
    const int nImage = 5;
    const int ImgWidth = 960;
    const int ImgHeight = 640;

    cv::Mat map1, map2;
    cv::Size imageSize(ImgWidth, ImgHeight);
    const double alpha = 1;
    cv::Mat NewCameraMatrix = getOptimalNewCameraMatrix(K, D, imageSize, alpha, imageSize, 0);

    for(int i=0; i<nImage; i++)
    {
        string InputPath = str + to_string(i) + ".png";
        cv::Mat RawImage = cv::imread(InputPath);
        cv::imshow("RawImage", RawImage);

        cv::Mat UndistortImage;
        cv::undistort(RawImage, UndistortImage, K, D, K);
//        cv::undistort(RawImage, UndistortImage, K, D, NewCameraMatrix);
        cv::imshow("UndistortImage", UndistortImage);

        string OutputPath = str + to_string(i) + "_un2" + ".png";
        cv::imwrite(OutputPath, UndistortImage);
        cv::waitKey(0);
    }

    return 0;
}

缺点:
如果有多个图片需要矫正,那么不推荐使用cv::undistort的方法,因为initUndistortRectifyMap函数本来只需要计算一次就行,但cv::undistort需要每次循环都计算。所以相当于你n张图像计算了n次initUndistortRectifyMap,这会大大降低效率,增加程序耗时。

使用 getOptimalNewCameraMatrix + initUndistortRectifyMap + remap 矫正图像

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

using namespace std;

int main()
{
    const cv::Mat K = ( cv::Mat_<double> ( 3,3 ) << 931.73, 0.0, 480.0, 0.0, 933.16, 302.0, 0.0, 0.0, 1.0 ); // 相机内参矩阵
    const cv::Mat D = ( cv::Mat_<double> ( 5,1 ) << -1.7165e-1, 1.968259e-1, 0.0, 0.0, -3.639514e-1 ); // 相机畸变参数

    const string str = "/home/jiang/4_learn/WeChatCode/ImageUndistort/data/";
    const int nImage = 5;
    const int ImgWidth = 960;
    const int ImgHeight = 640;

    cv::Mat map1, map2;
    cv::Size imageSize(ImgWidth, ImgHeight);
    const double alpha = 1;
    cv::Mat NewCameraMatrix = getOptimalNewCameraMatrix(K, D, imageSize, alpha, imageSize, 0);
    initUndistortRectifyMap(K, D, cv::Mat(), NewCameraMatrix, imageSize, CV_16SC2, map1, map2);

    for(int i=0; i<nImage; i++)
    {
        string InputPath = str + to_string(i) + ".png";
        cv::Mat RawImage = cv::imread(InputPath);
        cv::imshow("RawImage", RawImage);

        cv::Mat UndistortImage;
        remap(RawImage, UndistortImage, map1, map2, cv::INTER_LINEAR);
        cv::imshow("UndistortImage", UndistortImage);

        string OutputPath = str + to_string(i) + "_un" + ".png";
        cv::imwrite(OutputPath, UndistortImage);
        cv::waitKey(0);
    }

    return 0;
}

当alpha=1时,所有像素均保留,但存在黑色边框。

当alpha=0时,损失最多的像素,没有黑色边框。

参考

https://zhuanlan.zhihu.com/p/137053640

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值