1

2 つの画像を一致させようとしています。1 つはモバイル画面のスクリーン ショットで、テンプレート画像は任意のアプリ アイコンです。同じ画像から切り取ったソースとテンプレートを一致させると、完全に一致します。しかし、別のモバイル画面から切り取ったアプリ アイコンを使用すると、正しく一致していません。

画像マッチングのために、次のコードに取り組んでいます:

int main( int argc, char** argv )
{

Mat objectImg = imread("source.jpg", cv::IMREAD_GRAYSCALE);
Mat sceneImg = imread("note4-3.jpg", cv::IMREAD_GRAYSCALE);

//cv::resize(sceneImg,sceneImg,objectImg.size(),0,0,CV_INTER_CUBIC);

if( !objectImg.data || !sceneImg.data )
{
    printf( " No image data \n " );
    return -1337;
}

std::vector<cv::KeyPoint> objectKeypoints;
std::vector<cv::KeyPoint> sceneKeypoints;
cv::Mat objectDescriptors;
cv::Mat sceneDescriptors;

Ptr<FeatureDetector> detector;
detector = cv::MSER::create();
detector->detect(objectImg, objectKeypoints);
detector->detect(sceneImg, sceneKeypoints);

Ptr<DescriptorExtractor> extractor = cv::ORB::create();
extractor->compute( objectImg, objectKeypoints, objectDescriptors );
extractor->compute( sceneImg, sceneKeypoints, sceneDescriptors );

if(objectDescriptors.type()!=CV_32F) {
objectDescriptors.convertTo(objectDescriptors, CV_32F);
}

if(sceneDescriptors.type()!=CV_32F) {
sceneDescriptors.convertTo(sceneDescriptors, CV_32F);
}

vector< vector<DMatch> > matches;
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
matcher->knnMatch( objectDescriptors, sceneDescriptors, matches, 8 );

double max_dist = 0; double min_dist = 100;

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

std::vector<cv::DMatch> good_matches;

for( int i = 0; i < objectDescriptors.rows; i++ )
{ 
    if( matches[i][0].distance <= max(2*min_dist, 0.02) ) {
        good_matches.push_back( matches[i][0]); 
    }

}

//look whether the match is inside a defined area of the image
//only 25% of maximum of possible distance
/*double tresholdDist = 0.50 * sqrt(double(sceneImg.size().height*sceneImg.size().height + sceneImg.size().width*sceneImg.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 = objectKeypoints[matches[i][j].queryIdx].pt;
        Point2f to = sceneKeypoints[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();
        }
    }
}*/

Mat allmatchs;
   drawMatches(objectImg,objectKeypoints,sceneImg,sceneKeypoints,good_matches,allmatchs,Scalar::all(-1), Scalar::all(-1),vector<char>(),0);
namedWindow("Matchs" , CV_WINDOW_NORMAL);
imshow( "Matchs",allmatchs);

waitKey(0);

}

[別のソースから切り取った場合の間違った一致][1]

上記の結果は、あるモバイル スクリーン ショットのソースと別のスクリーン ショットのテンプレートを照合したときに得られます。

私はopencv3.0を使用しています

コードを変更したか、テンプレート マッチングまたはその他の手法を使用する必要があるかどうかを助けてください。

サンプル画像:

ソース画像

テンプレート

4

2 に答える 2

1

あなたが提供した画像を見て、私はあなたを助けるいくつかの変更を提案することができます.

  • 適切な一致の選択を削除します。これにより、シャープな特徴が存在する場合に問題が発生します。シャープな特徴は、他の良い一致と比較すると、ハミング距離が非常に短くなります。2*min_dist を選択すると、間接的に適切な一致が無視されます。
  • オブジェクト画像に適切な数の特徴点があることを確認してください。
  • この機能検出器と記述子の組み合わせがうまくいかない場合は、MSER-ORB よりもはるかに優れた、STAR-BRIEF、SURF などの他の機能検出器と記述子を選択します。
  • あなたの状況では、検出器マッチャーは回転不変である必要はなく、スケール不変でなければなりません。オブジェクト画像のサイズを変更してみてください

私の提案がお役に立てば幸いです

于 2016-01-04T09:10:58.333 に答える