鱼眼畸变校正
Fisheye distortion correction
我在这个 link http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/ 上看到了一种消除鱼眼镜头畸变的算法,我尝试用 opencv 在 C++ 中实现它。当参数强度接近于零时,输出图像与输入图像完全相同,而我得到的值较高时效果不佳。如果有人知道可能是什么问题(在我的代码中,或者更一般地说,在算法中),那将非常有帮助。
非常感谢。
#include "opencv2\core\core.hpp"
#include "opencv2\highgui\highgui.hpp"
#include "opencv2\calib3d\calib3d.hpp"
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
int main() {
cout << " Usage: display_image ImageToLoadAndDisplay" << endl;
Mat_<Vec3b> eiffel;
eiffel = imread("C:/Users/Administrator/Downloads/TestFisheye.jpg", CV_LOAD_IMAGE_COLOR); // Read the file
if (!eiffel.data) // Check for invalid input
{
cout << "Could not open or find the image" << endl;
return -1;
}
cout << "Input image depth: " << eiffel.depth() << endl;
namedWindow("Display window", WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", eiffel); // Show our image inside it.
//waitKey(0); // Wait for a keystroke in the window
int halfWidth = eiffel.rows / 2;
int halfHeight = eiffel.cols / 2;
double strength = 0.0001;
double correctionRadius = sqrt(pow(eiffel.rows, 2) + pow(eiffel.cols, 2)) / strength;
Mat_<Vec3b> dstImage = eiffel;
int newX, newY;
double distance;
double theta;
int sourceX;
int sourceY;
double r;
for (int i = 0; i < dstImage.rows; ++i)
{
for (int j = 0; j < dstImage.cols; j++)
{
newX = i - halfWidth;
newY = j - halfHeight;
distance = sqrt(pow(newX, 2) + pow(newY, 2));
r = distance / correctionRadius;
if (r == 0.0)
theta = 1;
else
theta = atan(r) / r;
sourceX = round(halfWidth + theta*newX);
sourceY = round(halfHeight + theta * newY);
dstImage(i, j)[0] = eiffel(sourceX, sourceY)[0];
dstImage(i, j)[1] = eiffel(sourceX, sourceY)[1];
dstImage(i, j)[2] = eiffel(sourceX, sourceY)[2];
}
}
namedWindow("Display window 2", WINDOW_AUTOSIZE);
imshow("Display window 2", dstImage); // Show our image inside it.
waitKey(0);
return 0;
}
PS:我目前正在处理 link 中发布的第一张图片。
这里有 2 个问题:
1 - 您需要将强度从 0.0001 增加到更合理的值(尝试 5)。
2 - 您使用的是相同的起点和终点矩阵。 Mat_<Vec3b> dstImage = eiffel;
实际上并没有分配任何新内存。 dstImage
只是指向原始图像的智能指针。所以当你修改它的时候,你同时也在修改源图像。这会给你带来非常糟糕的结果。而是 Mat_<Vec3b> dstImage = eiffel.clone()
通过这些更改,我得到了下图:
不是很好,但至少快速和简单。
我在这个 link http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/ 上看到了一种消除鱼眼镜头畸变的算法,我尝试用 opencv 在 C++ 中实现它。当参数强度接近于零时,输出图像与输入图像完全相同,而我得到的值较高时效果不佳。如果有人知道可能是什么问题(在我的代码中,或者更一般地说,在算法中),那将非常有帮助。 非常感谢。
#include "opencv2\core\core.hpp"
#include "opencv2\highgui\highgui.hpp"
#include "opencv2\calib3d\calib3d.hpp"
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
int main() {
cout << " Usage: display_image ImageToLoadAndDisplay" << endl;
Mat_<Vec3b> eiffel;
eiffel = imread("C:/Users/Administrator/Downloads/TestFisheye.jpg", CV_LOAD_IMAGE_COLOR); // Read the file
if (!eiffel.data) // Check for invalid input
{
cout << "Could not open or find the image" << endl;
return -1;
}
cout << "Input image depth: " << eiffel.depth() << endl;
namedWindow("Display window", WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", eiffel); // Show our image inside it.
//waitKey(0); // Wait for a keystroke in the window
int halfWidth = eiffel.rows / 2;
int halfHeight = eiffel.cols / 2;
double strength = 0.0001;
double correctionRadius = sqrt(pow(eiffel.rows, 2) + pow(eiffel.cols, 2)) / strength;
Mat_<Vec3b> dstImage = eiffel;
int newX, newY;
double distance;
double theta;
int sourceX;
int sourceY;
double r;
for (int i = 0; i < dstImage.rows; ++i)
{
for (int j = 0; j < dstImage.cols; j++)
{
newX = i - halfWidth;
newY = j - halfHeight;
distance = sqrt(pow(newX, 2) + pow(newY, 2));
r = distance / correctionRadius;
if (r == 0.0)
theta = 1;
else
theta = atan(r) / r;
sourceX = round(halfWidth + theta*newX);
sourceY = round(halfHeight + theta * newY);
dstImage(i, j)[0] = eiffel(sourceX, sourceY)[0];
dstImage(i, j)[1] = eiffel(sourceX, sourceY)[1];
dstImage(i, j)[2] = eiffel(sourceX, sourceY)[2];
}
}
namedWindow("Display window 2", WINDOW_AUTOSIZE);
imshow("Display window 2", dstImage); // Show our image inside it.
waitKey(0);
return 0;
}
PS:我目前正在处理 link 中发布的第一张图片。
这里有 2 个问题:
1 - 您需要将强度从 0.0001 增加到更合理的值(尝试 5)。
2 - 您使用的是相同的起点和终点矩阵。 Mat_<Vec3b> dstImage = eiffel;
实际上并没有分配任何新内存。 dstImage
只是指向原始图像的智能指针。所以当你修改它的时候,你同时也在修改源图像。这会给你带来非常糟糕的结果。而是 Mat_<Vec3b> dstImage = eiffel.clone()
通过这些更改,我得到了下图:
不是很好,但至少快速和简单。