【发布时间】:2011-12-14 08:59:14
【问题描述】:
我认为在 MFC 视图上显示 OpenCV2 Mat 很简单,但事实并非如此。 This is only relevant material I found on google。请原谅我的无知,但我找不到任何其他材料来展示如何将 SetDIBitsToDevice 与一维数组“数据”成员返回一起使用。更具体地说,我需要知道如何为函数指定 BITMAPINFO。我要回到旧的 C 风格 OpenCV 来使用 MFC 吗?
更新:
我找到了an example of SetDIBitsToDevice,它实际上是用于旧的 C 风格 OpenCV。但是将其转换为 OpenCV2 很简单。我需要提到一些事情才能让它发挥作用:
-
Bpp 方法效果不佳,因为 Mat 的深度返回 0。我只是这样更改:
static int Bpp(cv::Mat img) { return 8 * img.channels(); } Mat 没有原始成员。但是对于 FillBitmapInfo 方法的 origin 参数,简单地放置 0 就可以了。
除此之外,以下代码效果很好。希望这对其他开发者也有帮助。
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;
}
}
}
【问题讨论】:
-
您提供的链接有什么问题?
-
@vasile 尽管有关于 SetDIBitsToDevice 的文档,但我无法弄清楚如何将 SetDIBitsToDevice 与一维数组“数据”成员返回一起使用。
-
@Paul 我已经将您的示例视为其他几个问题/答案的基础。但是,我想知道,您如何避免在
FillBitmapInfo函数中使用memset导致内存泄漏?还是以某种方式自动释放?你能详细说明一下这方面吗? -
@adn 对不起,我不明白你的问题。是什么让您认为使用 memset 会导致内存泄漏?为什么要释放它?
-
你是我的英雄!节省我很多时间。我不需要 CvvImage,只需复制并稍微修改您的代码即可。关键点是
SetDIBitsToDevice调用,但BITMAPINFO迷惑初学者。