法一: 使用 getOptimalNewCameraMatrix + initUndistortRectifyMap + remap 矯正圖像
函數解析:
1、cv::getOptimalNewCameraMatrix()
“Return the new camera matrix based on the free scaling parameter”,即根據根據比例因子傳回相應的新的相機内參矩陣。
Mat cv::getOptimalNewCameraMatrix
(
InputArray cameraMatrix, // 相機内參矩陣
InputArray distCoeffs, // 相機畸變參數
Size imageSize, // 圖像尺寸
double alpha, // 縮放比例
//當alpha=1時,所有像素均保留,但存在黑色邊框。
//當alpha=0時,損失最多的像素,沒有黑色邊框。
Size newImgSize = Size(), // 校正後的圖像尺寸
Rect * validPixROI = 0, // 輸出感興趣區域設定
bool centerPrincipalPoint = false // 可選标志
)
1.1相機内參矩陣:
fx, fy:使用像素來描述x, y軸方向焦距的長度, 機關像素
cx,cy,主點的實際位置,機關也是像素。
指派方法:
//fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375;
const cv::Mat K = (cv::Mat_<double>(3,3) << 458.654, 0,367.215, 0, 457.296, 248.375, 0,0,1);
1.2相機畸變參數:
5個畸變參數D:k1 , k2 , k3 , p1 , p2
指派方法:
//k1 = -0.28340811, k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05;
const cv::Mat D = (cv::Mat_<double> ( 5,1 ) << -0.28340811, 0.07395907, 0.0, 0.00019359, 1.76187114e-05);
2、 cv::initUndistortRectifyMap()
用于計算原始圖像和矯正圖像之間的轉換關系,将結果以映射的形式表達,映射關系存儲在map1和map2中。
void cv::initUndistortRectifyMap
(
InputArray cameraMatrix, // 原相機内參矩陣
InputArray distCoeffs, // 原相機畸變參數
InputArray R, // 可選的修正變換矩陣
InputArray newCameraMatrix, // 新相機内參矩陣
Size size, // 去畸變後圖像的尺寸
int m1type, // 第一個輸出的映射(map1)的類型,CV_32FC1 or CV_16SC2
OutputArray map1, // 第一個輸出映射
OutputArray map2 // 第二個輸出映射
)
3、 cv::remap()
把原始圖像中某位置的像素映射到矯正後的圖像指定位置。
void cv::remap
(
InputArray src, // 原始圖像
OutputArray dst, // 矯正圖像
InputArray map1, // 第一個映射
InputArray map2, // 第二個映射
int interpolation, // 插值方式
int borderMode=BORDER_CONSTANT, // 邊界模式
const Scalar& borderValue=Scalar() // 邊界顔色,預設Scalar()黑色
)
法一 完整代碼:
//
// Created by daybeha on 2021/9/20.
//
//https://zhuanlan.zhihu.com/p/137053640
#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 );
// 内參
// double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375;
const cv::Mat K = (cv::Mat_<double>(3,3) << 458.654, 0,367.215, 0, 457.296, 248.375, 0,0,1);
// 畸變參數
// double k1 = -0.28340811, k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05;
const cv::Mat D = (cv::Mat_<double> ( 5,1 ) << -0.28340811, 0.07395907, 0.0, 0.00019359, 1.76187114e-05);
const string str = "/home/daybeha/Documents/My Codes/Visual Slam/learning code/ch5/imageBasics/";
const int nImage = 5;
// const int nImage = 1;
// const int ImgWidth = 752;
// const int ImgHeight = 480;
//
// cv::Mat map1, map2;
// cv::Size imageSiz(ImgWidth, ImgHeight);
// const double alpha = 1;
cv::Mat map1, map2;
cv::Mat image = cv::imread("../../imageBasics/distorted.png");
int rows = image.rows, clos = image.cols;
cv::Size imageSize(clos, rows);
// 當alpha=1時,所有像素均保留,但存在黑色邊框
// 當alpha=0時,損失最多的像素,沒有黑色邊框
// const double alpha = 1;
const double alpha = 0; //
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);
// }
cv::imshow("Distorted Image", image);
cv::Mat UndistortImage;
remap(image, UndistortImage, map1, map2, cv::INTER_LINEAR);
cv::imshow("UndistortImage", UndistortImage);
// string OutputPath = str + to_string(i) + "_un" + ".png";
// cv::imwrite(OutputPath, UndistortImage);
string OutputPath = "../../imageBasics/undistorted.png";
cv::imwrite(OutputPath, UndistortImage);
cv::waitKey(0);
return 0;
}
法二:使用 undistort()
未完待續……
法三: 手動實作
先看SLAM十四講中的相關講解
……
參考
關于OpenCV中的去畸變
相機标定——相機的内參矩陣IntrinsicMatrix參數解釋
Step1:模型 16個相機參數(内參、外參、畸變參數)
視覺SLAM十四講(第二版)