Как получить эффективный результат в 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://stackoverflow.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, какие изменения я должен сделать, чтобы получить хороший результат?

3

Решение

В любом обнаружении признаков + извлечении, сопровождаемом оценкой гомографии, есть много параметров, с которыми вы можете играть. Однако главное, что нужно понять, это то, что это почти всегда вопрос Время вычислений 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. ваш четвертый и последний параметры говорят, что размер патча для расчета составляет 10х10, это довольно мало, но если вы работаете с низким разрешением, это нормально.
  4. ваш тип счета (один перед последним параметром) может немного изменить время выполнения, вы можете использовать ORB::FAST_SCORE вместо ORB::HARRIS_SCORE но это не имеет большого значения.

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

7

Другие решения


По вопросам рекламы [email protected]