将HBITMAP转换为cv :: Mat

时间:2011-08-09 16:51:24

标签: c++ visual-studio winapi opencv

我似乎无法弄清楚如何做到这一点,我在谷歌搜索并找到了两个代码示例,一个来自github屏幕捕获库,另一个来自发布组,但它们似乎都没有工作。< / p>

我有一个结构:

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直接转换为cv :: Mat for OpenCV2.1。

它有点有效,除了图像是纯灰色并且它崩溃了。显然,当涉及到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 catch中,我得到一个错误的分配错误。显然,在这一点上,我们已经确定我没有自由的线索如何做到这一点,所以任何帮助都将不胜感激。

更新

如果我运行此代码:

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,同样的问题。

那么我现在做错了什么?

2 个答案:

答案 0 :(得分:1)

来自OpenCV文档

  

data - 指向用户数据的指针。获取数据的矩阵构造函数   和步骤参数不分配矩阵数据。相反,他们只是   初始化指向指定数据的矩阵标题,即   没有数据被复制。此操作非常有效,可以用于   使用OpenCV函数处理外部数据。外部数据不是   自动解除分配,用户应该照顾它。

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

答案 1 :(得分:0)

我不知道它是什么,但是当我问一个问题的时候,我发现找到答案时会感到茫然。无论如何,这个问题的一部分实际上是通过这个问题的答案来解决的:

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

  

在Visual C ++中:

     

转到Project-&gt;属性(或Alt-F7)配置   属性 - >链接器 - >输入 - >附加依赖性

     

取代平常&#34; cv210.lib cxcore210.lib highgui210.lib&#34; by&#34;   cv210d.lib cxcore210d.lib highgui210d.lib&#34; - 哪些是调试   库。

highgui仍然显示灰色并且不起作用,但现在可以使用上述方法从HBITMAP读取数据。而且我真的不需要高贵,无论如何都只是为了测试。