如何在MFC视图上显示OpenCV Mat [英] How to display OpenCV Mat on MFC View

查看:934
本文介绍了如何在MFC视图上显示OpenCV Mat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为在MFC视图上显示OpenCV2 Mat很简单,但不是。 这只是我在google上找到的相关资料。对不起我的无知,但我找不到任何其他材料展示如何使用SetDIBitsToDevice与一维数组data成员返回。更具体地说,我需要知道如何为函数指定BITMAPINFO。我回到旧C风格的OpenCV与MFC合作吗?



UPDATE:



我发现 SetDIBitsToDevice ,这实际上是用于旧的C风格的OpenCV。但它是直接转换为OpenCV2。有一些事情我需要提及,使其工作:


  1. Bpp方法不能很好地工作,因为Mat的深度返回0。只是改变了这样:

      static int Bpp(cv :: Mat img){return 8 * img.channels } 


  2. Mat没有origin成员。但是简单地将0设置为FillBitmapInfo方法的原始参数。


除此之外,希望这也有助于其他开发者。

  void CopenCVTestView :: OnDraw(CDC * pDC)
{
COpenCVTestDoc * pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(!pDoc)
return;
if(pDoc-> m_cvImage.empty())return;
// TODO:为本地数据添加绘制代码
int height = pDoc-> m_cvImage.rows;
int width = pDoc-> m_cvImage.cols;
uchar buffer [sizeof(BITMAPINFOHEADER)+ 1024];
BITMAPINFO * bmi =(BITMAPINFO *)buffer;
FillBitmapInfo(bmi,width,height,Bpp(pDoc-> m_cvImage),0);
SetDIBitsToDevice(pDC-> GetSafeHdc(),0,0,width,
height,0,0,0,height,pDoc-> m_cvImage.data,bmi,
DIB_RGB_COLORS) ;
}
void COpenCVTestView :: FillBitmapInfo(BITMAPINFO * bmi,int width,int height,int bpp,int origin)
{
assert(bmi&& width& = 0&& height> = 0&&(bpp == 8 || bpp == 24 || bpp == 32));

BITMAPINFOHEADER * bmih =&(bmi-> bmiHeader);

memset(bmih,0,sizeof(* bmih));
bmih-> biSize = sizeof(BITMAPINFOHEADER);
bmih-> biWidth = width;
bmih-> biHeight = origin? abs(height):-abs(height);
bmih-> biPlanes = 1;
bmih-> biBitCount =(unsigned short)bpp;
bmih-> biCompression = BI_RGB;

if(bpp == 8)
{
RGBQUAD * palette = bmi-> bmiColors;

for(int i = 0; i <256; i ++)
{
palette [i] .rgbBlue = palette [i] .rgbGreen = palette [i]。 rgbRed =(BYTE)i;
palette [i] .rgbReserved = 0;
}
}
}


解决方案>

从MSDN:


lpvBits [in]
指向以字节数组形式存储的颜色数据的指针。有关详细信息,请参阅以下注释部分。


这是您必须初始化的指针,


I thought displaying OpenCV2 Mat on MFC View is simple but is not. This is only relevant material I found on google. Excuse me for my ignorance but I can't find any other materials showing how to use SetDIBitsToDevice with one dimensional array "data" member returns. More specifically, I need to know how to specify BITMAPINFO for the function. Do I go back to Old C-style OpenCV to work with MFC?

UPDATE:

I found an example of SetDIBitsToDevice which is actually for old C-style OpenCV. But it was straightforward to convert it for OpenCV2. There are things I need to mention to make it work:

  1. Bpp method does not work well as Mat's depth returns 0. I just changed like this:

    static int Bpp(cv::Mat img) { return 8 * img.channels(); } 
    

  2. Mat does not have origin member. But simply putting 0 is fine for origin argument of FillBitmapInfo method.

Other than that, following code works great. Hope this helps other devs too.

void COpenCVTestView::OnDraw(CDC* pDC)
{
COpenCVTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
    return;
if(pDoc->m_cvImage.empty()) return;
// TODO: add draw code for native data here
int height=pDoc->m_cvImage.rows;
int width=pDoc->m_cvImage.cols;
uchar buffer[sizeof( BITMAPINFOHEADER ) + 1024]; 
BITMAPINFO* bmi = (BITMAPINFO* )buffer; 
FillBitmapInfo(bmi,width,height,Bpp(pDoc->m_cvImage),0);
SetDIBitsToDevice(pDC->GetSafeHdc(), 0, 0, width,
    height, 0, 0, 0, height, pDoc->m_cvImage.data, bmi,
    DIB_RGB_COLORS);
}
void COpenCVTestView::FillBitmapInfo(BITMAPINFO* bmi, int width, int height, int bpp, int origin) 
{ 
assert(bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); 

BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 

memset(bmih, 0, sizeof(*bmih)); 
bmih->biSize = sizeof(BITMAPINFOHEADER); 
bmih->biWidth = width; 
bmih->biHeight = origin ? abs(height) : -abs(height); 
bmih->biPlanes = 1; 
bmih->biBitCount = (unsigned short)bpp; 
bmih->biCompression = BI_RGB; 

if (bpp == 8) 
{ 
    RGBQUAD* palette = bmi->bmiColors; 

            for (int i = 0; i < 256; i++) 
    { 
        palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 
        palette[i].rgbReserved = 0; 
    } 
} 
}

解决方案

From MSDN:

lpvBits [in] A pointer to the color data stored as an array of bytes. For more information, see the following Remarks section.

This is the pointer you must init with the data returned from Mat::data.

这篇关于如何在MFC视图上显示OpenCV Mat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆