我有一组图像,并希望在所有情况下进行交叉匹配,并使用OpenCV 2.4.6(ROS Hydro Package)使用轨道栏显示结果。匹配部分是使用CV :: DMATCH-Objects的矢量矢量图进行的:

image[0] --- image[3] -------- image[8] ------ ...
   |             |                 |
   |         cv::DMatch-vect   cv::DMatch-vect
   |
image[1] --- ...
   |
image[2] --- ...
   |
  ...
   |
image[N] --- ...
.

因为我们省略了与图像匹配的图像(无需点),因为查询映像可能与查询图像的所有匹配列表图像不匹配,所以查询图像的每组匹配可能具有不同的大小。请注意,它实现的方式我实际上与一对图像相匹配,当然是不是最佳的(特别是因为我使用了带有交叉检查的BruteForce匹配器,这基本上意味着我匹配一对图像4次! )但现在就是这样。为了避免匹配的匹配图像的拍摄,我填充了CV :: Mat对象的矢量矢量图。每个CV ::垫代表当前的查询图像和一些匹配火车映像(我使用cv :: drawmatches()):

image[0] --- cv::Mat[0,3] ---- cv::Mat[0,8] ---- ...
   |
image[1] --- ...
   |
image[2] --- ...
   |
  ...
   |
image[N] --- ...
.

注意:在上面的示例中,cv :: mat [0,3]代表使用图像[0]和图像存储CV :: DrawMatches()乘积的CV :: MAT [ 3]。

以下是GUI设置:

  • 主窗口:这里我显示当前查询映像。使用轨栏 - 让我们调用它track_query - 我遍历我的集合中的每个图像。
  • 辅助窗口:这里我显示匹配的对(查询,列车),其中Track_query的滑块的位置与另一个轨道栏中的滑块位置之间的组合 - 让我们调用它track_train - 让我允许我迭代所有CV :: mat-match-matters用于当前查询图像。

此处的问题来自每个查询可以具有可变数量的匹配列车图像。我的Track_train应该能够适应匹配的列车图像的数量,即每个CV :: Mat-向量中的元素数量为当前查询图像。遗憾的是到目前为止,我无法找到这样做的方法。 CV :: createTrackBar()需要计数参数,从我看到的内容设置轨栏的滑块的限制,而 不能 稍后更改。如果我错了,请纠正我,因为这正是困扰着我。可能的解决方案(不太优雅,涉及各种检查,以避免超出范围的错误)是占据最大的匹配列车图像的大小,并将其用作我的Track_train的限制。如果可能的话,我想避免这样做。另一种可能的解决方案涉及根据所选择的查询图像在我的辅助窗口中创建每个查询图像的轨栏。目前,这似乎是更容易的方法,但是追随轨道博士的一个很大的开销,更不用说我没有听说过OpenCV让你隐藏GUI控件。以下是两个可能澄清一点点的例子:

例1: 在主窗口中,我使用Track_Query选择图像2。对于此图像,我已经设法从我的集合匹配5个其他图像。让我们说那些是图像4,10,17,18和20.辅助窗口自动更新,并在图像2和图像4之间匹配(首先在匹配的列车图像的子集中)。 Track_train必须从0到4.在两个方向上移动滑块允许我通过辅助窗口进行图像4,10,17,18和20更新。

例2: 在主窗口中,我使用Track_Query选择图像7。对于此图像,我已经设法从我的集合匹配3个其他图像。让我们说那些是图像0,1,11和19.辅助窗口自动更新,并在图像2和图像0之间匹配(首先在匹配的列车图像的子集中)。 track_train必须从0到2。在两个方向上移动滑块允许我每次都会通过辅助窗口进行图像0,1,1和19更新。

如果您有任何疑问,请随时询问,我会尽可能地回答它们。提前谢谢!

ps:可悲的是ROS包的方式它具有opencv可以提供的最低限度。没有Qt集成,没有OpenMP,没有OpenGL等。

有帮助吗?

解决方案

做更多的研究后,我非常确定目前不可能。这就是为什么我实现了我在我的问题中提供的第一个命题 - 使用匹配矢量与其中最多的匹配项中,以确定轨栏的最大大小,然后使用一些检查来避免超出范围的异常。以下还有一个或多或少详细描述如何运作。由于我的代码中的匹配程序涉及一些不涉及手头问题的额外检查,我将在此跳过。注意,在一组给定的图像集中,我们要匹配,我将图像指代对象图像当该图像(示例:卡)与场景图像匹配时(例如:一组卡) - 顶级匹配矢量(见下文)并等于ProcessEdimages中的索引(见下文)。我在OpenCV中找到了火车/查询符号,令人困惑。此场景/对象表示法从 http://docs.opencv.org /doc/tutorials/features2d/feature_homography/feature_homography.html 。您可以更改或交换您喜欢的符号,但请确保您随时更改它,否则您可能最终有一个奇怪的结果。

// stores all the images that we want to cross-match
std::vector<cv::Mat> processedImages;
// stores keypoints for each image in processedImages
std::vector<std::vector<cv::Keypoint> > keypoints;
// stores descriptors for each image in processedImages 
std::vector<cv::Mat> descriptors;

// fill processedImages here (read images from files, convert to grayscale, undistort, resize etc.), extract keypoints, compute descriptors
// ...

// I use brute force matching since I also used ORB, which has binary descriptors and HAMMING_NORM is the way to go
cv::BFmatcher matcher;
// matches contains the match-vectors for each image matched to all other images in our set
// top level index matches.at(X) is equal to the image index in processedImages
// middle level index matches.at(X).at(Y) gives the match-vector for the Xth image and some other Yth from the set that is successfully matched to X
std::vector<std::vector<std::vector<cv::DMatch> > > matches;
// contains images that store visually all matched pairs
std::vector<std::vector<cv::Mat> > matchesDraw;

// fill all the vectors above with data here, don't forget about matchesDraw
// stores the highest count of matches for all pairs - I used simple exclusion by simply comparing the size() of the current std::vector<cv::DMatch> vector with the previous value of this variable
long int sceneWithMaxMatches = 0;
// ...

// after all is ready do some additional checking here in order to make sure the data is usable in our GUI. A trackbar for example requires AT LEAST 2 for its range since a range (0;0) doesn't make any sense
if(sceneWithMaxMatches < 2)
  return -1;

// in this window show the image gallery (scene-images); the user can scroll through all image using a trackbar
cv::namedWindow("Images", CV_GUI_EXPANDED | CV_WINDOW_AUTOSIZE);
// just a dummy to store the state of the trackbar 
int imagesTrackbarState = 0;
// create the first trackbar that the user uses to scroll through the scene-images
// IMPORTANT: use processedImages.size() - 1 since indexing in vectors is the same as in arrays - it starts from 0 and not reducing it by 1 will throw an out-of-range exception
cv::createTrackbar("Images:", "Images", &imagesTrackbarState, processedImages.size() - 1, on_imagesTrackbarCallback, NULL);
// in this window we show the matched object-images relative to the selected image in the "Images" window
cv::namedWindow("Matches for current image", CV_WINDOW_AUTOSIZE);
// yet another dummy to store the state of the trackbar in this new window
int imageMatchesTrackbarState = 0;
// IMPORTANT: again since sceneWithMaxMatches stores the SIZE of a vector we need to reduce it by 1 in order to be able to use it for the indexing later on
cv::createTrackbar("Matches:", "Matches for current image", &imageMatchesTrackbarState, sceneWithMaxMatches - 1, on_imageMatchesTrackbarCallback, NULL);

while(true)
{
  char key = cv::waitKey(20);
  if(key == 27)
    break;

  // from here on the magic begins
  // show the image gallery; use the position of the "Images:" trackbar to call the image at that position
  cv::imshow("Images", processedImages.at(cv::getTrackbarPos("Images:", "Images")));

  // store the index of the current scene-image by calling the position of the trackbar in the "Images:" window
  int currentSceneIndex = cv::getTrackbarPos("Images:", "Images");
  // we have to make sure that the match of the currently selected scene-image actually has something in it
  if(matches.at(currentSceneIndex).size())
  {
    // store the index of the current object-image that we have matched to the current scene-image in the "Images:" window
    int currentObjectIndex = cv::getTrackbarPos("Matches:", "Matches for current image");
    cv::imshow(
            "Matches for current image",
            matchesDraw.at(currentSceneIndex).at(currentObjectIndex < matchesDraw.at(currentSceneIndex).size() ? // is the current object index within the range of the matches for the current object and current scene
            currentObjectIndex : // yes, return the correct index
            matchesDraw.at(currentSceneIndex).size() - 1));  // if outside the range show the last matched pair!
  }
}

// do something else
// ...
.

棘手的部分是第二个窗口中的轨栏,负责将匹配的图像访问到我们当前所选图像中的“图像”窗口中。如我所解释的那样,我将轨道栏“匹配:”在“当前图像”窗口的“匹配中”,以便从0到(SycefithexMatches-1)的范围。但是,并非所有图像都具有与图像集中的其余相同的匹配量(如果您已经完成了一些额外的过滤,则应用十倍以确保可靠的匹配,例如通过利用配合,比率测试,MIN / MAX距离检查等的属性来确保可靠的匹配。)。因为我无法找到动态调整轨栏的范围的方法,所以我需要验证索引。否则,对于某些图像及其匹配,应用程序将抛出超出范围的异常。这是由于对某些匹配的简单事实,我们尝试访问匹配的索引,该索引大于它的大小为负1,因为cv :: getTrackBarpos()一直到(ScenewithexMatches-1)。如果轨迹栏的位置超出了当前所选向量的匹配匹配的范围,我只需将MatchDraw-Image设置为“当前图像的匹配”到载体中的最后一个。在这里,我利用了索引不能低于零的事实以及轨栏的位置,以便不需要检查这个,而是只有在初始位置之后才出现。如果不是您的情况,请确保检查较低的情况绑定也是鞋面。

希望这有帮助!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top