【问题标题】:Convert HBITMAP to cv::Mat将 HBITMAP 转换为 cv::Mat
【发布时间】:2011-10-23 09:52:21
【问题描述】:

我似乎无法弄清楚如何做到这一点,我在 google 上搜索并找到了两个代码示例,一个来自 github 屏幕截图库,另一个来自发布组,它们似乎都没有工作。

我有一个结构:

struct ClacksScreen
{
    HWND hDesktopWnd; 
    int width, height;
    RECT wr, cr;
    HDC hdcClacksScreen; // hardware ClacksScreen
    HDC hdcMemDC; // ClacksScreen in memory
    HBITMAP hbmClacksScreen; //hbitmap of the ClacksScreen
    BITMAP bmpClacksScreen;
    BITMAPINFOHEADER bi;
};

已更新。我定义了一些函数,包括将位图写入磁盘的函数,它工作正常,屏幕被捕获并将 bmp 写入磁盘,这是我想要的。

现在我想将屏幕上的 HBITMAP 直接转换为 OpenCV2.1 的 cv::Mat。

它有点工作,除了图像是纯灰色的并且它崩溃了。显然,我在 c++ 方面仍然很n00b,所以可能有一些简单的东西我只是没有摸索。

static cv::Mat copyToCVMat(const ClacksScreen * s)
{
    cv::Mat image;
    image.create(s->bmpClacksScreen.bmWidth, s->bmpClacksScreen.bmHeight, CV_8UC4);
    GetDIBits(s->hdcMemDC, s->hbmClacksScreen, 0,
            (UINT)s->bmpClacksScreen.bmHeight,
            image.data,
            (BITMAPINFO *)&s->bi, DIB_RGB_COLORS);
    return image;
}

当我包装一个 cv::imwrite(image);在尝试捕获中,我得到了一个错误的分配错误。显然,在这一点上,我们已经确定我不知道如何做到这一点,因此我们将不胜感激。

更新

如果我运行这段代码:

try {
    cv::Mat screen = cv::imread("captureqwsx.jpg");
    if (!screen.data) {
        printf("no image data?");
    }
    cv::imwrite("out.jpg",screen);
} catch(std::exception e) {
    printf("Exception %s\n",e.what());
}

我得到了输出:

没有图像数据?异常错误分配

当我尝试运行高 gui 时,它和以前一样,写入磁盘的 .jpg 和 .bmps 都会出现问题,它们可以在图像查看器和 MS Paint 中查看。

我尝试使用完全不同的图片,来自网站的 .png,同样的问题。

那么我现在做错了什么?

【问题讨论】:

    标签: c++ visual-studio winapi opencv


    【解决方案1】:

    来自 OpenCV 文档

    data – 指向用户数据的指针。获取数据的矩阵构造函数 和 step 参数不分配矩阵数据。相反,他们只是 初始化指向指定数据的矩阵头,即 没有数据被复制。这个操作效率很高,可以用来 使用 OpenCV 函数处理外部数据。外部数据不 自动释放,用户应该注意它。

    我认为这就是重点,使用这个构造函数不会复制你传递给构造函数的缓冲区,所以在你不再需要 cv::Mat 之前你不应该释放这些数据。另外我对这些东西几乎一无所知,但是为什么要将 BITMAPINFOHEADER 和 BITMAPFILEHEADER 传递给 cv::Mat 对象,这似乎根本不对。

    【讨论】:

    • 对不起,当它不起作用时,我只是尝试了所有方法。看到上面的更新,我现在用的是GetDIBits版本。此外,在文档中有一个构造函数来获取数据: // 矩阵头的构造函数指向用户分配的数据 Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);
    【解决方案2】:

    我不知道它是什么,但是当我提出问题的那一刻,我就会着迷于寻找答案。无论如何,这个问题的一部分实际上是通过这个问题的答案来解决的:

    OpenCV 2.0 C++ API using imshow: returns unhandled exception and "bad-flag"

    在 Visual C++ 中:

    转到项目->属性(或 Alt-F7)配置 属性->链接器->输入->附加依赖

    将通常的“ cv210.lib cxcore210.lib highgui210.lib”替换为“ cv210d.lib cxcore210d.lib highgui210d.lib" - 这是调试 图书馆。

    highgui 仍然显示灰色并且不起作用,但是使用上述方法从 HBITMAP 读取现在可以正常工作。而且我真的不需要highgui,反正只是为了测试。

    【讨论】:

      【解决方案3】:

      我写了自己的函数来做类似的事情,希望它可以帮助你: How to capture the desktop in OpenCV (ie. turn a bitmap into a Mat)?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-29
        • 2014-05-07
        • 2011-06-07
        • 2016-04-13
        • 1970-01-01
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        相关资源
        最近更新 更多