Tricks & Notes of Using OpenCV with MFC

来源:互联网 发布:一体化智能马桶 知乎 编辑:程序博客网 时间:2024/06/06 10:41

Introduction


I’m currently working on a project that requires sufficient knowledge of the integration of OpenCV and MFC development. Therefore, I believe that it is of great importance to record everything needed to improve myself and help with further implementation.

How to Display A CV::Mat


The tutorials or solutions I could find online about image processing, involving with two of these technologies are all too ancient which utilize a class called CvvImage, the one included in earlier versions of OpenCV, in order to show images of the format of IplImage. The code segment below, however, shows a different approach of displaying images of the newer Mat, which is essentially better than any of the previous image formats.

void DrawPicToHDC(cv::Mat cvImg, UINT ID, bool bOnPaint){    // Get the HDC handle information from the ID passed    CDC *pDC = GetDlgItem(ID)->GetDC();    HDC hDCDst = pDC->GetSafeHdc();    CRect rect;    GetDlgItem(ID)->GetClientRect(&rect);    cv::Size winSize(rect.right, rect.bottom);    // Resize the source to the size of the destination image if necessary    cv::Mat cvImgTmp(winSize, CV_8UC3);    if (cvImg.size() != winSize)    {        cv::resize(cvImg, cvImgTmp, winSize);    }    else    {        cvImgTmp = cvImg;    }    // Rotate the image    cv::flip(cvImgTmp,cvImgTmp,0);    // Initialize the BITMAPINFO structure    BITMAPINFO bitInfo;    bitInfo.bmiHeader.biBitCount = 24;    bitInfo.bmiHeader.biWidth = winSize.width;    bitInfo.bmiHeader.biHeight = winSize.height;    bitInfo.bmiHeader.biPlanes = 1;    bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    bitInfo.bmiHeader.biCompression = BI_RGB;    bitInfo.bmiHeader.biClrImportant = 0;    bitInfo.bmiHeader.biClrUsed = 0;    bitInfo.bmiHeader.biSizeImage = 0;    bitInfo.bmiHeader.biXPelsPerMeter = 0;    bitInfo.bmiHeader.biYPelsPerMeter = 0;    // Add header and OPENCV image's data to the HDC    StretchDIBits(hDCDst, 0, 0,        winSize.width, winSize.height, 0, 0,        winSize.width, winSize.height,        cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);    ReleaseDC( pDC );}

Key Functions


The following functions are quoted from a program called CVMFC that illustrates the use of OpenCV within an MFC application. As a beginner of development of image processing, I really appreciate the work that’s been accomplished in the demo program and the valuable inspiration the source code constantly gives me.

  • StrechDIBits

    This is one of the functions in Windows API. It copies an image source to a destination rectangle and modifies the size of the image accordingly.

    int StretchDIBits(     HDC hdc,  //A handle to the destination device context                  int XDest, YDest, nDestWidth, nDestHeight,  //Parameters of the destination rectangle     int XSrc, YSrc, nSrcWidth, nSrcHeight,  //Parameters of the source rectangle     CONST VOID *lpBits,  //A pointer to the image bits, which are stored as an array of bytes           CONST BITMAPINFO *lpBitsInfo,      // A pointer to a BITMAPINFO structure that contains information about the DIB     UINT iUsage,  //bmiColors     DWORD dwRop  //A raster-operation code );
  • CtreateMapInfo

    This is a function that creates BITMAPINFO for the given image, a structure that defines the dimensions and color information for a DIB(Device-Independent Bitmap).

    LPBITMAPINFO CtreateMapInfo(IplImage* workImg, int flag){     BITMAPINFOHEADER BIH={40,1,1,1,8,0,0,0,0,0,0};     LPBITMAPINFO lpBmi;     int wid,hei,bits,colors,i;     wid =workImg->width;     hei =workImg->height;     bits=workImg->depth*workImg->nChannels;     if (bits>8)         colors=0;     else         colors=1<<bits;     lpBmi=(LPBITMAPINFO) malloc(40+4*colors);     BIH.biWidth = wid;     BIH.biHeight = hei;     BIH.biBitCount = (BYTE) bits;     memcpy(lpBmi,&BIH,40);                       //If workImg represents an 8-bit or 256-color image     if (bits==8) {                                  if (flag==1) {  //Grayscale                     for (i=0;i<256;i++) {                VgaColorTab[i].rgbRed=VgaColorTab[i].rgbGreen =                         VgaColorTab[i].rgbBlue=(BYTE) i;            }            memcpy(lpBmi->bmiColors,VgaColorTab,1024);        }        else if (flag==2) {  //Default            memcpy(lpBmi->bmiColors,VgaDefPal,1024);        }        else if (flag==3) {  //Custom                       memcpy(lpBmi->bmiColors,VgaColorTab,1024);        }     }     return(lpBmi);}
  • imageClone

    int imageClone(IplImage* pi, IplImage** ppo){     if (*ppo) {         cvReleaseImage(ppo);                     }     (*ppo) = cvCloneImage(pi);                 return(1);}
  • imageReplace

    int imageReplace(IplImage* pi, IplImage** ppo){     if (*ppo)          cvReleaseImage(ppo);                    (*ppo) = pi;                                 return(1);}
  • imageType

    This function identifies the image type.

    int  imageType(IplImage* p) {    int  i,j,k,bpl,n,pg[256];    BYTE *buf;    k=p->nChannels;    if (k==1) {                                     for (i=0;i<256;i++) {            pg[i]=0;        }        buf=(BYTE*)p->imageData;        bpl=p->widthStep;        for (i=0;i<p->height;i++) {            for (j=0;j<p->width;j++){                pg[buf[j]]++;            }             buf+=bpl;        }        for (i=0,n=0;i<256;i++) {            if (pg[i]) n++;        }        if (n==2) k=-1;               }    return(k);}
  • CCVMFCDoc::Load

    BOOL CCVMFCDoc::Load(IplImage** pp, LPCTSTR csFileName){    IplImage* pImg=NULL;    pImg = cvLoadImage(csFileName,-1);          if (!pImg)         return(false);    cvFlip(pImg);                        if (*pp) {        cvReleaseImage(pp);    }    (*pp)=pImg;    m_Display=0;    return(true);}
  • CCVMFCView::OnDraw

    void CCVMFCView::OnDraw(CDC* pDC){    CCVMFCDoc* pDoc = GetDocument();    ASSERT_VALID(pDoc);    if (pDoc->pImg!=NULL)   {        if (pDoc->m_Display==0) {            imageClone(pDoc->pImg,&saveImg);            m_dibFlag=imageClone(saveImg,&workImg);            m_ImageType=imageType(workImg);            m_SaveFlag=m_ImageType;            pDoc->m_Display=1;        }    }    if (m_dibFlag) {                        if (m_lpBmi)            free(m_lpBmi);        m_lpBmi=CtreateMapInfo(workImg,m_dibFlag);        m_dibFlag=0;        CSize  sizeTotal;        sizeTotal = CSize(workImg->width,workImg->height);        SetScrollSizes(MM_TEXT,sizeTotal);      }    char *pBits;    if(m_CaptFlag==1)        pBits=m_Frame->imageData;    else if(workImg)          pBits=workImg->imageData;    if (workImg) {                                  StretchDIBits(pDC->m_hDC,                0,0,workImg->width,workImg->height,                0,0,workImg->width,workImg->height,                pBits,m_lpBmi,DIB_RGB_COLORS,SRCCOPY);    }}

Because the program was implemented several years ago, the functions it contains use old OpenCV APIs, which should be updated for the development of C++ applications. For instance, the memory deallocation CV::Mat.release() will ONLY be needed under certain circumstances because it is handled automatically in most cases.

原创粉丝点击