MFC PictureControl에 Mat 이미지 불러오기

반응형
728x90
반응형
 
Introduction

MFC에서 picture control에 IplImage, Mat 이미지를 불러와야하는 경우가 종종 있었습니다.(과거형..) 최근에는 이를 이용하여 몇가지 툴을 만들고 있지만, 옛날에는 자료들이 없어 조금씩 정리를하고 있습니다.  서론 없이 코드를 보면서 이야기를 바로 하도록 하겠습니다. 
 
 
MFC - Mat 이미지 호출

 
COpenCVTestDlg.h 
public :
    Mat m_matImage;
    BITMAPINFO *m_pBitmapInfo;

    void CreateBitmapInfo(int w, int h, int bpp);
    void DrawImage();
 
MFC 다이얼로그에 Mat, BITMAPINFO 를 정의 합니다. 그리고 함수 정의 두개 추가 합니다. 
 
 
COpenCVTestDlg.cpp 
void COpenCVTestDlg::CreateBitmapInfo(int w, int h, int bpp)
{
    if (m_pBitmapInfo != NULL)
    {
        delete[]m_pBitmapInfo;
        m_pBitmapInfo = NULL;
    }

    if (bpp == 8)
        m_pBitmapInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)];
    else // 24 or 32bit
        m_pBitmapInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFO)];

    m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    m_pBitmapInfo->bmiHeader.biPlanes = 1;
    m_pBitmapInfo->bmiHeader.biBitCount = bpp;
    m_pBitmapInfo->bmiHeader.biCompression = BI_RGB;
    m_pBitmapInfo->bmiHeader.biSizeImage = 0;
    m_pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
    m_pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
    m_pBitmapInfo->bmiHeader.biClrUsed = 0;
    m_pBitmapInfo->bmiHeader.biClrImportant = 0;

    if (bpp == 8)
    {
        for (int i = 0; i < 256; i++)
        {
            m_pBitmapInfo->bmiColors[i].rgbBlue = (BYTE)i;
            m_pBitmapInfo->bmiColors[i].rgbGreen = (BYTE)i;
            m_pBitmapInfo->bmiColors[i].rgbRed = (BYTE)i;
            m_pBitmapInfo->bmiColors[i].rgbReserved = 0;
        }
    }
    
    m_pBitmapInfo->bmiHeader.biWidth = w;
    m_pBitmapInfo->bmiHeader.biHeight = -h;
}
 
상단 코드는 MFC의  picture control에 출력하기위한 코드입니다. 즉, openCV 이미지를 bitmap 형태로 값을 저장하기위한 코드..!!
 

 

 

 
 
COpenCVTestDlg.cpp
void COpenCVTestDlg::DrawImage()
{
    CClientDC dc(GetDlgItem(IDC_PC_VIEW));

    CRect rect;
    GetDlgItem(IDC_PC_VIEW)->GetClientRect(&rect);

    SetStretchBltMode(dc.GetSafeHdc(), COLORONCOLOR);

    StretchDIBits(dc.GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, m_matImage.cols, m_matImage.rows, m_matImage.data, m_pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);

}
 
  • 참고 : Picture control의 이름은 IDC_PC_VIEW
 
MFC의 CDC를 이용하네요. GDI? GDI+ 등도 있지만, 내용이 복잡복잡하니 필요할 때 또 정리하도록 하겠습니다. 
 
 
COpenCVTestDlg.cpp 에서 호출
void COpenCVTestDlg::OnBnClickedBtnImageload()
{
    CFileDialog fileDlg(TRUE, NULL, NULL, OFN_READONLY, _T("image file(*.jpg;*.bmp;*.png;)|*.jpg;*.bmp;*.png;|All Files(*.*)|*.*||"));
    if (fileDlg.DoModal() == IDOK)
    {
        CString path = fileDlg.GetPathName();

        CT2CA pszString(path);
        std::string strPath(pszString);

        m_matImage = imread(strPath, IMREAD_UNCHANGED);
        CreateBitmapInfo(m_matImage.cols, m_matImage.rows, m_matImage.channels()*8);
        DrawImage();
    }
}
 
사용방법은 MFC에서 파일다이얼로그를 호출 후, path 입력 그리고 이미지를 출력하는 것입니다. 
 
 
 
기타

최근 작업을 하면서, 상단의 코드를 이용하여 initDialog함수 내부에서 사용했었는데, 이미지가 제대로 불러지지 않더군요. 문제점이랄까? 해결방법은 Timer를 이용하여 해결하였습니다. Timer를 이용하여 setTImer, KillTimer를 반복하면서 이미지 sequence 를 호출하는 것이죠. 
 
문제점이라 이야기 하고 싶은 부분은 딱히, 뭐라 표현할 수 없는게, 오랫동안 작업하다보니, 용어, 키워드는 기억이 나지는 않지만, 이런 경우는 저렇게 해결하면 된다만 기억 하고 있네요. 그래도 문제점을 조금 정리해보자면, MFC UI를 갱신할 때는 MFC에서 제공하는 API함수를 사용해야한다(?) 라는 것입니다. 이런 부분들이 MFC에서 작업할 때 조금 불편한 부분들이 다소있지만, 처음 작업하시는 분들이 볼때는 코드가 문제가 없는데 어디서 막히는지 알수 없는 부분들이 많아 기록으로 남겨 둡니다. 
 
(코드는 그러고보니, 아래 Reference의 내용과 동일하네요. 현재 작업 중인 코드가 아니네요..ㅠㅠ)
 
 
Reference
 
 
728x90
반응형

댓글

Designed by JB FACTORY