如何使用opencv 2.4.9获得有效的ORB结果?

时间:2015-01-19 11:52:19

标签: c++ opencv image-processing orb

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匹配器匹配,但我没有得到好结果。我在这里添加Image以了解问题Finding Object Image from frame Image

这里您可以看到泰迪熊上的深蓝色线条实际上是一个矩形,当从对象关键点识别对象时,该矩形将从帧图像周围绘制。 在这里,我使用Opencv 2.4.9,我应该做些什么改变才能获得好结果?

1 个答案:

答案 0 :(得分:7)

在任何特征检测+提取后进行单应性估计,您可以使用许多参数。然而,要意识到的主要问题是它几乎总是计算时间VS的问题。精度

代码最关键的失败点是ORB初始化:

cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10);
  1. 第一个参数告诉提取器仅使用检测器的前25个结果。为了可靠地估计8 DOF单应性而不对参数进行约束,您应该具有比参数更多的特征,即80,或者只是使其成为100。
  2. 第二个参数用于在八度(或级别)之间缩小图像(或检测器补丁)。使用数字1.0f意味着你不会改变八度音阶之间的音阶,这没有任何意义,特别是因为你的第三个参数是2级而不是1级。默认值为{{1} }对于缩放和1.2f级别,对于较少的计算,使用81.5f级别的缩放(同样,只是一个建议,其他参数也会起作用)。
  3. 你的第四个和最后一个参数表示要计算的补丁大小是10x10,这个非常小,但是如果你处理的是低分辨率,那很好。
  4. 您的分数类型(最后一个参数前一个)可以稍微改变运行时间,您可以使用4代替ORB::FAST_SCORE,但它并不重要。
  5. 最后但并非最不重要的是,当你初始化BruteForce Matcher对象时,你应该记得使用ORB::HARRIS_SCORE类型,因为ORB是一个二进制特性,这将使匹配过程的规范计算实际意味着什么。 / p>