13

OpenCV は、RANSAC 関数自体を提供していません。少なくとも、それを呼び出して実行できる形式 (例: cv::ransac(...)) では提供していません。RANSAC を使用できるすべての関数/メソッドには、それを有効にするフラグがあります。ただし、これは、ホモグラフィ/基本行列を推定した後に RANSAC が計算するインライアで実際に何か他のことをしたい場合には、常に役立つとは限りません。たとえば、Octave または同様のソフトウェア/ポイントのライブラリで素敵なプロットを作成し、フィルタリングされた一致の残りのセットなど

2 つの画像を一致させた後、一致のベクトルを取得します。それに加えて、もちろん、マッチング プロセスで使用された 2 セットのキーポイント (各画像に 1 つ) があります。一致とキーポイントを使用して、ポイントの 2 つのベクトル (例: cv::Point2f points) を作成し、これらを に渡しますfindHomography()thisthisの投稿から、その関数に渡すマスクを使用してインライアがどのように正確にマークされているかを発見しました。マスク内の各行は、インライア/アウトライアに関連しています。ただし、2 つのポイント セットから行インデックス情報を使用する方法がわかりません。OpenCV のソース コードを見ても、あまり理解できませんでした。(署名とマスク部分に関してはfindFundamental()同様)で、彼らは使用しますfindHomography()compressPoints()、これは、入力として持っている 2 つのセット (ソース ポイントと宛先ポイント) を何らかの方法で 1 つに結合しているように見えます。マスクの性質を判断するためのテスト中に、2 セットの一致するポイントを試しました (標準手順に変換) cv::Keypointscv::Point2f各セットには 300 ポイントが含まれているため、合計で 600 ポイントになります。返されたマスクには 300 行が含まれています (このトピックでは値は重要ではありません)。

編集:これを書いているときに答えを発見しました(以下を参照)が、誰かがこの情報をできるだけ早くコンパクトな形式で必要とする場合に備えて、とにかくこの質問を投稿することにしました。RANSAC をサポートする OpenCV の関数の 1 つがまだ必要であることに注意してください。したがって、ポイントのセットはあるが、ホモグラフィや基礎行列を計算するつもりがない場合、これは明らかに方法ではありません。OpenCV の API で、この障害を回避するのに役立つ有用なものを見つけることができなかったので、使用する必要があります外部ライブラリ。

4

2 に答える 2

14

解決策は実際には非常に簡単です。知っているように、マスクの各行は、インライアまたはアウトライアがある場合に情報を提供します。ただし、入力として 2 セットのポイントがあるので、1 つの値を含む行が 2 つのポイントをどのように正確に表すのでしょうか? この種のインデックス付けの性質は、findHomography() でこれら 2 つの点のセットが実際にどのように表示されるかを考えているときに頭に浮かびました (私の場合、2 つの画像間のホモグラフィを計算していました)。画像のペア間の一致から抽出されるという単純な事実のため、両方のセットに同じ数のポイントがあります。これは、マスク内の行が 2 つのセット内のポイントの実際のインデックスであり、2 つの画像の一致のベクトル内のインデックスでもあることを意味します。これに基づいて一致したポイントの小さなサブセットを手動で参照することに成功し、結果は期待どおりです。cv::DMatch. 以下に、1 組のインライアの簡単な例を示します。

for(int i = 0; i < matchesObjectScene.size(); ++i)
{
   // extract points from keypoints based on matches
   pointsObject.push_back(keypointsObject.at(matchesObjectScene.at(i).queryIdx).pt);
   pointsScene.push_back(keypointsScene.at(matchesObjectScene.at(i).trainIdx).pt);
}
// compute homography using RANSAC
cv::Mat mask;
cv::Mat H = cv::findHomography(pointsObject, pointsScene, CV_RANSAC, ransacThreshold, mask);

上記の例で、インライアを印刷すると

int maskRow = 10;
std::cout << "POINTS: object(" << pointsObject.at(maskRow).x << "," << pointsObject.at(maskRow).y << ") - scene(" << pointsScene.at(maskRow).x << "," << pointsScene.at(maskRow).y << ")" << std::endl;

もう一度、今回はキーポイントを使用します (抽出された 2D ポイントでも実行できます)。

std::cout << "POINTS (via match-set): object(" << keypointsObject.at(matchesCurrentObject.at(maskRow).queryIdx).pt.x << "," << keypointsObject.at(matchesCurrentObject.at(maskRow).queryIdx).pt.y << ") - scene(" << keypointsScene.at(matchesCurrentObject.at(maskRow).trainIdx).pt.x << "," << keypointsScene.at(matchesCurrentObject.at(maskRow).trainIdx).pt.y << ")" << std::endl;

実際には同じ出力が得られます。

POINTS: object(462,199) - sscene(485,49)
POINTS (via match-set): object(462,199) - scene(485,49)

実際のインライアを取得するには、マスクの現在の行に実際に 0 またはゼロ以外の値が含まれているかどうかを確認する必要があります。

if((unsigned int)mask.at<uchar>(maskRow))
  // store match or keypoints or points somewhere where you can access them later
于 2014-06-27T16:36:32.453 に答える