OpenCV 3.1 按拍摄顺序拼接图像

OpenCV 3.1 Stitch images in order they were taken

我正在构建一个 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 张),一些对象出现在彼此的顶部和它们不应该出现的地方。 我还注意到最终结果的 "beginning" (左侧)也不是矢量中的第一张图像 这很奇怪。

我将 "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 : 我想按照拍摄的顺序拼接图像,但上面的代码对我不起作用,我该怎么做?

所以我发现这里的问题不在于图像的拼接顺序,而在于在基于单应性的估计器和束射线调整器中为相机参数估计的旋转。

这些旋转角度是在考虑自旋转相机的情况下估算的,我的用例涉及用户旋转相机(这意味着也会有一些平移。 因此(我猜)水平角度(围绕 Y 轴)被高度高估,这意味着该算法认为图像集覆盖 >= 360 度,这导致一些不应重叠的重叠区域。

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

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();