D's World

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

Exit mobile version