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

  

짜짜잔~

 

cfile24.uf.203234514D35E90C11EEEB.pdf

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

12 thoughts to “Face Detect”

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

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

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

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


    2. haarcascade_frontalface_alt2.xml
      파일은 따로 올리지 않았군요…
      첨부하겠습니다~

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

    1. 네… 저도 안경을 쓰고 있는데 정면은 잘 됩니다.
      스케일과 인터벌을 조정해 보세요~

    2. 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”) )로 들어가는지 봤더니 안들어가더군요.
    왜그런걸까요?

류진모 에 응답 남기기 응답 취소

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.