2015-01-19 4 views
3
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와 일치 시키지만 좋은 결과를 얻지는 못합니다. 여기에 문제를 이해하기위한 이미지를 추가하고 있습니다 Finding Object Image from frame Image 효율적으로 얻는 방법 opencv 2.4.9를 사용하여 ORB에서 결과를 얻으려면?

여기에 일치하는 키 포인트로 객체가 인식 될 때 프레임 이미지에서 객체 주위에 실제로 그려지는 사각형 인 테디의 진한 파란색 선을 볼 수 있습니다. 여기 Opencv 2.4.9를 사용하고 있는데, 좋은 결과를 얻으려면 어떻게해야합니까?

+0

"효율적"에 대한 기준을 정하십시오. – rayryeng

+0

빠르고 신뢰성이 높습니다. 나는 좋은 결과를 얻지 못하고 있습니다. 일치 효율은 30 %입니다. –

+0

정확히 무엇을 탐지하려고하는지에 대한 설명도 제공해야합니다. 간단히 코드 덤핑과 우리가 당신의 코드를 통과 할 것으로 기대하는 것은 아무런 관심을 끌지 않을 것입니다 ... 누군가 (그러나 나)로부터 아무런 의견도없이 질문을 올린 지 4 일이 지났음을 알 수 있습니다. – rayryeng

답변

5

임의의 피쳐 검출 + 추출 후 호모 그래피 추정에 사용되는 많은 매개 변수가 있습니다. 그러나 실현해야 할 요점은 거의 항상 계산 시간 VS의 문제입니다. 정확도.

cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10); 
  1. 첫 번째 매개 변수는 검출기에서 상위 25 개 결과를 사용하여 추출을 알려줍니다 : 가장 중요한이 코드의 지점을 실패

    는 ORB 초기화입니다. 매개 변수에 제약이없는 8 자유도 호모 그래피의 신뢰할 수있는 추정을 위해서는 매개 변수보다 더 많은 기능 즉, 80보다 더 많은 기능이 있거나 단지 100으로 설정해야합니다.

  2. 두 번째 매개 변수는 이미지 크기를 줄이기위한 것입니다 (또는 레벨의 검출기 패치). 숫자 1.0f을 사용하면 옥타브 사이의 눈금을 변경하지 않는다는 것을 의미합니다. 특히 세 번째 매개 변수는 2가 아닌 1의 숫자가 아니기 때문에 의미가 없습니다. 기본값은 축척의 경우 1.2f이고 계산의 경우는 8 수준입니다. 1.5f4 레벨의 비율을 사용하십시오 (다시 한번 제안 만하면 다른 매개 변수도 작동합니다).
  3. 네 번째 및 마지막 매개 변수는 계산할 패치 크기가 10x10이라고 말하면서 매우 작지만, 저해상도로 작업하면 괜찮습니다.
  4. 점수 유형 (마지막 매개 변수 이전에 하나)은 런타임을 조금 변경할 수 있습니다. ORB::HARRIS_SCORE 대신 ORB::FAST_SCORE을 사용할 수 있지만별로 중요하지 않습니다.

마지막으로 당신이 BruteForce Matcher를 개체를 초기화 할 때, 당신은 ORB는 바이너리 기능이기 때문에 실제로 무언가를 의미,이 일치 과정에 대한 표준의 계산을 할 cv::NORM_HAMMING 유형을 사용하는 것을 기억해야한다,하지 이상.

+0

대단히 감사합니다. 당신의 대답이 나를 도왔습니다. –