优化相机参数并计算误差 - OpenCV

9
我一直在尝试使用CvLevMarq来优化我的相机参数,但是阅读相关文献后发现它会导致结果不稳定,而我正在经历这种情况。我了解了其他替代方案,并找到了使用EIGEN的该库this library
然而,上述库似乎使用了一个不支持OpenCV的拼接类,可能需要我将其移植到OpenCV中。
在继续之前,考虑到这可能不是一项容易的任务,我想先问问周围是否有其他人遇到过同样的问题?
我目前正在使用:
1. 使用FASTFeatureDetector计算特征
Ptr<FeatureDetector> detector = new FastFeatureDetector(5,true);
detector->detect(firstGreyImage, features_global[firstImageIndex].keypoints); // Previous picture
detector->detect(secondGreyImage, features_global[secondImageIndex].keypoints); // New picture

2. 使用SIFTDescriptorExtractor提取特征

Ptr<SiftDescriptorExtractor> extractor = new SiftDescriptorExtractor();
extractor->compute(firstGreyImage, features_global[firstImageIndex].keypoints, features_global[firstImageIndex].descriptors); // Previous Picture
extractor->compute(secondGreyImage, features_global[secondImageIndex].keypoints, features_global[secondImageIndex].descriptors); // New Picture

3. 使用BestOf2NearestMatcher进行特征匹配

vector<MatchesInfo> pairwise_matches;
BestOf2NearestMatcher matcher(try_use_gpu, 0.50f);
matcher(features_global, pairwise_matches);
matcher.collectGarbage();

4. 从设备传递的CameraParams.R四元数(略微不准确,导致问题)

5. CameraParams.Focal == 389.0f -- 尝试了不同的值,389.0f是唯一与图像水平匹配但垂直不匹配的值。

6. Bundle AdjustmentcvLevMarqcalcError & calcJacobian

Ptr<BPRefiner> adjuster = new BPRefiner();
adjuster->setConfThresh(0.80f);
adjuster->setMaxIterations(5);
(*adjuster)(features,pairwise_matches,cameras);

7. 曝光补偿器 (增益)

8. OpenCV 多频带混合器

目前的进展:

  • 接缝查找器 - 在某种程度上有效,但它取决于cvLevMarq算法的结果。也就是说,如果算法不正确,seamFinder也会失效。

  • 基于单应性估计器非常有效。然而,由于它“依赖”于特征,所以不幸的是这不是我正在寻找的方法。

我不想依赖于特征,因为我已经有了矩阵,如果有一种方法可以“优化”当前的矩阵,那么这将是预期的结果。

目前的结果:

cvLevMarq “俄罗斯轮盘” 6/10:

这就是我想要实现的10/10次效果。但是有4/10次,它看起来像下面这张图片。

enter image description here

仅仅重新运行算法就会改变结果。有4/10的概率结果看起来像这样(或更差):

cvLevMarq“俄罗斯轮盘赌” 4/10:

enter image description here

期望结果:

我想使用已匹配的特征“精细”我的相机参数,希望图像能够完美对齐。不要指望cvLevMarq可以为我完成这项工作(它有4/10的概率无法完成),是否有其他方法来确保图像对齐呢?

更新:

我尝试了以下版本:

OpenCV 3.1:使用3.1版的CVLevMarq就像玩俄罗斯轮盘一样。有时候可以完美地对齐它们,而有时候它会估计焦距为NAN,这会导致多波段混合器中的segfault(ROI = 0,0,1,1,因为出现了NAN)。

OpenCV 2.4.9/2.4.13:使用2.4.9或2.4.13版的CvLevMarq,遗憾的是除了NAN问题之外,情况完全一样。6/10次可以完美地对齐图像,但另外4次则完全不行。

我的猜测/想法:

  • 使用OpenCV进行模板匹配。也许如果我对图像的末端进行模板匹配(即x = 0,y = 0,height = image.height,width = 50),会有所帮助。您对此有何想法?

  • 我发现这篇关于在Homography中应用Levenberg Marquardt的论文很有趣。看起来这可以解决我的问题,因为该论文使用角点检测等方法来检测图像中的特征。您对此有何想法?

  • 也许问题不在于CvLevMarq,而是在于BestOf2NearestMatcher?但是,我已经搜索了好几天,找不到另一种方法来返回成对的匹配结果以传递给BPRefiner

  • Hough Line Transform 检测第一/第二幅图像中的直线并将其用于对齐图像。您对此有何想法?--一个问题可能是,如果图像中没有任何直线怎么办?例如空墙?

  • 也许我在处理一个非常简单的东西时过度处理了..或者我没有?基本上,我正在尝试对齐一组图像,以便我可以对它们进行变形而不会重叠。如果您觉得不理解,请留言 :)

更新于8月12日:

尝试了各种组合后,目前绝对最好的选择是CvLevMarq。唯一的问题就是如上面的图片所示,结果不稳定。如果有任何建议,将永远感激不尽。


抱歉如果我的问题不够清晰。我还是比较新手。无论如何,这些图像大约相差24度,目标是对齐它们。我没有使用四元数,而是实现了更高精度的实际矩阵。通过调整相机焦距参数,我最终使用了camera_global[i].Focal = 418.0f,使其在水平方向上看起来对齐了,但在垂直方向上没有对齐。 - user4200570
我也尝试过使用 CvLevMarqcalcJacobian,但没有成功。虽然它可以对齐图像,但结果是不可预测的。 - user4200570
将图像平衡化,我的意思是 - user4200570
让我更新一些图片,以消除一些混淆 :) @slawekwin - user4200570
1
其实,现在我想起来了,我觉得这不会改变什么。每张图片大约有800个特征,应该足够进行对齐了。 - user4200570
显示剩余11条评论
3个回答

1
如果您想拼接图像,您应该查看stitching_detailed.cpp。它可能会解决您的问题。
此外,在此代码中,我使用了Canny边缘检测的Graph Cut Seam Finding方法以获得更好的拼接结果。如果您想优化此代码,请参见here
另外,如果您要将其用于个人用途,SIFT是不错的选择。但请注意,SIFT是有专利的,如果您将其用于商业目的,则需要付费。请改用ORB。
希望这能帮到您!

1

看起来很酷!但不确定从哪里获取ROS值? - user4200570
你在谈论哪些ROS值,你也可以不需要ROS的情况下安装它,参见这里:https://github.com/ethz-asl/kalibr/wiki/installation。 - ffurrer
请纠正我,但是使用它需要使用传感器或bagcreator脚本生成ROS bag值。无论哪种方式,似乎都有些过度了?或者也许我完全错了--如果是这样,请您解释一下这将如何使我受益? - user4200570

1
似乎您的参数初始化有问题。我建议先使用线性估计器,即忽略您的嘈杂传感器,然后将其用作非线性优化器的初始值。
一个快速的方法是使用getaffinetransform,因为您主要有旋转。

谢谢!你有任何线性估计器的建议吗?或者有任何我可以参考的实现示例吗?@fireant - user4200570
我明白了,所以你只是使用 std::vector< Point2f > obj;std::vector< Point2f > scene; 来进行 getAffineTransform 操作? - user4200570
没错,那应该可以。 - fireant
太棒了!!非常感谢! - user4200570
1
我的意思是,初步估计后,你应该这样做,然后可以运行非线性优化。 - fireant
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接