Opencv全向标定校正
Opencv Omnidirectional Calibration Rectification
我有一个广角镜头(>160 度)。我已经尝试过 Pinhole 和 Fisheye 模型,它们似乎提供了清晰的校正图像,但牺牲了一点 FOV。所以我决定尝试使用全向模型。
使用全向模型:
double rms = cv::omnidir::stereoCalibrate(Omni_L.RealP, Omni_L.ImageP, Omni_R.ImageP, Omni_L.img.size(), Omni_R.img.size(), K1, xi1, D1, K2, xi2, D2, rvec, tvec, rvecsL, tvecsL, flags, critia);
std::cout << "RMS : " << rms << std::endl;
我在立体校准后得到以下结果
RMS : 0.527522
Camera_Matrix1 :
[773.9380049495828, 0, 394.6697338356358;
0, 776.2094223216956, 382.016762545214;
0, 0, 1]
Xi-1 :[1.804945374650817]
Distortion Parameters1:
[0, 0, -0.009983732008104793, -0.004530718062523464]
Camera_Matrix2:
[783.1807043871861, 0, 393.2120687911561;
0, 784.4790955477508, 386.7954078861521;
0, 0, 1]
Xi-2 :[1.837909340970556]
Distortion Parameters2:
[0, 0, -0.009779422171305124, -0.003723193186299092]
rvec :[-0.003821627764900316;
0.005567569400892289;
0.001491183114878044]
tvec:[-63.09243360480385;
0.1195353275271446;
0.9082801155496641]
R:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
P:
[773.9380049495828, 0, 394.6697338356358;
0, 776.2094223216956, 382.016762545214;
0, 0, 1]
然后我做不失真:
cv::Mat R = cv::Mat::eye(3, 3, CV_32FC1);
cv::Mat Mapx, Mapy;
cv::Mat P(3, 3, CV_32FC1);
P = K1;
cv::Mat orid = cv::imread("Left\1.jpg");
std::cout << orid.size();
std::cout << "R : "<<R<<std::endl;
std::cout << "P : " << P << std::endl;
cv::Size s= orid.size();
try {
cv::omnidir::initUndistortRectifyMap(K1, D1, xi1, R, P, s, CV_32FC1, Mapx, Mapy, cv::omnidir::RECTIFY_PERSPECTIVE);// Knew, new_size);
cv::remap(orid, DC, Mapx, Mapy, cv::INTER_CUBIC);
}
catch (cv::Exception & e)
{
std::cerr << e.msg << std::endl; // output exception message
}
std::string Save_Original = "Distorted_Original" + std::to_string(10) + EXT;
cv::imwrite(Save_Original, orid);
std::string Save_Corrected = "Distorted_Corrected" + std::to_string(10) + EXT;
cv::imwrite(Save_Corrected, DC);
问题一:
为什么径向畸变为零?
问题二:
经过校正的无失真图像的输出大大降低了 FOV。我的代码有问题吗?
原图:
失真校正图像:
问题三:
cv::omnidir::initUndistortRectifyMap()函数中的P和R有什么作用?
问题四:
需要关于如何通过全向校准获得具有更多 FoV 的良好校正图像的想法?
Post 试验:
@sushi(在下面评论)建议尝试 RECTIFY_CYLINDRICAL 相同的图像,下面是结果:
cv::omnidir::RECTIFY_CYLINDRICAL
-> 结果更差
首先我推荐你阅读这个教程:https://docs.opencv.org/master/dd/d12/tutorial_omnidir_calib_main.html
回答您的问题:
- 失真系数取决于您选择的失真模型。
- 看教程(图像校正部分),如果你想保留所有fov,你必须将标志更改为RECTIFY_CYLINDRICAL
- P是"new"校正后图像的相机矩阵,R是原图和物体之间的旋转变换space。如果您使用 cv::omnidir::undistortImage 消除图像失真,则可以跳过这两个参数。查看有关 knew.
的推荐值的教程
- 看第2点的答案。
这是我使用RECTIFY_PERSPECTIVE的方法的结果,我不知道为什么RECTIFY_CYLINDRICAL在这种情况下不起作用:
要实现它,只需像这样取消扭曲您的图像:
cv::Size s = orid.size();
cv::Mat Knew = cv::Mat(cv::Matx33f(s.width / 4, 0, s.width / 2,
0, s.height / 4, s.width / 2,
0, 0, 1));
cv::MAt undistorted;
cv::omnidir::undistortImage(orid, undistorted, K1, D1, xi1, cv::omnidir::RECTIFY_PERSPECTIVE, Knew, orid.size());
我有一个广角镜头(>160 度)。我已经尝试过 Pinhole 和 Fisheye 模型,它们似乎提供了清晰的校正图像,但牺牲了一点 FOV。所以我决定尝试使用全向模型。
使用全向模型:
double rms = cv::omnidir::stereoCalibrate(Omni_L.RealP, Omni_L.ImageP, Omni_R.ImageP, Omni_L.img.size(), Omni_R.img.size(), K1, xi1, D1, K2, xi2, D2, rvec, tvec, rvecsL, tvecsL, flags, critia);
std::cout << "RMS : " << rms << std::endl;
我在立体校准后得到以下结果
RMS : 0.527522
Camera_Matrix1 :
[773.9380049495828, 0, 394.6697338356358;
0, 776.2094223216956, 382.016762545214;
0, 0, 1]
Xi-1 :[1.804945374650817]
Distortion Parameters1:
[0, 0, -0.009983732008104793, -0.004530718062523464]
Camera_Matrix2:
[783.1807043871861, 0, 393.2120687911561;
0, 784.4790955477508, 386.7954078861521;
0, 0, 1]
Xi-2 :[1.837909340970556]
Distortion Parameters2:
[0, 0, -0.009779422171305124, -0.003723193186299092]
rvec :[-0.003821627764900316;
0.005567569400892289;
0.001491183114878044]
tvec:[-63.09243360480385;
0.1195353275271446;
0.9082801155496641]
R:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
P:
[773.9380049495828, 0, 394.6697338356358;
0, 776.2094223216956, 382.016762545214;
0, 0, 1]
然后我做不失真:
cv::Mat R = cv::Mat::eye(3, 3, CV_32FC1);
cv::Mat Mapx, Mapy;
cv::Mat P(3, 3, CV_32FC1);
P = K1;
cv::Mat orid = cv::imread("Left\1.jpg");
std::cout << orid.size();
std::cout << "R : "<<R<<std::endl;
std::cout << "P : " << P << std::endl;
cv::Size s= orid.size();
try {
cv::omnidir::initUndistortRectifyMap(K1, D1, xi1, R, P, s, CV_32FC1, Mapx, Mapy, cv::omnidir::RECTIFY_PERSPECTIVE);// Knew, new_size);
cv::remap(orid, DC, Mapx, Mapy, cv::INTER_CUBIC);
}
catch (cv::Exception & e)
{
std::cerr << e.msg << std::endl; // output exception message
}
std::string Save_Original = "Distorted_Original" + std::to_string(10) + EXT;
cv::imwrite(Save_Original, orid);
std::string Save_Corrected = "Distorted_Corrected" + std::to_string(10) + EXT;
cv::imwrite(Save_Corrected, DC);
问题一:
为什么径向畸变为零?
问题二:
经过校正的无失真图像的输出大大降低了 FOV。我的代码有问题吗?
原图:
问题三:
cv::omnidir::initUndistortRectifyMap()函数中的P和R有什么作用?
问题四:
需要关于如何通过全向校准获得具有更多 FoV 的良好校正图像的想法?
Post 试验:
@sushi(在下面评论)建议尝试 RECTIFY_CYLINDRICAL 相同的图像,下面是结果:
cv::omnidir::RECTIFY_CYLINDRICAL
-> 结果更差
首先我推荐你阅读这个教程:https://docs.opencv.org/master/dd/d12/tutorial_omnidir_calib_main.html 回答您的问题:
- 失真系数取决于您选择的失真模型。
- 看教程(图像校正部分),如果你想保留所有fov,你必须将标志更改为RECTIFY_CYLINDRICAL
- P是"new"校正后图像的相机矩阵,R是原图和物体之间的旋转变换space。如果您使用 cv::omnidir::undistortImage 消除图像失真,则可以跳过这两个参数。查看有关 knew. 的推荐值的教程
- 看第2点的答案。
这是我使用RECTIFY_PERSPECTIVE的方法的结果,我不知道为什么RECTIFY_CYLINDRICAL在这种情况下不起作用:
cv::Size s = orid.size();
cv::Mat Knew = cv::Mat(cv::Matx33f(s.width / 4, 0, s.width / 2,
0, s.height / 4, s.width / 2,
0, 0, 1));
cv::MAt undistorted;
cv::omnidir::undistortImage(orid, undistorted, K1, D1, xi1, cv::omnidir::RECTIFY_PERSPECTIVE, Knew, orid.size());