30

ステレオ画像の特徴点を合わせたい。私はすでにさまざまなアルゴリズムで特徴点を見つけて抽出しましたが、今は適切に一致させる必要があります。この場合、検出と抽出、およびBruteForceMatcher特徴点のマッチングに FAST アルゴリズムを使用しています。

一致するコード:

vector< vector<DMatch> > matches;
//using either FLANN or BruteForce
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(algorithmName);
matcher->knnMatch( descriptors_1, descriptors_2, matches, 1 );

//just some temporarily code to have the right data structure
vector< DMatch > good_matches2;
good_matches2.reserve(matches.size());  
for (size_t i = 0; i < matches.size(); ++i)
{ 
    good_matches2.push_back(matches[i][0]);     
}

多くの誤った一致があるため、最小距離と最大距離を計算し、悪すぎるすべての一致を削除しました。

//calculation of max and min distances between keypoints
double max_dist = 0; double min_dist = 100;
for( int i = 0; i < descriptors_1.rows; i++ )
{
    double dist = good_matches2[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
}

//find the "good" matches
vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{
    if( good_matches2[i].distance <= 5*min_dist )
    {
        good_matches.push_back( good_matches2[i]); 
    }
}

問題は、多くの誤った一致が得られるか、正しい一致がわずかしか得られないことです (下の画像を参照)。

悪い結果の試合が多い
(出典: codemax.de )

いくつかの良い試合だけ
(出典: codemax.de )

プログラミングの問題ではなく、マッチングの問題だと思います。私が理解している限りでは、ローカル距離 (x&y 位置) ではなく、BruteForceMatcher特徴点の視覚的距離 (に保存されます) のみが考慮されます。これは、私の場合も重要です。FeatureExtractorこの問題を経験した人や、マッチング結果を改善するための良いアイデアはありますか?

編集

コードを変更して、50 個のベスト マッチが得られるようにしました。この後、指定されたエリアにあるかどうかを確認するために最初の一致を実行します。そうでない場合は、指定されたエリア内で一致が見つかるまで次の一致を行います。

vector< vector<DMatch> > matches;
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(algorithmName);
matcher->knnMatch( descriptors_1, descriptors_2, matches, 50 );

//look if the match is inside a defined area of the image
double tresholdDist = 0.25 * sqrt(double(leftImageGrey.size().height*leftImageGrey.size().height + leftImageGrey.size().width*leftImageGrey.size().width));

vector< DMatch > good_matches2;
good_matches2.reserve(matches.size());  
for (size_t i = 0; i < matches.size(); ++i)
{ 
    for (int j = 0; j < matches[i].size(); j++)
    {
    //calculate local distance for each possible match
    Point2f from = keypoints_1[matches[i][j].queryIdx].pt;
    Point2f to = keypoints_2[matches[i][j].trainIdx].pt;        
    double dist = sqrt((from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y));
    //save as best match if local distance is in specified area
    if (dist < tresholdDist)
    {
        good_matches2.push_back(matches[i][j]);
        j = matches[i].size();
    }
}

これ以上の一致は得られないと思いますが、これにより、より多くの誤った一致を削除できます。

少ないがより良い機能
(出典: codemax.de )

4

3 に答える 3

25

すべての特徴検出アルゴリズムを比較することで、より多くの一致が得られる適切な組み合わせを見つけました。現在、特徴検出に FAST、特徴抽出に SIFT、マッチングに BruteForce を使用しています。チェックと組み合わせて、一致が定義された領域内にあるかどうかを確認すると、多くの一致が得られます。画像を参照してください。

FAST や SIFT との相性が良い
(出典: codemax.de )

関連するコード:

Ptr<FeatureDetector> detector;
detector = new DynamicAdaptedFeatureDetector ( new FastAdjuster(10,true), 5000, 10000, 10);
detector->detect(leftImageGrey, keypoints_1);
detector->detect(rightImageGrey, keypoints_2);

Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create("SIFT");
extractor->compute( leftImageGrey, keypoints_1, descriptors_1 );
extractor->compute( rightImageGrey, keypoints_2, descriptors_2 );

vector< vector<DMatch> > matches;
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
matcher->knnMatch( descriptors_1, descriptors_2, matches, 500 );

//look whether the match is inside a defined area of the image
//only 25% of maximum of possible distance
double tresholdDist = 0.25 * sqrt(double(leftImageGrey.size().height*leftImageGrey.size().height + leftImageGrey.size().width*leftImageGrey.size().width));

vector< DMatch > good_matches2;
good_matches2.reserve(matches.size());  
for (size_t i = 0; i < matches.size(); ++i)
{ 
    for (int j = 0; j < matches[i].size(); j++)
    {
        Point2f from = keypoints_1[matches[i][j].queryIdx].pt;
        Point2f to = keypoints_2[matches[i][j].trainIdx].pt;

        //calculate local distance for each possible match
        double dist = sqrt((from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y));

        //save as best match if local distance is in specified area and on same height
        if (dist < tresholdDist && abs(from.y-to.y)<5)
        {
            good_matches2.push_back(matches[i][j]);
            j = matches[i].size();
        }
    }
}
于 2013-08-02T15:27:53.507 に答える