-
[OpenCV] Webcam을 이용해서 SIFT 매칭 예제Tech/Development 2013. 9. 14. 01:05
이전에 OpenCV를 이용해서 간단히 웹캠을 화면에 출력하는 코드 템플릿을 올렸다. 그런데, 포스팅이 심심하다는 생각이 들어서 얼굴 인식을 넣어서 포스팅을 한번 더 했었다.
2013/09/12 - [Research/Vision] - [OpenCV] OpenCV를 이용해 기본적인 Webcam 출력하기
2013/09/13 - [Research/Vision] - [OpenCV] Webcam을 이용해서 얼굴을 인식하는 간단한 예제
기왕 한 김에 이번엔 SIFT도 포스팅해야겠다고 생각했다. OpenCV에 라이브러리로 들어가 있으니 아주 쉽게 사용할 수 있다. 많이들 쓰는 lena를 DB로 써서 웹캠과 매칭되는 걸 테스트해보았다. 역시 명불허전이다. 대충 들고 있어도 매칭이 잘 된다.
/* * @file ocv_cam_sift.cc * @brief SIFT using OpenCV with Webcam * @author http://thinkpiece.tistory.com */ #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 main(int argc, char *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(argv[1],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 cv::resize(frame_original,frame,cv::Size(frame_original.cols/2, frame_original.rows/2),0,0,CV_INTER_NN); // downsample 1/2x } 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 gray scale & equalize cv::Mat grayframe; cv::cvtColor(frame, grayframe, CV_BGR2GRAY); cv::equalizeHist(grayframe,grayframe); // ------------------------------------------------------------- // face 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; } // VideoCapture automatically deallocate camera object return 0; }