Cfile7.uf .181B1C494D2DEE9C0EF174

공간 영역 필터링 – Dialog Box 기반 구현

이번 시간에는 Dialog Box기반으로 OpenCV를 이용하는 방법에 대해서 알아보겠습니다.

 

공간 필터링(Spatial Filtering)이란 영상에 있는 공간 주파수 대역을 제거하거나 강조하는 필터 처리입니다. 사용되는 필터의 계수에 따라 특정 주파수를 제거하거나 강조하게 되며, 필터 마스크(Filter Mask)또는 회선 마스크의 가중치 선택이 공간 필터의 행동을 결정하게 됩니다. 영상처리에 사용되는 회선 마스크는 홀수 차원의 정방형 마스크가 사용되게 됩니다.

 

필터는 입력되는 신호의 일부 성분을 제거하거나 일부 특성을 변경하려고 설계된 하나의 시스템이며 두 종류로 구분됩니다. 첫 번째는 필터의 길이가 한정된 유한임펄스응답(FIR ; Finite Impulse Response)필터이고, 두 번째는 필터의 길이가 무한정한 무한임펄스응답(IIR ; Infinite Impulse Respones)필터입니다. FIR필터는 필터를 설계하기가 쉬우며 따라서 신호도 쉽게 처리할 수 있는 장점을 가지고 있습니다. IIR필터는 필터를 설계하기가 어려우나 필터의 특성은 더 우수합니다. 영상처리에서는 FIR 필터를 더 많이 사용합니다.

 

컨벌루션(회선;Convolution)이란 선형 시불변 시스템에 입력되는 신호가 어떤 신호를 출력하는지 결정하는 식을 의미합니다.

 

영상처리는 가로방향과 세로 방향의 처리가 필요한 2차원 처리이며, 필터링을 이용한 영상처리는 2차원의 컨벌루션을 수행하는 것입니다.

 

OpenCV에서 마스크 모양의 커널(Kernel)을 회선하는 함수는 cvFilter2D입니다. 이 함수를 레퍼런스에서 찾아보면 다음과 같습니다.

Cfile27.uf .13119F484D2DEE9C12A5E9

 

cvFilter2D함수는 src영상을 받아 kernel을 가지고 필터링 한 후 dst로 출력해 줍니다. 여기서 anchor은 어느 지점부터 필터링을 시작할 지를 결정해 주는 값이며 기본으로 (-1, -1)위치가 지정됩니다. 이는 공간영역 필터링에서 주변에 테두리가 생기지 않게 됩니다.

Cfile7.uf .181B1C494D2DEE9C0EF174

 

이번에 구현할 필터 마스크(Kernel)은 다음과 같습니다.

1. soften filter – 부드러운 효과
Cfile23.uf .195B644F4D2DEE9D047227

 

2. Enhance focus filter – 물체를 둘러싼 것을 초점을 맞춘 효과
Cfile1.uf .19316A534D2DEE9D082E59

 

3. Enhance detail filter – 물체를 둘러싼 것을 상세히 드러냄
Cfile22.uf .1464884C4D2DEE9E0B15A0

 

4. Blur light filter – 블러링 단점인 잡음 미제거 보안 효과
Cfile30.uf .15331E4A4D2DEE9E0CFA35

 

5. Gaussian filter – 블러링 단점인 잡음 미제거 보안 효과
Cfile3.uf .1345BB4E4D2DEE9F05B9F6

 

먼저 DeiosImgUtil Class를 작성하도록 하겠습니다. 이 DeiosImgUtil Class에는 이미지의 너비가 4의 배수가 되도록 조정하는 멤버 함수와 이미지를 HBITMAP으로 변환하는 멤버 함수가 들어갑니다.

 

Class를 만든 후 Resize4Bitmap함수와 IplImage2Bitmap함수를 추가합니다. 원형은 다음과 같습니다.

IplImage *Resize4Bitmap(int resize_height, int resize_width, IplImage * image)

HBITMAP IplImage2Bitmap(IplImage * image)

다음과 같이 작성합니다.

// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/324p~325p

IplImage *CDeiosImgUtil::Resize4Bitmap(int resize_height, int resize_width, IplImage * image){

        int height = image->height;

        int width = image->width - (image->width%4);

 

        int sHeight = height;

        int sWidth = width;

 

        if( (height > resize_height) && (width > resize_width) ){

                sHeight = resize_width;

                width = (int) (width*(resize_height/(double)height));

                sWidth = width - (width%4);

        }else if( height > resize_height) sHeight = resize_height;

        else if( width > resize_width) sWidth = resize_width - (resize_width%4);

 

        IplImage *resize_image = cvCreateImage(cvSize(sWidth, sHeight), IPL_DEPTH_8U, image->nChannels);

 

        cvResize(image, resize_image, CV_INTER_CUBIC);

 

        return resize_image;

}
// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/325p~326p

HBITMAP CDeiosImgUtil::IplImage2Bitmap(IplImage *image ){

        HDC hDC=::CreateCompatibleDC(0);

        BYTE tmp[sizeof(BITMAPINFO)+255*4 ];

        BITMAPINFO *bmi = (BITMAPINFO *) tmp;

        HBITMAP hBmp;

 

        int height = image->height;

        int width = image->width;

        int widthStep = width +(width % 4);

        int nChannels = image->nChannels;

        int bpp = 8*nChannels;

        int bmpDataSize = height*widthStep*nChannels;

 

        memset( bmi, 0, sizeof(BITMAPINFO) );

        bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

        bmi->bmiHeader.biHeight = height; // 영상의 높이

        bmi->bmiHeader.biWidth = width; //영상의 너비

        bmi->bmiHeader.biPlanes = 1; // 비트 플레인 수 (항상 1임)

        bmi->bmiHeader.biBitCount = bpp; // 한 화소당 비트 개수

        bmi->bmiHeader.biCompression = BI_RGB; // BI_RGB: 압축하지 않음.

        bmi->bmiHeader.biSizeImage = bmpDataSize; // 영상의 크기

        bmi->bmiHeader.biClrUsed = 0;

 

        if( bpp == 8 ){

                for( int i=0; i<256; i++ ){

                        bmi->bmiColors[i].rgbBlue = i;

                        bmi->bmiColors[i].rgbGreen = i;

                        bmi->bmiColors[i].rgbRed = i;

                }

        }

 

        hBmp = ::CreateDIBSection( hDC, bmi, DIB_RGB_COLORS, NULL, 0, 0 );

        ::DeleteDC(hDC);

 

        ::SetBitmapBits( hBmp, image->imageSize, image->imageData );

 

        return hBmp;

}

이번에는 해당 기능을 구현할 Filter Class를 만듭니다.

Filter Class에는 오버로딩 된 ApplyFilter2D멤버 함수가 작성됩니다.

원형은 다음과 같습니다.

IplImage * ApplyFilter2D(IplImage * src, float *kernel, int kHeight, int kWidth);

IplImage * ApplyFilter2D(IplImage * src, float **kernel, int kHeight, int kWidth);

IplImage * ApplyFilter2D(IplImage * src, CvMat kernel);

다음과 같이 코드를 작성합니다.

// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/295p

IplImage * CFilter::ApplyFilter2D(IplImage * src, float *kernel, int kHeight, int kWidth){

        CvMat mat_kernel = cvMat( kWidth, kHeight, CV_32FC1, kernel );  

 

        IplImage *dst = ApplyFilter2D( src, mat_kernel );  

 

        cvReleaseData( &mat_kernel );  

 

        return dst;  

}
// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/295p~296p

IplImage * CFilter::ApplyFilter2D(IplImage * src, float **kernel, int kHeight, int kWidth){

        int cnt = -1;  

 

        float *single_kernel = (float *)calloc( kHeight*kWidth, sizeof(float) );  

 

        for(int i = 0; i < kHeight ; i++)

                for(int j = 0; j
// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/296p

IplImage * CFilter::ApplyFilter2D(IplImage * src, CvMat kernel){

        IplImage *dst = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, src->nChannels);

 

        cvFilter2D(src, dst, &kernel, cvPoint(-1, -1));

 

        return dst;

}

이제 UI를 설계해 보겠습니다. [리소스뷰] -> [Dialog] -> [Dialog 삽입]을 선택합니다.

Cfile2.uf .171ACA494D2DEE9F0F2D4B

다음과 같이 컨트롤 들을 배열합니다.

Cfile10.uf .162378594D2DEEA017C669

 

Picture Control의 속성을 다음과 같이 지정합니다.

Cfile23.uf .151B40494D2DEEA014797A

ID : IDC_PREVIEW_IMAGE

Type : Bitmap

Sunken : True

Center Image : True

 

비슷한 방법으로 Combo Box의 속성을 다음과 같이 지정합니다.

ID : IDC_COMBO_FILTER_TYPE

Type : Drop List

 

이번에는 2개의 Button중 첫 번째 Button의 속성을 설정하겠습니다.

ID : IDC_PREVIEW_BUTTON

Caption : 미리보기

 

2번째 Button의 속성을 설정하겠습니다.

ID : IDC_INITIAL_BUTTON

Caption : 초기화

 

이번에는 Dialog의 ID를 지정해 줍니다.

ID : IDD_FILTER_DIALOG

 

이제 만들어진 Dialog에 대응하는 Class를 추가합니다.

[Shift + Alt + C]버튼을 눌러 Class 추가 마법사를 실행합니다. 클래스 이름은 FilterDlg로 합니다.

Cfile23.uf .17223B524D2DEEA10D5EAF

 

이번에는 Dialog의 각 Control에 대응하는 멤버 변수를 추가해 보겠습니다.

 

모든 Control의 멤버 변수를 추가할 필요는 없으며, 입력과 출력을 필요로 하는 Control의 멤버 변수만 추가하면 됩니다.

[Ctrl + Shift + X]키를 눌러 Class 마법사를 실행합니다.

CFilterDlg Class의 IDC_COMBO_FILTER_TYPE Control의 멤버 변수를 추가합니다.

클래스 이름과 멤버 변수를 확인 후, 변수 추가 버튼을 클릭합니다.

Cfile29.uf .17328A564D2DEEA11D5F5D

 

멤버 변수 이름을 m_combo_filter로 지정합니다.

Cfile22.uf .1828AE574D2DEEA211C7D3

 

동일한 방법으로 다음과 같은 멤버 변수를 추가합니다.

IDC_PREVIREW_IMAGE : m_preview_image

이번에는 Dialog 초기화 코드를 작성하겠습니다.

Cfile5.uf .202DF2504D2DEEA203DB64

 

마찬가지 방법으로 OnDestroy멤버 함수도 추가해 줍니다.

 

이제 FilterDlg.h 파일을 열어 다음과 같은 멤버 변수를 추가합니다.

CvvImage d_org_cvvImage; // 원 영상

CvvImage d_cvvImage; // 필터링 결과 후의 영상

int picture_height; // Picture 컨트롤의 높이 기준 

int picture_width; // Picture 컨트롤의 너비 기준(4의 배수)

float soften_mask[9]; // For Soften filtering

float ef_mask[9]; // For Enhance focus filtering

float ed_mask[9]; // For Enhance detail filtering

float bl_mask[9]; // For Blur light filtering

float bb_mask[9]; // For Blur blending filtering

이번에는 각종 헤더 파일을 include 하겠습니다.

#include "MainFrm.h"

#include "ChildFrm.h"

#include "MFC_OpenCVDoc.h"

#include "Filter.h"

#include "DeiosImgUtil.h"

OnInitDialog멤버 함수에 다음과 같이 코딩합니다.

// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/317p~320p

BOOL CFilterDlg::OnInitDialog(){

        CDialogEx::OnInitDialog();

 

        // TODO:  여기에 추가 초기화 작업을 추가합니다.

 

        // STEP 1 : Picture 컨트롤 크기 초기화 

        picture_height = 228; // Picture 컨트롤의 높이 기준 

        picture_width = 328; // Picture 컨트롤의 너비 기준(4의 배수)

 

        // STEP 2 : 필터 마스크 초기화

 

        // STEP 2-1 : Soften filter - 부드러운 효과를 냄.

        float _mask1[] = {      1.0f/18.0f,  1.0f/18.0f, 1.0f/18.0f,

                                                1.0f/18.0f, 10.0f/18.0f, 1.0f/18.0f,

                                                1.0f/18.0f,  1.0f/18.0f, 1.0f/18.0f };

        memcpy( soften_mask, _mask1, sizeof(float)*9 );

 

        // STEP 2-2 : Enhance focus filter - 물체를 둘러싼 것을 초점을 맞춘 효과를 냄.

        float _mask2[] = {      -1.0f/3.0f,  0.0f/3.0f, -1.0f/3.0f,

                                                0.0f/3.0f,  7.0f/3.0f,  0.0f/3.0f,

                                                -1.0f/3.0f,  0.0f/3.0f, -1.0f/3.0f };

        memcpy( ef_mask, _mask2, sizeof(float)*9 );

 

        // STEP 2-3 : Enhance detail filter - 물체를 둘러싼 것을 상세히 드러내는 효과를 냄.

        float _mask3[] = {      0.0f/5.0f, -1.0f/5.0f,  0.0f/5.0f,

                                                -1.0f/5.0f,  9.0f/5.0f, -1.0f/5.0f,

                                                0.0f/5.0f, -1.0f/5.0f,  0.0f/5.0f };

        memcpy( ed_mask, _mask3, sizeof(float)*9 );

 

        // STEP 2-4 : Blur light filter - 블러링 단점인 잡음 미제거 보완 효과를 냄.

        float _mask4[] = {      1.0f/14.0f, 1.0f/14.0f, 1.0f/14.0f,

                                                2.0f/14.0f, 2.0f/14.0f, 2.0f/14.0f,

                                                1.0f/14.0f, 1.0f/14.0f, 1.0f/14.0f };

        memcpy( bl_mask, _mask4, sizeof(float)*9 );

 

        // STEP 2-5 : Blur blending filter - 블러링 단점인 잡음 미제거 보완 효과를 냄.

        float _mask5[] = {      1.0f/16.0f, 2.0f/16.0f, 1.0f/16.0f,

                                                2.0f/16.0f, 4.0f/16.0f, 2.0f/16.0f,

                                                1.0f/16.0f, 2.0f/16.0f, 1.0f/16.0f };

        memcpy( bb_mask, _mask5, sizeof(float)*9 );

 

        // STEP 3 : 콤보 박스에 항목 추가 

        CString strFilterList[] = { _T( "Soften filter" ), _T( "Enhance focus filter" ), _T( "Enhance detail filter" ), _T( "Blur light filter" ),_T( "Blur blending filter" )};

 

        int length = sizeof(strFilterList) / sizeof(CString);

        for(int i = 0; i< length ; i++)

                m_combo_filter.AddString(strFilterList[i]);

 

        CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();

        CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();

        CMFC_OpenCVDoc *pDoc = (CMFC_OpenCVDoc *)pChild->GetActiveDocument();

 

        // STEP 5 : 원 영상을 복사

        d_org_cvvImage.CopyOf( pDoc->m_CvvImage.GetImage(), pDoc->m_CvvImage.GetImage()->nChannels*8 );

        d_cvvImage.CopyOf( pDoc->m_CvvImage.GetImage(), pDoc->m_CvvImage.GetImage()->nChannels*8 );

 

        // STEP 6 : 원 영상을 비트맵으로 변환하기 위한 영상 크기 재조절

        CDeiosImgUtil cUtil;

 

        // (주의!) BITMAP의 특성 : 가로의 길이가 4의 배수가 아니면 찌그러짐

        IplImage *image = d_org_cvvImage.GetImage();

        IplImage *resize_image = cUtil.Resize4Bitmap( picture_height, picture_width, image );

 

        HBITMAP hBitmap = cUtil.IplImage2Bitmap( resize_image );

        cvReleaseImage( &resize_image );

 

        // STEP 7 : 변환한 비트맵을 m_preview 즉, picture 컨트롤에 뿌려준다.

        m_preview_image.SetBitmap( hBitmap );

 

        // STEP 8 : 화면 갱신

        UpdateData( FALSE ); 

 

        return TRUE;  // return TRUE unless you set the focus to a control

        // 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.

}

이번에는 미리보기 Button에 해당하는 멤버 함수를 작성해 보겠습니다.

FilterDlg Class의 이벤트 영역에서 IDC_PREVIEW_BUTTON을 선택 한 후 BN_CLICKED를 선택하여 메시지 처리기를 추가합니다.

Cfile7.uf .181B1C494D2DEE9C0EF174

 

다음과 같이 코딩합니다.

// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/328p~330p

void CFilterDlg::OnBnClickedPreviewButton()

{

        // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

        float kernel[9] = {0., };

        int kernel_height = 3;

        int kernel_width = 3;

        int kernel_length = kernel_height*kernel_width;

 

        // STEP 1 : 콤보 박스에서 선택한 항목을 가져오기

        CString str;

        int nIndex = m_combo_filter.GetCurSel();

        if( nIndex == CB_ERR ) return;

        m_combo_filter.GetLBText( nIndex, str );

 

        // STEP 2 : 콤보 박스에서 선택한 필터링 수행 하기 위한 커널 복사

        if( str == "Soften filter" )

                memcpy( kernel, soften_mask, sizeof(float)*kernel_length );

        else if( str == "Enhance focus filter" )

                memcpy( kernel, ef_mask, sizeof(float)*kernel_length );

        else if( str == "Enhance detail filter" )

                memcpy( kernel, ed_mask, sizeof(float)*kernel_length );

        else if( str == "Blur light filter" )

                memcpy( kernel, bl_mask, sizeof(float)*kernel_length );

        else if( str == "Blur blending filter" )

                memcpy( kernel, bb_mask, sizeof(float)*kernel_length );

 

        // STEP 3 : 원 영상을 비트맵으로 변환하기 위한 영상 크기 재조절

        CDeiosImgUtil cUtil;

        IplImage *image = d_cvvImage.GetImage();

        IplImage *resize_image = cUtil.Resize4Bitmap( picture_height, picture_width, image );

 

        // STEP 4 : 공간 영역 필터링 수행

        CFilter cFilter;

        IplImage *filtered_image = cFilter.ApplyFilter2D( resize_image, kernel, kernel_height, kernel_width );

        IplImage *filtered_image2 =  cFilter.ApplyFilter2D( d_cvvImage.GetImage(), kernel, kernel_height, kernel_width );

 

        d_cvvImage.CopyOf(filtered_image2);

 

        // STEP 5 : 수행한 결과를 비트맵으로 변환.

        HBITMAP hBitmap = cUtil.IplImage2Bitmap( filtered_image );

        //d_cvvImage.CopyOf( filtered_image, filtered_image->nChannels*8 );

 

        // STEP 6 : 변환한 비트맵을 m_preview 즉, picture 컨트롤에 뿌려줌.

        m_preview_image.SetBitmap( hBitmap );

        m_preview_image.Invalidate(); 

 

        // STEP 7 : 메모리 해제

        cvReleaseImage( &resize_image );

        cvReleaseImage( &filtered_image );

        cvReleaseImage( &filtered_image2 );

 

        // STEP 8 : 화면 갱신

        UpdateData( FALSE );  

}

초기화 Button에 대응하는 멤버 함수를 추가하고 다음과 같이 코딩합니다.

// 정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/332p

void CFilterDlg::OnBnClickedInitialButton()

{

        // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

        // STEP 1 : 원 영상을 가져옴.

        CDeiosImgUtil cUtil;

        IplImage *image = d_org_cvvImage.GetImage();

        IplImage *resize_image = cUtil.Resize4Bitmap( picture_height,

                picture_width, 

                image );

 

        // STEP 2 : 비트맵으로 변환.

        HBITMAP hBitmap = cUtil.IplImage2Bitmap( resize_image );

        d_cvvImage.CopyOf( resize_image, resize_image->nChannels*8 );

 

        // STEP 3 : 변환한 비트맵을 m_preview 즉, picture 컨트롤에 뿌려줌.

        m_preview_image.SetBitmap( hBitmap );

        m_preview_image.Invalidate(); 

 

        // STEP 4 : 메모리 해제

        cvReleaseImage( &resize_image );

 

        // STEP 5 : 화면 갱신

        UpdateData( FALSE ); 

}

마지막으로 확인 Button에 해당하는 메시지 처리기를 구현하겠습니다.

다음과 같이 코딩합니다.

void CFilterDlg::OnBnClickedOk()

{

        // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

        CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();

        CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();

        CMFC_OpenCVDoc *pDoc = (CMFC_OpenCVDoc *)pChild->GetActiveDocument();

 

        pDoc->m_CvvImage.CopyOf( d_cvvImage );

        UpdateData(TRUE);

        CDialogEx::OnOK();

}

이제 Dialog를 보여주는 작업만 남았습니다. 이전 시간에 Menu에 추가해 봤으니, 이번 시간에는 Toolbar에 추가해 보겠습니다.

Cfile4.uf .1523B9524D2DEEA30CD71A

IDR_MAINFRAME_256에도 똑같이 설정합니다.

 

View Class에서 해당하는 멤버 함수를 추가합니다.

Cfile7.uf .17332E4A4D2DEEA41833B4

void CMFC_OpenCVView::OnFilter2d()

{

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

        CFilterDlg dlg;

        dlg.DoModal();

 

        Invalidate(FALSE);

}

Cfile2.uf .1745B24E4D2DEEA4055424 Cfile29.uf .2045C44E4D2DEEA504F0EF

 

Reference
정성환 외 1명/컴퓨터 비전 실무 프로그래밍/홍릉과학출판사/2007/288p~343p,571p
신종홍 외 2명/디지털 영상처리 입문/한빛미디어/2010/430p~462p

cfile25.uf.1745A14E4D2DEFF014A94F.pdfcfile22.uf.1744584E4D2DEFF308F5F5.zip
http://mfc-opencv.googlecode.com/svn/trunk/ -> r4

Similar Posts

  • Face Detect

    이번 시간은 MFC와 OpenCV의 기본 사용법 마지막 내용이 되겠습니다. Cam 영상을 Dialog에 뿌려주는 부분에서 기본 사용법이 끝났어야 하지만… 조금 아쉬운 관계로 더 진행해 봤죠… 저도 아직 초보단계지만, MFC와 OpenCV의 기본 사용법은 뭐 없습니다… MFC야… GUI프로그래밍을 위해서 그냥 쓴 것이고… OpenCV는 영상을 받아오고, 출력하는 부분만 하면 기본은 끝난거 아닌가요?   지금까지 “오픈소스 OpenCV를 이용한 컴퓨터 비전…

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

    이번에는 본격적으로 OpenCV를 사용하여 영상처리를 해 보겠습니다. 그 첫 단계로 메뉴기반 정지영상 처리를 해 볼 것이며, cvSplit함수를 사용하여 RGB 컬러공간을 분리하는 예제를 구현해 보겠습니다.   먼저 OpenCV 2.1 C API Reference에서 cvSplit함수를 찾아보면 다음과 같습니다. cvSplit함수는 다중 채널(Multi-channel)배열을 여러 개의 단일 채널(Single-channel) 배열로 분할하거나, 배열에서 단일 채널을 추출 할 수 있음을 알 수 있습니다. 또한,…

  • 모든 창 닫기 구현

    이번 시간에는 열려있는 모든 창을 닫는 기능을 구현해 보도록 하겠습니다. 먼저 리소스 뷰를 보기 좋게 꺼내어 두는게 좋겠죠? [보기] → [다른 창] → [리소스 뷰]를 클릭합니다.   이번엔 메뉴 바에 해당 기능을 추가할 예정입니다. 리소스 뷰에서 [Menu] → [IDR_*TYPE]을 선택한 후 그림과 같이 지정합니다. Caption : 모든 창 닫기 ID : ID_FILE_CLOSE_ALL Prompt : 열려진…

  • HVR-2000 Series 이용하기

    이번 시간에는 조금 더 재미있는 것을 해 보겠습니다. 바로 요놈입니다.   바로 HyVision System의 HVR-2000 Series입니다. 일반적인 웹캠이야 그냥 연결만 해주면 바로 써먹을 수 있었는데, 요놈은 조금 다릅니다.   USB드라이버야 당연히 깔아줘야 하는거고… 별도의 SDK를 이용해서 Cam에 접근하게 됩니다.   하이비전시스템에서 HVR SDK Interface Guide를 친절하게 작성해 주셔서 별 무리 없이 실습을 진행 해 볼…

  • OpenCV 파일 저장기능 구현

    “Visual Studio 2010에서 OpenCV MFC 프로젝트 만들기(http://deios.kr/400)”에 이어 이번에는 파일 저장기능을 구현해 보도록 하겠습니다.   파일 열기는 OnOpenDocument()함수를 재정의 했던거 기억하시죠? 마찬가지로 파일 저장은 OnSaveDocument()함수를 재정의 하면 됩니다.   이젠 그림만 봐도 아시겠죠? return CDocument::OnSaveDocument(lpszPathName); 부분을 다음과 같이 수정합니다. USES_CONVERSION; return m_CvvImage.Save(W2A(lpszPathName)); 저번에도 말씀드렸지만 OpenCV 라이브러리가 char *형을 받기 때문에 W2A매크로를 사용해 줍니다. 이번에는 새…

  • 모덜리스(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: 여기에 명령…

6 Comments

  1. View Class에 ID_FILTER2D명령에 함수 추가하는 부분이 잘 안되네요. 저는 Visual Studio 2008을 사용하고 있는데요. Toolbar에 F2를 추가하였는데 View Class에서 ID_FILTER2D를 찾을 수가 없어요. 제가 어떤 부분을 실수한건지 모르겠네요. 작성해주신데로 차례차례 따라했는데… 쉽진 않네요. 아직 경험이 많이 부족해서요.. ^^… 이와 유사한 MFC를 이용한 Cam영상 출력부분도 이상하게 잘 안돼요…Dialog가 제대로 뜨질 않네요. 쩝~~~… 제가 혹시 중요한 무언가를 빠뜨렸을까요?

    1. 멍멍~
      빠진부분도 찾지 못해서… 그냥 소스만 C&P하다가 안되니깐 설명탓할빠엔 블로그같은거 보질 말던가 -_-;;;
      라고 하면 기분이 엄청 좋으시겠죠???

      적어놓고 블로그 방치해놓긴 했지만… 빠진 부분은 없습니다. 혹여 빠진 부분이 있다면 그건 일반적인 프로그래밍 스킬이니 알아서 공부하시길…

답글 남기기

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