OpenCV 3.1按照拍摄顺序拼接图像

时间:2016-09-21 11:35:16

标签: c++ opencv android-ndk opencv-stitching

我正在构建一个Android应用来创建全景图。用户捕获一组图像和那些图像 被发送到基于https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp的我的本地拼接功能。 由于图像是有序的,我想将每个图像仅匹配到矢量中的下一个图像。

我发现了一篇英特尔文章,其中包含以下代码:

vector<MatchesInfo> pairwise_matches;
BestOf2NearestMatcher matcher(try_gpu, match_conf);
Mat matchMask(features.size(),features.size(),CV_8U,Scalar(0));
for (int i = 0; i < num_images -1; ++i)
{
    matchMask.at<char>(i,i+1) =1;
}
matcher(features, pairwise_matches,matchMask);
matcher.collectGarbage();

问题是,这不会编译。我猜它,因为我使用OpenCV 3.1。 然后我找到了某个地方,这段代码会做同样的事情:

int range_width = 2;
BestOf2NearestRangeMatcher matcher(range_width, try_cuda, match_conf);
matcher(features, pairwise_matches);
matcher.collectGarbage();

对于我的大多数样品,这都很好。但有时候,特别是当我拼接时 一大堆图像(大约15个),一些对象出现在彼此的顶部,并且在他们不应该的地方。 我还注意到最终结果的“开始”(左侧)也不是矢量中的第一个图像 这很奇怪。

我使用“orb”作为features_type,使用“ray”作为ba_cost_func。好像我不能在OpenCV 3.1上使用SURF。 其余的初始参数如下所示:

bool try_cuda = false;
double compose_megapix = -1; //keeps resolution for final panorama
float match_conf = 0.3f; //0.3 default for orb
string ba_refine_mask = "xxxxx";
bool do_wave_correct = true;
WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;
int blend_type = Blender::MULTI_BAND;
float blend_strength = 5;

double work_megapix = 0.6;
double seam_megapix = 0.08;
float conf_thresh = 0.5f;
int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
string seam_find_type = "dp_colorgrad";
string warp_type = "spherical";

所以有人可以告诉我为什么这不起作用以及我应该如何匹配我的功能?任何帮助或方向将不胜感激!

TL; DR :我想按拍摄顺序缝合图像,但上面的代码对我不起作用,我该怎么做?

2 个答案:

答案 0 :(得分:0)

所以我发现这里的问题不在于图像被拼接的顺序,而在于基于Homography的估算器和束光调整器中的相机参数估计的旋转。

这些旋转角度是根据自转相机进行估算的,我的使用案例包含用户旋转相机(这意味着也会进行一些翻译)。 因为(我猜)水平角度(围绕Y轴)被高度估计,这意味着算法认为图像集覆盖> = 360度,这导致一些不应重叠的重叠区域。

虽然还没有找到解决这个问题的方法。

答案 1 :(得分:0)

matcher()将UMat作为掩码而不是Mat对象,因此请尝试以下代码:

vector<MatchesInfo> pairwise_matches;
BestOf2NearestMatcher matcher(try_gpu, match_conf);
Mat matchMask(features.size(),features.size(),CV_8U,Scalar(0));
for (int i = 0; i < num_images -1; ++i)
{
    matchMask.at<char>(i,i+1) =1;
} 

UMat umask = matchMask.getUMat(ACCESS_READ);

matcher(features, pairwise_matches, umask);
matcher.collectGarbage();