ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [OpenCV] Webcam을 이용해서 SIFT 매칭 예제
    Tech/Development 2013.09.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;
    }
    

    TAG

    댓글 19

    • 프로필사진

      다른 소스들은 다 되고 SIFT를 이용하여 웹캠에서 매칭은 자꾸 오류가 나네요.

      1>test.obj : error LNK2019: "public: __thiscall cv::SIFT::SIFT(int,int,double,double,double)" (??0SIFT@cv@@QAE@HHNNN@Z) 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
      1>C:\Users\kwu\Desktop\realtime test\test\Debug\test.exe : fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.

      이렇게 뜨는데 오류를 못잡겠네요 ㅠㅠ

      2014.04.08 18:28 신고
    • 프로필사진

      아 해결됐습니다.
      라이브러리 경로가 꼬여있던게 문제 였네요 ㅠㅠ
      덕분에 이 사이트에서 많은 것을 배우고 갑니다.
      감사합니다~^^

      2014.04.09 16:46 신고
    • 프로필사진

      안녕하세요 게시물 잘 보고 있습니다.
      코드 내에 검출하고자하는 이미지 파일 부분이 몇번째줄인가요??
      lena로 찾아봐도 없고.. 잘 못찾겠습니다
      도움주시면 감사하겠습니다!

      2014.04.29 23:14 신고
      • 프로필사진

        cv::Mat db_original = cv::imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);

        이 부분이구요. 정확히 말해서는 lena.jpg 라고 입력하는 부분은 없고, 프로그램을 실행할 때 첫번째 매개변수 (argv[1])로 넘겨받습니다.

        $ ./test lena.jpg

        이런 식으로 실행하면 되겠죠!

        2014.04.30 13:47 신고
    • 프로필사진

      좋은 자료 감사합니다

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

      실습 중에 이 부분에서 자꾸 연산 속도가 아주 많이 저하 되는데...
      이유와 해결 방법을 알고 싶습니다..ㅠ

      2014.07.10 14:52 신고
      • 프로필사진

        detector.detect() 함수에서는 입력받은 영상(grayframe)에서 특징점을 추출하게되는데, 이 부분이 원래 연산 시간이 오래 걸립니다.
        이를 빠르게 하기 위해서는 1) 직접 detect 함수를 구현하시는 방법(최적화해서 작성하신다면), 2) GPU기반으로 구현된 함수를 이용하는 방법, 3) 다른 종류의 특징점추출 알고리즘을 이용하는 방법, 예를 들어 FAST, SURF 등... 의 3가지 방법이 있겠네요.

        2014.07.15 23:14 신고
    • 프로필사진

      비밀댓글입니다

      2014.07.23 13:26
    • 프로필사진

      이전 얼굴인식 자료는 문제가 없었는데 SIFT는 실행하게 되면 창이 저절로 꺼지는데 왜 그러는건가요? 오류는 없고 워닝에서 타입에 관한거 몇개 뜨긴 하는데 그문제인가요??

      2014.08.05 14:54 신고
    • 프로필사진

      워닝에러는 3가지 거든요 유니코드 문제 C4819 & 데이터 손실 C4244 에러 & 부호에러 C4018 세가지요 이렇게 말씀드리면 이해 되실까요??
      실례가 안된다면 문자로좀 여쭙고 싶은데 010 2042 5767로 문자부탁드리거나 간단한거면 답글좀 부탁드릴게요

      2014.08.11 12:41 신고
      • 프로필사진

        혹시 code에서 어느 부분이 문제가 되었다는 line number도 같이 뜨지 않나요? warning line number 알려주시면 아마 답해드릴 수 있을 것 같아요.

        2014.08.19 02:55 신고
    • 프로필사진

      안녕하세요 계속 해결이 안되어 질문드립니다. 위의 코드는 잘 실행이 됩니다. 그런데 resize를 빼고 하니 에러가 나는 것을 확인했습니다. 혹시 webcam과 일반 이미지를 matching할 때 size에 따라 문제가 생기는 것인지 궁금하네요..
      calibration을 해야해서 size 변경은 피하고 싶은데 방법이 없을지 궁금합니다..
      drawmatches에서 지속적으로 error가 나옵니다..

      2014.08.14 10:53 신고
    • 프로필사진

      안녕하세요
      라인 넘버 95
      matcher.match(dscr_db, dscr_frame, matches);

      여기서 exception이 발생하면서 꺼저 버리는데, 이건 왜그런지 알수 있나요? 다른 코드에서 knnMatch를 사용해도 동일한 결과가 계속나오네요...

      opencv.exe의 0x5d31aa16에 처리되지 않은 예외가 있습니다. 0xC0000005: 0x00000006 위치를 읽는 동안 액세스 위반이 발생했습니다.

      2014.08.19 16:13 신고
    • 프로필사진

      위에 까지는 실행이 되는데
      이 밑 부분부터 진행이 안되는데 알려 주세요

      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;
      }

      2014.11.25 12:55 신고
    • 프로필사진

      비밀댓글입니다

      2015.04.23 17:54
    • 프로필사진

      에러는 안나는데 실행하면 웹캠도안켜지고 그냥 아무키나누르면 종료된다고 창만뜨네요
      에러가 없어서 더 힘듭니다 ㅜㅜ
      아 그리고 $./lena.jpg 이런식으로쓰고싶은데 어느자리어 어떻게 넣어야 할까요? 죄송해요 너무 잘몰라서 ㅜㅜ

      2016.07.12 17:15 신고
    • 프로필사진

      cv::SiftFeatureDetector detector(0.05, 5.0);
      cv::SiftDescriptorExtractor extractor(3.0);

      이부분에서 SIFT 파라미터 값들 설정해주는 것 같은데요.

      각각 저 값들이 어떤 파라미터인지 알려주실 수 있나요??

      2017.11.14 11:28 신고
Designed by Tistory.