RGB 컬러 공간 분리 – 메뉴 기반 구현

이번에는 본격적으로 OpenCV를 사용하여 영상처리를 해 보겠습니다. 그 첫 단계로 메뉴기반 정지영상 처리를 해 볼 것이며, cvSplit함수를 사용하여 RGB 컬러공간을 분리하는 예제를 구현해 보겠습니다.

 

먼저 OpenCV 2.1 C API Reference에서 cvSplit함수를 찾아보면 다음과 같습니다.

cvSplit함수는 다중 채널(Multi-channel)배열을 여러 개의 단일 채널(Single-channel) 배열로 분할하거나, 배열에서 단일 채널을 추출 할 수 있음을 알 수 있습니다.

또한, 입력이 IplImage인 경우에는 cvCopy함수를 사용해서도 같은 결과를 얻을 수 있음을 알 수 있습니다.

 

이미 “영상처리 프로그래밍 by Visual C++”에서 해 본 것처럼 별도의 Class를 만들고 이를 호출하는 방식으로 예제를 구현해 보겠습니다.

 

먼저 해당 기능을 구현할 Class를 만듭니다. 저는 CDeiosColor라고 하겠습니다.

MFC를 공부할 때 헝가리언 표기법(Hungarian notation)을 알아둔다면 많은 도움이 됩니다. MS가 .Net에서 헝가리언 표기법을 포기했다고는 하지만 많은 이름들이 헝가리언 표기법을 근사적으로 따릅니다. 헝가리언 표기법을 반드시 따를 필요는 없지만 대략적으로 봐 둔다면 MFC프로그래밍 뿐만 아니라 각종 라이브러리 사용 시에 많은 도움이 됩니다. 자신만의 코딩 스타일을 만들어서 일관적으로 사용한다면 과거에 만들었던 코드를 분석하거나 디버깅 할 때에 많은 도움을 받게 될 것입니다.

참고로 Class 이름(DeiosColor) 앞의 C는 Class임을 알려주는 MS의 코딩 스타일입니다.

클래스 뷰에서 마우스 오른쪽 버튼을 클릭하고, [추가] → [클래스]를 선택하여 클래스 추가 마법사를 실행합니다.

 

[C++ 클래스]를 선택하여 일반 Class를 만든 후 클래스 이름을 지정해 주고 [마침]을 클릭합니다.

 

다음으로 멤버 함수를 추가하겠습니다. 멤버 함수는 DSplitRGB이며 함수 원형은 다음과 같습니다.

void DSplitRGB(IplImage *color_image, IplImage **red, IplImage **green, IplImage **blue)

헤더 파일(DeiosColor.h)에 cv.h를 include 한 후, 소스 파일(DeiosColor.cpp)에 다음과 같이 코딩합니다.

void CDeiosColor::DSplitRGB(IplImage * color_image, IplImage ** red, IplImage ** green, IplImage ** blue)

{

        *red = cvCreateImage(cvGetSize(color_image), IPL_DEPTH_8U,1);

        *green = cvCreateImage(cvGetSize(color_image), IPL_DEPTH_8U,1);

        *blue = cvCreateImage(cvGetSize(color_image), IPL_DEPTH_8U,1);

 

        cvSplit(color_image, *red, *green, *blue, NULL);

}

이번에는 새로운 메뉴를 등록해 보겠습니다. MFC 리소스 뷰의 메뉴 항목을 보면 다음과 같은 4개의 리소스가 보입니다.

 

이 중 IDR_MAINFRAME은 문서가 하나도 생성되지 않은 시점의 메뉴를, IDR_MFC_OpenCVTYPE은 한 개 이상의 문서가 생성된 시점의 메뉴를, IDR_POPUP_EDIT은 팝업 메뉴를 의미합니다. 우리는 한 개의 문서(사진)을 필요로 하기 때문에 IDR_MFC_OpenCVTYPE리소스를 편집해야 합니다.

다음과 같은 모양으로 메뉴를 편집하고 다음과 같은 속성을 줍니다.

이번에는 Split RGB메뉴를 클릭했을 때 발생할 이벤트를 처리하는 이벤트 처리기를 등록해 보겠습니다.

[Ctrl + Shift + X]키를 누르면 [Class Wizard]가 열립니다.

 

“DeiosColor.h”파일을 include한 후 다음과 같이 코딩합니다.

void CMFC_OpenCVView::OnColorSplitRgb()

{

        // TODO: 여기에 명령 처리기 코드를 추가합니다.

        CMFC_OpenCVDoc* pDoc = GetDocument();  

        ASSERT_VALID(pDoc);  

 

        IplImage *color_image = pDoc->m_CvvImage.GetImage();  

 

        if( color_image->nChannels != 3 ){  

            AfxMessageBox( TEXT("컬러 영상이 아닙니다."), MB_ICONSTOP );  

            return;  

        }

 

        IplImage *red, *green, *blue;  

           

        CDeiosColor cColor;  

        cColor.DSplitRGB( color_image, &red, &green, &blue );  

 

        pDoc->CopyClipBoard( red );

        ((CMFC_OpenCVApp *)AfxGetApp())->OnEditPaste();

        CMFC_OpenCVDoc *pDoc1 = (CMFC_OpenCVDoc *)((CMDIFrameWnd*)AfxGetMainWnd())->GetActiveFrame()->GetActiveDocument();  

        pDoc1->SetTitle(TEXT("[SplitRGB()] 변환 결과 - 빨강 채널"));  

 

        pDoc->CopyClipBoard( green );  

        ((CMFC_OpenCVApp *)AfxGetApp())->OnEditPaste();

        CMFC_OpenCVDoc *pDoc2 = (CMFC_OpenCVDoc *)((CMDIFrameWnd*)AfxGetMainWnd())->GetActiveFrame()->GetActiveDocument();  

        pDoc2->SetTitle(TEXT("[SplitRGB()] 변환 결과 - 녹색 채널"));  

 

        pDoc->CopyClipBoard( blue );  

        ((CMFC_OpenCVApp *)AfxGetApp())->OnEditPaste();

        CMFC_OpenCVDoc *pDoc3 = (CMFC_OpenCVDoc *)((CMDIFrameWnd*)AfxGetMainWnd())->GetActiveFrame()->GetActiveDocument();  

        pDoc3->SetTitle(TEXT("[SplitRGB()] 변환 결과 - 파랑 채널"));  

 

        cvReleaseImage( &red );  

        cvReleaseImage( &green );  

        cvReleaseImage( &blue );  

 

        Invalidate( FALSE );  

}

마지막으로 MFC_OpenCV.h에서 OnEditPaste를 public으로 바꿔줍니다.

 

Reference
정성환외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/274p~287p
최호성/Visual C++ 2008 MFC 윈도우 프로그래밍/프리렉/2009/669p~674p
OpenCV 2.1.0 The Reference Manual/127p

 

cfile10.uf.123821514D28B1571795C9.pdfcfile7.uf.184156574D28B1ED16BFD9.zip

One thought to “RGB 컬러 공간 분리 – 메뉴 기반 구현”

댓글 남기기

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