특징점 검출하고 매칭하는 방법중에서

실시간으로 물체를 감시하는데에는 어떤 것이 가장 좋을지 알아보기 위해

하나씩 결과를 보는 중이다.

실시간으로 사용하기에는 SURF가 가장 적합할 것이라는 건 알지만

얼마나 차이가 나는지 확인해보고 싶어졌기 때문에 구현했다.

 

먼저 SIFT먼저 소스를 찾아 구현해보았는데,

읽어보고 있던 책을 촬영해 DB로 사용했고,

실시간 캠 영상에서 책을 촬영해 어느정도 되는지 확인했다.

OpenCV 안의 SIFT 속도는 실시간으로는 적합해 보이지 않는다.

 

SURF를 구현하려면

FeatureDetector와 DescriptororExtractor 구조체 앞의 Sift를 Surf로 변경해주면 된다.

 

예제는 다음과 같다.

 


#include "stdafx.h"
#include <opencv/cv.h>
#include <opencv/highgui.h>

#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/nonfree/features2d.hpp>

#include <iostream>
#include <cstdlib>

int _tmain(int argc, _TCHAR* argv[])
{
 // webcam routine
 cv::VideoCapture capture(0);

 if (!capture.isOpened()) {
  std::cerr << "Could not open camera" << std::endl;
  return 0;
 }

 // create a window
 cv::namedWindow("webcam", 1);

 // SIFT configuration
 /*if (argc != 2) {
  std::cerr << "usage: ocv_cam_sift filename" << std::endl;
  return 0;
 }*/

 cv::Mat db_original = cv::imread("book.png", CV_LOAD_IMAGE_GRAYSCALE);
 cv::Mat db;

 cv::resize(db_original, db, cv::Size(db_original.cols / 2, db_original.rows / 2), 0, 0, CV_INTER_NN);

 // SIFT feature detector and feature extractor
 cv::SiftFeatureDetector detector(0.05, 5.0);
 cv::SiftDescriptorExtractor extractor(3.0);

 // Feature detection
 std::vector<cv::KeyPoint> kps_db;
 detector.detect(db, kps_db);

 // Feature description
 cv::Mat dscr_db;
 extractor.compute(db, kps_db, dscr_db);

 while (true) {
  bool frame_valid = true;

  cv::Mat frame_original;
  cv::Mat frame;

  try {
   capture >> frame_original; // get a new frame from webcam
   // downsample 1/2x
   cv::resize(frame_original, frame, cv::Size(frame_original.cols / 2, frame_original.rows / 2), 0, 0, CV_INTER_NN);
  }
  catch (cv::Exception& e) {
   std::cerr << "Exception occurred. Ignoring frame... " << e.err << std::endl;
   frame_valid = false;
  }

  if (frame_valid) {
   try {
    // convert captured frame to grayscale & equlize
    cv::Mat grayframe;
    cv::cvtColor(frame, grayframe, CV_BGR2GRAY);
    cv::equalizeHist(grayframe, grayframe);

    // detection routine

    // keypoint detection
    std::vector<cv::KeyPoint> kps_frame;
    detector.detect(grayframe, kps_frame);

    // keypoint description
    cv::Mat dscr_frame;
    extractor.compute(grayframe, kps_frame, dscr_frame);

    // matching using FLANN matcher
    cv::FlannBasedMatcher matcher;
    std::vector<cv::DMatch> matches;
    matcher.match(dscr_db, dscr_frame, matches);

    double max_dist = 0.0, min_dist = 100.0;

    for (int i = 0; i < matches.size(); i++) {
     double dist = matches[i].distance;
     if (dist < min_dist) min_dist = dist;
     if (dist > max_dist) max_dist = dist;
    }

    // drawing only good matches (dist less than 2*min_dist)
    std::vector<cv::DMatch> good_matches;

    for (int i = 0; i < matches.size(); i++) {
     if (matches[i].distance <= 2 * min_dist) {
      good_matches.push_back(matches[i]);
     }
    }

    cv::Mat img_matches;
    cv::drawMatches(db, kps_db, frame, kps_frame, good_matches, img_matches, cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

    // print the output
    cv::imshow("webcam", img_matches);
   }
   catch (cv::Exception& e) {
    std::cerr << "Exception occurred. Ignoring frame... " << e.err << std::endl;
   }
  }
  if (cv::waitKey(30) >= 0) break;
 }
 return 0;
}

 

+ Recent posts