使用OpenCV在MFC / C ++应用程序中显示图像

时间:2011-06-14 22:12:02

标签: c++ mfc opencv

我想在MFC应用程序中显示我从具有OpenCV(cvCaptureFromAVI函数)的avi文件中捕获的帧。

我是MFC的新手,但我觉得我已接近使其成功。但是,不是在图片框中显示的帧,而是在新窗口中显示它们。

cvGetWindowName始终返回空值。

有我的代码:

CWnd* hPic = 0;
hPic = GetDlgItem(IDC_STATICPIC1);  
const char* szWindName = cvGetWindowName(hPic->GetSafeHwnd());
cvShowImage(szWindName, frame_copy);

4 个答案:

答案 0 :(得分:7)

所以经过长时间的研究,我发现了一些可以使它发挥作用的东西。

解决方案是创建窗口,然后将其插入图片框。我不确定这是好习惯,但我现在还没有找到更好的东西。

cvNamedWindow("IDC_STATIC_OUTPUT", 0); 
cvResizeWindow("IDC_STATIC_OUTPUT", 420, 240);

HWND hWnd = (HWND) cvGetWindowHandle("IDC_STATIC_OUTPUT"); 
HWND hParent = ::GetParent(hWnd); 
     ::SetParent(hWnd, GetDlgItem(IDC_PIC1)->m_hWnd); 
     ::ShowWindow(hParent, SW_HIDE); 

cvShowImage("IDC_STATIC_OUTPUT", frame_copy);

在这种情况下,图片框称为IDC_PIC1,frame_copy是OpenCV IplImage。

希望这有助于某人。

答案 1 :(得分:7)

使用以下代码,您可以将Mat转换为CImage,然后在任何地方显示CImage:

int Mat2CImage(Mat *mat, CImage &img){
  if(!mat || mat->empty())
    return -1;
  int nBPP = mat->channels()*8;
  img.Create(mat->cols, mat->rows, nBPP);
  if(nBPP == 8)
  {
    static RGBQUAD pRGB[256];
    for (int i = 0; i < 256; i++)
        pRGB[i].rgbBlue = pRGB[i].rgbGreen = pRGB[i].rgbRed = i;
    img.SetColorTable(0, 256, pRGB);
  }
  uchar* psrc = mat->data;
  uchar* pdst = (uchar*) img.GetBits();
  int imgPitch = img.GetPitch();
  for(int y = 0; y < mat->rows; y++)
  {
    memcpy(pdst, psrc, mat->cols*mat->channels());//mat->step is incorrect for those images created by roi (sub-images!)
    psrc += mat->step;
    pdst += imgPitch;
  }

  return 0;
}

答案 2 :(得分:0)

注意:如果将StretchDIBits()方法与BITMAPINFO方法一起使用,则必须注意StretchDIBits()期望原始OpenCV Mat :: data指针的行长度为偶数4个字节的倍数!如果没有,当你试图通过StretchDIBits()将数据复制到DC时,你会得到怪异的剪切 - 在这里,图像不仅沿着一个角度被剪切,而且颜色也都被删除了。

这是我完全正在使用的代码版本,它还支持在目标控件的矩形中保持图像宽高比。它可能会更快一点,但它现在有效:

void AdjustAspectImageSize( const Size& imageSize,
                            const Size& destSize, 
                                  Size& newSize )
{
   double destAspectRatio   =  float( destSize.width  )  /  float( destSize.height  );
   double imageAspectRatio  =  float( imageSize.width )  /  float( imageSize.height );

   if ( imageAspectRatio > destAspectRatio )
   {
      // Margins on top/bottom
      newSize.width    =   destSize.width;
      newSize.height   =   int( imageSize.height  *  
                                    ( double( destSize.width )  /  double( imageSize.width ) ) );
   }
   else
   {
      // Margins on left/right
      newSize.height   =   destSize.height;
      newSize.width    =   int( imageSize.width  *
                                    ( double( destSize.height )  /  double( imageSize.height ) ) );
   }
}


void DrawPicToHDC( Mat  cvImg, 
                   UINT nDlgID, 
                   bool bMaintainAspectRatio /* =true*/  )
{
   // Get the HDC handle information from the ID passed
   CDC* pDC  =  GetDlgItem(nDlgID)->GetDC();
   HDC  hDC  =  pDC->GetSafeHdc();

   CRect rect;
   GetDlgItem(nDlgID)->GetClientRect(rect);

   Size winSize( rect.right, rect.bottom );

   // Calculate the size of the image that
   // will fit in the control rectangle.
   Size origImageSize( cvImg.cols, cvImg.rows );
   Size imageSize;
   int  offsetX;
   int  offsetY;

   if ( ! bMaintainAspectRatio )
   {
      // Image should be the same size as the control's rectangle
      imageSize = winSize;
   }
   else
   {
      Size newSize;

      _AdjustAspectImageSize( origImageSize,
                              winSize,
                              imageSize );
   }

   offsetX   =   ( winSize.width  - imageSize.width  )  /  2;
   offsetY   =   ( winSize.height - imageSize.height )  /  2;

   // Resize the source to the size of the destination image if necessary
   Mat cvImgTmp;

   resize( cvImg, 
           cvImgTmp, 
           imageSize,
           0,
           0,
           INTER_AREA );

   // To handle our Mat object of this width, the source rows must
   // be even multiples of a DWORD in length to be compatible with 
   // SetDIBits().  Calculate what the correct byte width of the 
   // row should be to be compatible with SetDIBits() below.
   int stride  =  ( ( ( ( imageSize.width * 24 )  +  31 )  &  ~31 )  >>  3 );

   // Allocate a buffer for our DIB bits
   uchar* pcDibBits  =  (uchar*) malloc( imageSize.height * stride );

   if ( pcDibBits != NULL )
   {
      // Copy the raw pixel data over to our dibBits buffer.
      // NOTE: Can setup cvImgTmp to add the padding to skip this.
      for ( int row = 0;  row < cvImgTmp.rows;  ++row )
      {
         // Get pointers to the beginning of the row on both buffers
         uchar* pcSrcPixel  =  cvImgTmp.ptr<uchar>(row);
         uchar* pcDstPixel  =  pcDibBits  +  ( row * stride );

         // We can just use memcpy
         memcpy( pcDstPixel,
                 pcSrcPixel,
                 stride );
      }

      // Initialize the BITMAPINFO structure
      BITMAPINFO bitInfo;

      bitInfo.bmiHeader.biBitCount       =  24;
      bitInfo.bmiHeader.biWidth          =   cvImgTmp.cols;
      bitInfo.bmiHeader.biHeight         =  -cvImgTmp.rows;
      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;      //winSize.height * winSize.width * * 3;
      bitInfo.bmiHeader.biXPelsPerMeter  =  0;
      bitInfo.bmiHeader.biYPelsPerMeter  =  0;

      // Add header and OPENCV image's data to the HDC
      StretchDIBits( hDC, 
                     offsetX, 
                     offsetY,
                     cvImgTmp.cols,
                     cvImgTmp.rows,
                     0, 
                     0,
                     cvImgTmp.cols,
                     cvImgTmp.rows,
                     pcDibBits,
                     & bitInfo, 
                     DIB_RGB_COLORS, 
                     SRCCOPY );

      free(pcDibBits);
   }

   ReleaseDC(pDC);
}

答案 3 :(得分:-2)

int DrawImageToHDC(IplImage * img,HDC hdc,int xDest,int yDest,UINT iUsage,DWORD rop)

    char m_chBmpBuf[2048];
    BITMAPINFO *m_pBmpInfo = 0;
    m_pBmpInfo = (BITMAPINFO*)m_chBmpBuf;
    m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    m_pBmpInfo->bmiHeader.biWidth = img->width;
    m_pBmpInfo->bmiHeader.biHeight = -img->height;
    m_pBmpInfo->bmiHeader.biBitCount = 24;

    m_pBmpInfo->bmiHeader.biPlanes = 1;
    m_pBmpInfo->bmiHeader.biCompression = BI_RGB;
    m_pBmpInfo->bmiHeader.biSizeImage = 0;
    m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0;
    m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0;
    m_pBmpInfo->bmiHeader.biClrUsed = 0;
    m_pBmpInfo->bmiHeader.biClrImportant = 0;

    return StretchDIBits(hdc, xDest, yDest, img->width, img->height, 0, 0,
img->width, img->height, img->imageData, m_pBmpInfo, DIB_RGB_COLORS, SRCCOPY);

用法:DrawImageToHDC(img,pDC-&gt; m_hDC,Area.left,Area.top,DIB_RGB_COLORS,SRCCOPY);