Cfile10.uf .1515CD4D4D35E4C30BD32A

Face Detect

이번 시간은 MFC와 OpenCV의 기본 사용법 마지막 내용이 되겠습니다. Cam 영상을 Dialog에 뿌려주는 부분에서 기본 사용법이 끝났어야 하지만… 조금 아쉬운 관계로 더 진행해 봤죠…

저도 아직 초보단계지만, MFC와 OpenCV의 기본 사용법은 뭐 없습니다… MFC야… GUI프로그래밍을 위해서 그냥 쓴 것이고… OpenCV는 영상을 받아오고, 출력하는 부분만 하면 기본은 끝난거 아닌가요?

 

지금까지 “오픈소스 OpenCV를 이용한 컴퓨터 비전 실무 프로그래밍”이라는 책을 기준으로 진행해 왔는데, 뒷부분을 살펴봐도 뭐 없습니다. 가져온 영상을 OpenCV의 각종 함수들을 사용해서 내가 원하는 데로 조작해서 보여주는 것… 그 이상도 이하도 아닙니다.

 

자… 그럼 마지막 내용 진행해 보겠습니다. 이번 시간에는 간단하게 지난 시간에 만들었던 Dialog를 이용하겠습니다. 버튼 하나 추가하시구요~ 버튼의 ID는 “IDC_btnFaceDetect”로 하겠습니다. 당연히 이벤트 처리기도 추가해야겠죠?

 

OpenCV 2.1은 Camera 영상 처리에서 Callback을 사용하지 않는 관계로 혹은 제가 너무 무식해서 관련 내용을 찾지 못했거나… 불리언(Boolean)타입의 변수 하나를 잡아 flag로 사용하겠습니다.

 

변수 이름은 bFDisTrue로 하겠습니다. Type은 당연히 BOOL이구요, OnInitDialog에서 FALSE로 초기화 해 주는 부분까지 작성하겠습니다. 쉽게 하실 수 있으시죠?

다음은 Face Detect를 수행할 멤버 함수를 작성하겠습니다. 함수 원형은 다음과 같습니다.

void FaceDetect()

여기까지는 무난하게 하셨을거라 보고, 이번에는 “Cam 영상 출력해보기(http://deios.kr/413)”처럼 화면에 뿌려주기 전에 FaceDetect함수를 호출할 수 있도록 수정하겠습니다.

어디를 수정해야 할 지는 잘 아시죠? 당근 OnTimer를 수정해 줘야 합니다. 다음과 같이 수정합니다.

void CViewDlg::OnTimer(UINT_PTR nIDEvent)

{       // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        if(1 == nIDEvent){

                cvGrabFrame( capture );

                image = cvQueryFrame( capture );

                FaceDetect();

                m_CvvImage.CopyOf(image);

                CRect viewSize;

                m_sView.GetClientRect(&viewSize);

                m_CvvImage.DrawToHDC( m_sView.GetDC()->GetSafeHdc() ,viewSize);

        }

        CDialogEx::OnTimer(nIDEvent);

}

IDC_btnFaceDetect 이벤트 처리기에는 bFDisTrue의 값을 TRUE로 바꿔주는 코드를 넣겠습니다. 조금 응용하면 “시작 → 중지”버튼처럼 구현 할 수 있겠죠? 이것은 각자 해보세요~ 이벤트 처리기의 코드는 생략하겠습니다. 빨리 하고 자려구요 ㅠㅠ

Face Detect함수의 코드를 보여드리겠습니다.

void CViewDlg::FaceDetect()

{

        if(!bFDisTrue) return;

        CvScalar colors[] =  {  CV_RGB(0,0,255), CV_RGB(0,128,255), CV_RGB(0,255,255),

                                CV_RGB(0,255,0), CV_RGB(255,128,0), CV_RGB(255,255,0),

                                CV_RGB(255,0,0), CV_RGB(255,0,255)} ;

        double scale = 2.0;

 

        IplImage *gray = cvCreateImage(cvSize(image->width, image->height), 8, 1);

        IplImage *small_img = cvCreateImage(cvSize(cvRound(image->width / scale), cvRound(image->height/scale)), 8, 1);

 

        cvCvtColor(image, gray, CV_BGR2GRAY);

        cvResize(gray, small_img, CV_INTER_LINEAR);

        cvEqualizeHist(small_img, small_img);

        if(storage) cvClearMemStorage(storage);

 

        if(cascade){

                CvSeq *faces = cvHaarDetectObjects(small_img, cascade, storage, 1.1, 2, 0, cvSize(30, 30));

 

                for (int i = 0; i < (faces ? faces->total : 0); i++){

                        CvRect *r = (CvRect *)cvGetSeqElem(faces, i);

 

                        CvPoint center;

                        int radius;

 

                        center.x = cvRound( (r->x + r->width*0.5)*scale);

                        center.y = cvRound( (r->y + r->height*0.5)*scale);

                        radius = cvRound( (r->width + r->height)*0.25*scale);

 

                        cvCircle(image, center, radius, colors[i%8], 3, 8, 0);

                }

        }

 

        cvReleaseImage(&gray);

        cvReleaseImage(&small_img);

}

<

p class=”HStyle0″ style=”line-height: 150%;”>

마지막으로 두 개의 멤버변수를 잡고, 초기화 하겠습니다.

멤버변수는 다음과 같습니다.

CvMemStorage *storage;

CvHaarClassifierCascade *cascade;

초기화는 당연히 OnInitDialog에서 해 줘야 겠죠? 다음과 같이 초기화합니다.

cascade = (CvHaarClassifierCascade *)cvLoad("haarcascade_frontalface_alt2.xml", 0, 0, 0);

storage = cvCreateMemStorage(0);

  

짜짜잔~

 

Cfile10.uf .1515CD4D4D35E4C30BD32A

Cfile23.uf .121672584DF2262B35D013

cfile24.uf.203234514D35E90C11EEEB.pdf

cfile25.uf.123272514D35E5700B95C4.zipcfile25.uf.143192514D35E575139482.xmlcfile9.uf.123324434DEE56BF34AD4F.xml

Similar Posts

  • |

    2계층과 4계층의 오류제어, 흐름제어

    오류제어 및 흐름제어 기능은 계층 2와 4에도 있다. 이들의 차잇점을 쓰시오. 2계층과 4계층의 차이점.2계층은 서로 연결된 두 노드간의 제어이며, 4계층은 단대단 제어이다.따라서 4계층의 오류제어와 흐름제어는 단말과 네트워크를 포함한 제어 기술이다.2계층의 오류 제어는 오류제어를 담당한다. 4계층의 오류제어는 송신측과 수신측 단대단 오류 제어이다.2계층의 흐름제어는 역시 인접노드간의 흐름 제어이고, 4계층의 흐름제어는 단대단 흐름제어이다. 관련된 글: 고속 네트워크 프로토콜의…

  • 프로젝트 설정 파일 적용하기

    이전 시간까지는 처음에 만들었던 “MFC_OpenCV”라는 프로젝트를 기준으로 진행하였습니다. 하지만, 이제부터는 새 프로젝트를 만들어서 진행하는 경우가 많이 생길텐데요… 이 때마다 프로젝트 설정을 바꿔줘야 하는게 여간 귀찮은게 아닙니다… 그. 래. 서. 이번 시간에는 이러한 설정을 파일로 저장하고, 가져오는 방법에 대해서 알아보겠습니다. 일단 첨부한 OpenCV210.props 파일을 적당한 디렉토리에 다운로드 하시구요… 먼저 이 파일을 어떻게 불러오는지부터 알아보겠습니다. 먼저 VS2010실행하셔서…

  • |

    고속 네트워크에서의 메모리 병목 현상

    메모리가 미래 통신에 있어서 병목 지점이 되는 이유를 설명하고 해결 방안을 제시하시오. 1) 메모리는 코드와 데이터를 함께 저장한다. 표현 계층이 개입한다면 메모리 연산이 증가하게 되어 병목 현상이 발생한다. -> 표현계층을 적게 사용한다.2) 각 계층 이동시 메모리 연산 증가. OSI-7-layer에서 각 계층 이동시 메모리 복사가 빈번하게 일어나게 된다. -> shared memory, page remapping, 계층 통합 처리3)…

  • 모덜리스(Modeless) Dialog로 변환하기

    이전 시간에 만들었던 모달(Modal) Dialog를 모덜리스(Modeless) Dialog로 변환해 보겠습니다. Modal Dialog는 Dialog가 실행되는 동안 다른 작업을 하지 못하고, Modeless Dialog는 프로그램 실행 흐름을 방해하지 않는다는 것 정도는 알고 계시죠? 자 그럼 이전 시간 “MFC – Cam 영상 출력해보기(http://deios.kr/420)”에 만들었던 View Dialog를 멋지게 바꿔 보겠습니다.   OnCamView함수를 다음과 같이 수정합니다. void CMFC_OpenCVApp::OnCamView() {       // TODO: 여기에 명령…

12 Comments

  1. scale이 클 수록 더 빨리 영상을 처리하게 됩니다. 처음엔 인터발을 (1/12)*1000주고, scale을 1.2 줬는데… 뭐 이건 영상을 볼 수가 없더군요… 그래서 scale만 2.0으로 올렸더니 어느정도 봐 줄만 합니다…

  2. 얼굴을 잘 잡지를 못하고 벽이나 다른 곳을 잡습니다.

    xml 파일만 교체해도 이 코드가 실행되는지 궁금합니다. ^^

    1. 정면이 아닌 측면얼굴이나, 하단에서 올려다볼때, 상단에서 올려다볼때는 인식을 하지 못합니다 ㅠㅠ
      파일 이름도
      haarcascade_eye_tree_eyeglasses 와
      haarcascade_frontalface_alt2죠…

  3. 그 전에 face detect 예제를 돌려보았던 차여서 haarcascade_frontalface_alt2.xml 는 있었습니다.
    OpenCV 1.0 예제에 있는 facedetect 와 haarcascade_frontalface_alt2.xml 파일명도 같고 소스 코드도 비슷한데 잡히는 정도가 다르네요. 1.0 예제의 코드는 안경을 쓰고 있어도 매우 잘 잡고 있기에
    어떠한 차이점이 있는지 궁금하네요. Deios 님의 완성된 코드로 직접 실행해보셨을 때에는 잘 잡히시는지요?

    1. 1.0과의 차이점은 콜백 사용여부입니다.
      1.0은 콜백함수를 사용하여 OpenCV가 영상을 보여주기 전에 콜백함수를 실행하게 되고 OpenCV가 화면에 영상을 뿌려줍니다…
      2.0부터인가 콜백함수를 사용할 수 없기에 일단 OpenCV로부터 영상을 받아와서 처리후 화면에 뿌려주게 됩니다…
      성능 이슈는 충분히 있을 수 있죠…

    1. 글 작성시엔 스케일이 2.0이였고, 제 경우엔 너무 느려서 3.0정도로 조정하니 봐줄만 했습니다.
      방금 인터벌을 (1/(double)8)*1000 주고, 스케일을 5.0으로 줬는데 무리없이 잘 돌아가네요…
      인터벌과 스케일 모두 작을수록 좋습니다…
      벽이 잡힌다고 하시니 해당 문제는 아니겠지만 혹시나 해서 스케일과 인터벌을 조정해보라 말씀드린겁니다…

      안경 쓴 상태에서 인식한 화면 올려둘께요~
      제가 사용한 코드는 본문에 첨부된 파일 그대로입니다…(스케일과 인터벌만 수정)

  4. 좋은 예시 감사하고 . 초보라서 그런데..detection된 원 모양을 직사각형이나 정사각형으로 나타내게 할려면 어떤 함수를 써야되나요?
    답변 부탁드립니다.

  5. 올려주신 글을 보고 공부 많이 하고있습니다. 감사합니다.
    올려주신 예제를 따라하고 있는데요. 얼굴 검출이 안되요.ㅠ
    그래서 if(cascade)아래
    AfxMessageBox(_T(“1”) )로 들어가는지 봤더니 안들어가더군요.
    왜그런걸까요?

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다