3

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

4

2 回答 2

1

所以我发现这里的问题不在于拼接图像的顺序,而是基于 Homography Based Estimator 和 Bundle Ray Adjuster 中的相机参数估计的旋转。

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

尽管如此,仍然没有找到解决该问题的方法。

于 2016-10-11T10:46:23.720 回答
1

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();
于 2017-07-17T07:21:56.553 回答