Как получить эффективный результат в ORB, используя opencv 2.4.9?

int method = 0;

std::vector<cv::KeyPoint> keypoints_object, keypoints_scene;
cv::Mat descriptors_object, descriptors_scene;

cv::ORB orb;

int minHessian = 500;
//cv::OrbFeatureDetector detector(500);
//ORB orb(25, 1.0f, 2, 10, 0, 2, 0, 10);
cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10);
//cv::OrbFeatureDetector detector(500,1.20000004768,8,31,0,2,ORB::HARRIS_SCORE,31);
cv::OrbDescriptorExtractor extractor;

//-- object
if( method == 0 ) { //-- ORB
    orb.detect(img_object, keypoints_object);
    //cv::drawKeypoints(img_object, keypoints_object, img_object, cv::Scalar(0,255,255));
    //cv::imshow("template", img_object);

    orb.compute(img_object, keypoints_object, descriptors_object);
} else { //-- SURF test
    detector.detect(img_object, keypoints_object);
    extractor.compute(img_object, keypoints_object, descriptors_object);
}
// http://stackru.com/a/11798593
//if(descriptors_object.type() != CV_32F)
//    descriptors_object.convertTo(descriptors_object, CV_32F);


//for(;;) {
    cv::Mat frame = cv::imread("E:\\Projects\\Images\\2-134-2.bmp", 1);
    cv::Mat img_scene = cv::Mat(frame.size(), CV_8UC1);
    cv::cvtColor(frame, img_scene, cv::COLOR_RGB2GRAY);
    //frame.copyTo(img_scene);
    if( method == 0 ) { //-- ORB
        orb.detect(img_scene, keypoints_scene);
        orb.compute(img_scene, keypoints_scene, descriptors_scene);
    } else { //-- SURF
        detector.detect(img_scene, keypoints_scene);
        extractor.compute(img_scene, keypoints_scene, descriptors_scene);
    }

    //-- matching descriptor vectors using FLANN matcher
    cv::BFMatcher matcher;
    std::vector<cv::DMatch> matches;
    cv::Mat img_matches;
    if(!descriptors_object.empty() && !descriptors_scene.empty()) {
        matcher.match (descriptors_object, descriptors_scene, matches);

        double max_dist = 0; double min_dist = 100;

        //-- Quick calculation of max and min idstance between keypoints
        for( int i = 0; i < descriptors_object.rows; i++)
        { double dist = matches[i].distance;
            if( dist < min_dist ) min_dist = dist;
            if( dist > max_dist ) max_dist = dist;
        }
        //printf("-- Max dist : %f \n", max_dist );
        //printf("-- Min dist : %f \n", min_dist );
        //-- Draw only good matches (i.e. whose distance is less than 3*min_dist)
        std::vector< cv::DMatch >good_matches;

        for( int i = 0; i < descriptors_object.rows; i++ )

        { if( matches[i].distance < (max_dist/1.6) )
            { good_matches.push_back( matches[i]); }
        }

        cv::drawMatches(img_object, keypoints_object, img_scene, keypoints_scene, \
                good_matches, img_matches, cv::Scalar::all(-1), cv::Scalar::all(-1),
                std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

        //-- localize the object
        std::vector<cv::Point2f> obj;
        std::vector<cv::Point2f> scene;

        for( size_t i = 0; i < good_matches.size(); i++) {
            //-- get the keypoints from the good matches
            obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
            scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
        }
        if( !obj.empty() && !scene.empty() && good_matches.size() >= 4) {
            cv::Mat H = cv::findHomography( obj, scene, cv::RANSAC );

            //-- get the corners from the object to be detected
            std::vector<cv::Point2f> obj_corners(4);
            obj_corners[0] = cv::Point(0,0);
            obj_corners[1] = cv::Point(img_object.cols,0);
            obj_corners[2] = cv::Point(img_object.cols,img_object.rows);
            obj_corners[3] = cv::Point(0,img_object.rows);

            std::vector<cv::Point2f> scene_corners(4);

            cv::perspectiveTransform( obj_corners, scene_corners, H);

            //-- Draw lines between the corners (the mapped object in the scene - image_2 )
            cv::line( img_matches, \
                    scene_corners[0] + cv::Point2f(img_object.cols, 0), \
                    scene_corners[1] + cv::Point2f(img_object.cols, 0), \
                    cv::Scalar(0,255,0), 4 );
            cv::line( img_matches, \
                    scene_corners[1] + cv::Point2f(img_object.cols, 0), \
                    scene_corners[2] + cv::Point2f(img_object.cols, 0), \
                    cv::Scalar(0,255,0), 4 );
            cv::line( img_matches, \
                    scene_corners[2] + cv::Point2f(img_object.cols, 0), \
                    scene_corners[3] + cv::Point2f(img_object.cols, 0), \
                    cv::Scalar(0,255,0), 4 );
            cv::line( img_matches, \
                    scene_corners[3] + cv::Point2f(img_object.cols, 0), \
                    scene_corners[0] + cv::Point2f(img_object.cols, 0), \
                    cv::Scalar(0,255,0), 4 );

        }
    }

        t =(double) getTickCount() - t;
    printf("Time :%f",(double)(t*1000./getTickFrequency()));

    cv::imshow("match result", img_matches );
    cv::waitKey();


return 0;

Здесь я выполняю сопоставление шаблонов между двумя изображениями. где я извлекаю ключевые точки, используя алгоритм ORB и сопоставляя его с BF Matcher, но я не получаю хорошего результата. Здесь я добавляю изображение, чтобы понять проблемуПоиск объекта изображения из кадра изображения

Здесь вы можете видеть темно-синюю линию на тедди, которая на самом деле представляет собой прямоугольник, который будет нарисован вокруг объекта из фрейма изображения, когда объект будет распознан путем сопоставления ключевых точек. Здесь я использую Opencv 2.4.9, какие изменения я должен сделать, чтобы получить хороший результат?

1 ответ

В любом обнаружении признаков + извлечении, сопровождаемом оценкой гомографии, есть много параметров, с которыми вы можете играть. Однако главное, что нужно понять, это то, что это почти всегда проблема Computation Time VS. Точность

Самая важная точка отказа вашего кода - инициализация ORB:

cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10);
  1. Первый параметр указывает экстрактору использовать только 25 лучших результатов от детектора. Для надежной оценки гомографии с 8 степенями свободы без ограничений на параметры у вас должно быть на порядок больше признаков, чем параметров, т.е. 80, или просто сделайте его равным 100.
  2. Второй параметр предназначен для масштабирования изображений вниз (или патч детектора вверх) между октавами (или уровнями). используя номер 1.0f означает, что вы не изменяете масштаб между октавами, это не имеет смысла, тем более что ваш третий параметр - это количество уровней, а не 2. По умолчанию 1.2f для масштаба и 8 уровни, для меньшего количества вычислений, используйте масштабирование 1.5f а также 4 уровни (опять же, просто предложение, другие параметры тоже будут работать).
  3. ваш четвертый и последний параметры говорят, что размер патча для расчета составляет 10x10, это довольно мало, но если вы работаете с низким разрешением, это нормально.
  4. ваш тип счета (один перед последним параметром) может немного изменить время выполнения, вы можете использовать ORB::FAST_SCORE вместо ORB::HARRIS_SCORE но это не имеет большого значения.

Наконец, что не менее важно, когда вы инициализируете объект BruteForce Matcher, вы должны помнить, что нужно использовать cv::NORM_HAMMING тип, поскольку ORB - это двоичная функция, поэтому вычисления норм в процессе сопоставления что-то значат.

Другие вопросы по тегам