我已经完成了一些示例程序,可以消除棋盘上的镜头失真,就像鱼眼图像一样,它可以正常工作,这是屏幕截图
接下来我想使用鱼眼棋盘图案(右上图)以消除相同的镜头失真但是从真实图像中没有运气 - 曲面仍然保留在未失真的图像上, 因此我得到了这个
代码
void getObjectPoints(cv::Size, std::vector<std::vector<cv::Point3f>>&);
bool getImagePoints(cv::Mat&, cv::Size&, std::vector<std::vector<cv::Point2f>>&);
void runCalibration(cv::Mat& image, cv::Matx33d&, cv::Vec4d&);
cv::Mat removeFisheyeLensDist(cv::Mat&, cv::Matx33d&, cv::Vec4d&);
// ... definitions
void getObjectPoints(cv::Size patternSize, std::vector<std::vector<cv::Point3f>>& objectPoints)
{
const float squareSize = 0.0015f;
std::vector<cv::Point3f> knownBoardPositions;
for (int i = 0; i < patternSize.height; ++i)
{
for (int j = 0; j < patternSize.width; ++j)
{
knownBoardPositions.push_back(cv::Point3f(j*squareSize, i*squareSize, 0.0f));
}
}
if (knownBoardPositions.size() > 0)
objectPoints.push_back(knownBoardPositions);
}
bool getImagePoints(cv::Mat& image, cv::Size& patternSize, std::vector<std::vector<cv::Point2f>>& imagePoints)
{
bool patternFound = false;
while (!patternFound)
{
std::vector<cv::Point2f> corners;
for (int i = 7; i <= 30; ++i)
{
int w = i;
int h = i - 2;
patternFound = cv::findChessboardCorners(image, cv::Size(w, h), corners,
cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE);
if (patternFound)
{
patternSize.width = w;
patternSize.height = h;
imagePoints.push_back(corners);
break;
}
}
}
return patternFound;
}
void runCalibration(cv::Mat& image, cv::Matx33d& K, cv::Vec4d& D)
{
std::vector< std::vector<cv::Point2f> > imagePoints;
std::vector< std::vector<cv::Point3f> > objectPoints;
cv::Size patternSize;
bool patternFound = getImagePoints(image, patternSize, imagePoints);
if (patternFound)
{
getObjectPoints(patternSize, objectPoints);
std::vector<cv::Vec3d> rvecs;
std::vector<cv::Vec3d> tvecs;
cv::fisheye::calibrate(
objectPoints,
imagePoints,
image.size(),
K,
D,
rvecs,
tvecs,
cv::fisheye::CALIB_FIX_SKEW | cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC
| cv::fisheye::CALIB_FIX_K1 | cv::fisheye::CALIB_FIX_K2
| cv::fisheye::CALIB_FIX_K3 | cv::fisheye::CALIB_FIX_K4
// cv::TermCriteria(3, 20, 1e-6)
);
}
}
cv::Mat removeFisheyeLensDist(cv::Mat& distorted, cv::Matx33d& K, cv::Vec4d& D)
{
cv::Mat undistorted;
cv::Matx33d newK = K;
cv::fisheye::undistortImage(distorted, undistorted, K, D, newK);
return undistorted;
}
int main(int argc, char* argv[])
{
cv::Mat chessBoardPattern = //..
cv::Mat distortedImage = //...
cv::imshow("distorted", distortedImage);
cv::Matx33d K; cv::Vec4d D;
runCalibration(chessBoardPattern, K, D);
cv::Mat undistoredImage = removeFisheyeLensDist(distortedImage, K, D);
cv::imshow("undistored", undistoredImage);
cv::waitKey(0);
return 0;
}
我认为塔的图像在右边有一个非常类似于棋盘的曲线,所以相同的图案应该适用于塔图像......
我在那里做错了什么? 为什么它没有修复塔形图像的镜头失真?
答案 0 :(得分:3)
不幸的是你的假设
如果图像具有相同的曲率,那么相机参数应该大致相同,因此我可以用棋盘图案来展现鱼眼图像
错了。即使相同型号的相机也会在焦距,镜头几何形状和位置等方面存在差异,需要单独校准。除了在使用相机时,这些参数可能会因加热,振动和其他影响而改变(通常在实践中忽略这一点)。
要在不使用相机的情况下取消图像,您只需选择一些简单的鱼眼相机模型并尝试手动估计参数,尝试使直线看起来笔直(例如使用带滑块的GUI用于所有参数)。这可能很乏味,但我不知道更好的选择。此外,一些图像编辑软件可能有工具(如果我没记错GIMP)