MFC的View区显示OpenCV的Mat数据结构图像,24位彩色或者8位灰度图像

要点:
1). OpenCV采用C++接口中的Mat图像数据结构,可以是24位的CV_8UC3类型(RGB彩色图像),或者8位的CV_8UC!类型(灰度图像)。
2). 将Mat的数据在MFC的View区显示,关键是为Mat设计DIB类型的MBP信息头,也就是结构体BITMAPINFO(详见MSDN)。
3). 将Mat图像数据交给MFC之前需要调cv::filp()函数将数据垂直翻转一下,具体原因可以参考BMP文件的存储结构。
该方法可以将OpenCV处理过的数据方便的在MFC的View区显示。
下面贴出一段演示代码,主要实现简单的读取任何类型的图像,然后在单文档的MFC程序View区显示。
代码如下所示:
//将XXX替换为工程的名称
1)首先位Doc类添加成员变量:

public:
    BITMAPINFOm_bmi;
    Matm_img;
    Mat m_drawImg;

2)并打开菜单添加消息ID_FILE_OPEN,消息处理函数为:

void CXXXDoc::OnFileOpen()//XXX表示工程名称
{
    // TODO: Add your command handler code here
          
    LPCTSTRlpszFilter="Image Files(*.jpg)|*.jpg|ImageFiles(*.bmp)|*.bmp|任何文件|*.*||";
    CFileDialogfdlg(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
    CStringfilename;
    if(fdlg.DoModal()==IDOK)
    {
        filename=fdlg.GetPathName();
        strings(filename.GetBuffer());
        filename.ReleaseBuffer();
        m_img=imread(s,1);
        flip(m_img,m_drawImg,0);
        m_bmi=CreateBitmapInfo(m_img);
    }   
}

3)其中,CreateBitmapInfo函数为:

BITMAPINFO  CreateBitmapInfo(Mat workImg)    //  建立位图信息
{                                           
   BITMAPINFOHEADER BIH={40,1,1,1,8,0,0,0,0,0,0};
   BITMAPINFO bmi;
   intbits, colors;
   RGBQUAD  ColorTab[256];
    if(CV_8UC3==workImg.type())
    {
        bits=24;
    }
    if(CV_8UC1==workImg.type())
    {
        bits=8;
    }    
   if(bits>8) 
        colors=0;
   else
        colors=1<<bits;   
   BIH.biWidth   =workImg.cols;     
    BIH.biHeight  =workImg.rows;
   BIH.biBitCount=(BYTE) bits;   
   bmi.bmiHeader=BIH;
    if(bits==8) 
    {                           //  256 色位图
        for(inti=0;i<256;i++)  
        {                //  设置灰阶调色板
           ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE)i;
        }
        memcpy(bmi.bmiColors,ColorTab, 1024);      
   }
   return(bmi);
}

  4)在View类中添加WM_PAINT消息,响应函数如下:

void CXXXView::OnPaint()//XXX为工程名称
{
    CPaintDCdc(this); // devicecontext for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages
    CopenCVMFCDoc*pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if(!pDoc)
        return;
           
    // TODO: 在此处为本机数据添加绘制代码
    /*
    SetDIBitsToDevice(dc.m_hDC,
                        0,
                        0,
                        pDoc->m_bmi.bmiHeader.biWidth,
                        pDoc->m_bmi.bmiHeader.biHeight,
                        0,
                        0,
                        0,
                        pDoc->m_bmi.bmiHeader.biHeight,
                        pDoc->m_drawImg.data,
                        (LPBITMAPINFO)&(pDoc->m_bmi),
                        DIB_RGB_COLORS);
                        */
                                  
    //也可使用上面注释起来的SetDIBitsToDevice函数(不能实现拉伸)
    StretchDIBits(dc.m_hDC,
                  0, 0, 
                  pDoc->m_bmi.bmiHeader.biWidth,
                  pDoc->m_bmi.bmiHeader.biHeight,
                  0, 0, 
                  pDoc->m_bmi.bmiHeader.biWidth,
                  pDoc->m_bmi.bmiHeader.biHeight,
                  pDoc->m_drawImg.data,
                  (LPBITMAPINFO)&(pDoc->m_bmi),
                  DIB_RGB_COLORS, 
                  SRCCOPY);
    Invalidate(FALSE);
}

 

posted @ 2013-03-04 08:52  ledao  阅读(5464)  评论(0编辑  收藏  举报