質問

私は一組の画像を持っており、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] --- ...
.

それ自体で画像と一致することを省略しているため、クエリ画像の一致した列車画像の各セットとクエリ画像の各セットと照会画像を一致させないため、残りからのサイズが異なる場合があります。右に実装されている方法は、実際に一対の画像を2回一致させます。これは、もちろん最適ではない(特にクロスチェックでBruteForce Matcherを使用していますので、基本的には4回の画像のペアと一致させることを意味します。 )しかし今のところそれはそれです。一致した画像の一致するペアのオンザフライ図を避けるために、私はCV :: MATオブジェクトのベクトルのベクトルを入力しました。各CV :: MATは、現在のクエリイメージといくつかのマッチング列車イメージを表します(私はCV :: DrawMatches()):

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

:上記の例では、CV :: Mat [0,3]はCV :: Drawmatches()の積を画像[0]とimageの積を格納するCV :: Matです。 3]。

GUI設定:

  • メインウィンドウ:ここで現在のクエリイメージを表示します。トラックバーを使用する - TRACK_QUERYを呼び出しましょう - 私は自分のセットの各画像を反復します。
  • 副ウィンドウ:ここでは、track_queryのスライダの位置とこのウィンドウで別のトラックバーのスライダの位置との間の組み合わせを表示します。現在のクエリイメージのすべてのCV :: Mat-Match-Images

ここでの問題は、各クエリに可変数の列車画像を持つことができるという事実から来ています。私のtrack_trainは、マッチングされた列車画像の数、つまり現在のクエリイメージの各CV :: Mat-Vectorの要素数に調整できるはずです。悲しいことにこれまでのところ私はそれをする方法を見つけることができませんでした。 CV :: CreateTrackBar()には、TrackBarのスライダの制限が表示され、 が後で変更することはできません。私が間違っているのであれば私を訂正してください。これはまさに私を悩ませているものです。可能な解決策(範囲外のエレクトロスを避けるためのエレガントで様々な小切手を伴う)は、一致する列車画像の最大のセットのサイズを取り、それを私のtrack_trainの限界として使用することです。可能であれば、私はそれをやめたいと思います。別の可能な解決策は、選択されたクエリ画像に従って適切な値範囲を持つクエリ画像ごとにトラックバーを作成することを含む。今のところ、これは進むためのより簡単な方法のようですが、私がopencvを聞いたことがないという事実を言及していないということは、GUIコントロールを隠すことができるという事実を言及しないようなトラックバーの大きなオーバーヘッドをもたらします。これは少し少し明確にするかもしれない2つの例です:

例1: メインウィンドウで、track_queryを使用して画像2を選択します。このイメージのために私は私のセットから他の5つのイメージを一致させることができました。それらは画像4,10,17,18および20であると言ってみましょう。セカンダリウィンドウは自動的に更新され、画像2と画像4の間の一致(一致した列車画像のサブセット内)を表示します。 TRACK_TRAINは0から4に行かなければなりません。スライダを両方向に移動させることで、2次ウィンドウが毎回更新される画像4,10,17,18、および20を通過させます。

例2: メインウィンドウで、track_queryを使用して画像7を選択します。このイメージのために私は私のセットから他の3つのイメージを一致させることができました。これらのイメージ0,1,11および19であるとしましょう。セカンダリウィンドウは自動的に更新され、画像2と画像0の間の一致(一致した列車画像のサブセット内)を表示します。 TRACK_TRAINは0から2に行かなければなりません。スライダを両方向に移動すると、2次ウィンドウが毎回更新される画像0,1,1、および19を通過させます。

質問がある場合は、お気軽にお問い合わせください。事前にありがとう!

PS:悲しいことに、ROSパッケージの方法は、OpenCVが提供できるものの裸の最小値を持っています。 QT統合なし、OpenMP、OpenGLなど、

役に立ちましたか?

解決

もう少し研究を行った後は、これが現在不可能だと確信しています。だからこそ、私は私が私の質問で与えた最初の命題を実装しました - それに最悪の一致を持つ一致ベクトルを使用して、トラックバーの最大サイズを決定してからいくつかのチェックを使用して範囲外例を避けてください。以下の説明がすべて機能しているのかは、より詳細な説明があります。私のコードのマッチング手順は、手元の問題に関係なく、いくつかの追加の小切手を含みますので、ここでスキップします。一致したい画像のセットでは、その画像(例:カード)が現在シーンイメージと一致しているときにオブジェクトイメージとしての画像を参照してください(例:カードのセット) - トップレベルMatches-Vector(下記参照)および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
// ...
.

トリッキー部分は、「イメージ」ウィンドウで、一致した画像に現在選択されている画像にアクセスする責任がある2番目のウィンドウのトラックバーです。上で説明したように、私は「現在の画像の一致」ウィンドウの「マッチング」ウィンドウに、0から(ScanewismaxMatches-1)の範囲内のTrackBar "Matches:"を設定します。ただし、すべての画像がイメージ・セット内の残りと同じ量の一致を持っているわけではありません(たとえば、ホモグラフィのプロパティー、比テスト、最小距離チェックなどを利用することで、信頼できる一致を確実にするために追加のフィルタリングを行った場合は10倍に適用します。 。)。トラックバーの範囲を動的に調整する方法を見つけることができなかったので、インデックスの検証が必要でした。そうでなければ、いくつかの画像とその一致のために、アプリケーションは範囲外例をスローします。これは、CV :: GetTrackBarpos()がずっと行われるため(ScanewismaxMatches - 1)はずっと行われるため、一致するものでは、一致するものが一致するというわけでは、それがサイズから大きい索引を持つ索引を持つマッチベクトルにアクセスしようとしています。トラックバーの位置が現在選択されているベクトルの一致の範囲外になると、マッチドローイメージを「現在のイメージのマッチ」でベクトルの最後まで設定します。ここでは、索引付けがトラックバーの位置を下回ることができないという事実を悪用して、これをチェックする必要がないので、最初の位置0の後に何が起こる必要はありません。上限だけでなく、縛られています。

これが助けに役立つことを願っています!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top