ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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;
    }
    

    댓글

Copyright 2022 JY