opencv中去畸变undistort()函数的坑

问题描述

原始图片可以正常读取,去除畸变后的图像是全黑的,如下图所示。
在这里插入图片描述
代码如下

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

using namespace std;
using namespace cv;

int main(int argc, char **argv) {
    Mat image = imread(argv[1], 0);              // 原图 0表示灰度图
    int rows = image.rows;
    int cols = image.cols;
    Mat image_undistort = Mat(rows, cols, CV_8UC1);                            // 去畸变后的图
   
    // 畸变参数
    double k1 = -0.28340811, k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05;
    // 畸变系数矩阵
    Mat distort_coeffs = Mat::zeros(1, 4, CV_32FC1);
    distort_coeffs.at<double>(0, 0) = k1;
    distort_coeffs.at<double>(0, 1) = k2;
    distort_coeffs.at<double>(0, 2) = p1;
    distort_coeffs.at<double>(0, 3) = p2;
    // 内参
    double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375;
    // 内参矩阵
    /**
     * fx 0  cx
     * 0  fy cy
     * 0  0  1
    */
    Mat k = Mat::eye(3, 3, CV_32FC1);
    k.at<double>(0, 0) = fx;
    k.at<double>(0, 2) = cx;
    k.at<double>(1, 1) = fy;
    k.at<double>(1, 2) = cy;

    cv::undistort(image, image_undistort, k, distort_coeffs);

    imshow("image", image);
    imshow("image_undistort", image_undistort);
    waitKey(0);

    return 0;
}

原因分析

虽然畸变参数k1, k2, p1, p2是double类型,我想当然地把他转换成畸变系数矩阵的时候给他设置的类型也是double,但很不幸结果就是图片全黑。同理内参矩阵也是如此。

把畸变系数矩阵和内参矩阵的数据类型改成float之后奇迹发生了,他可以正常显示去畸变后的图像了!

要说原因,是因为Mat中的数据默认是float类型的,还是之前的k,我输出了一下k中(0,0)位置的元素以及其数据类型,发现确实是float类型,代码和结果如下。

cout << k.at<float>(0, 0) << endl;
cout << (typeid(k.at<float>(0, 0)) == typeid(float)) << endl;

在这里插入图片描述
代码中先创建了0矩阵和对角阵,然后在此基础上填充畸变参数和内参数,若设置成double就会造成一个Mat中有两种数据类型,这时就起冲突了,当然会出现意想不到的错误,不幸的是编译器并没有给出错误信息。

解决方案

将矩阵k和distort_coeffs中要填充的数据类型改为float

	// 畸变系数矩阵
    Mat distort_coeffs = Mat::zeros(1, 4, CV_32FC1);
    distort_coeffs.at<float>(0, 0) = k1;
    distort_coeffs.at<float>(0, 1) = k2;
    distort_coeffs.at<float>(0, 2) = p1;
    distort_coeffs.at<float>(0, 3) = p2;
	// 内参矩阵
	Mat k = Mat::eye(3, 3, CV_32FC1);
    k.at<float>(0, 0) = fx;
    k.at<float>(0, 2) = cx;
    k.at<float>(1, 1) = fy;
    k.at<float>(1, 2) = cy;

然后奇迹发生了
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值