2014-02-20 48 views
1

我正在使用DirectShow访问视频流,然后使用SampleGrabber过滤器和接口从每个帧获取样本以进一步进行图像处理。我使用回调函数,所以在每个新帧之后都会调用它。我基本上只是从PlayCap示例应用程序工作,并添加了一个示例过滤器到图形。ISampleGrabber :: BufferCB到IplImage;在OpenCV中显示乱码图像 - C++

我遇到的问题是我试图在不同的OpenCV窗口上显示抓取的样本。但是,当我尝试将缓冲区中的信息转换为IplImage时,我得到了乱七八糟的像素。对于BufferCB调用的代码如下,SANS任何适当的错误处理:

STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen) 
{ 
    AM_MEDIA_TYPE type; 
    g_pGrabber->GetConnectedMediaType(&type); 
    VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER *)type.pbFormat; 

    BITMAPINFO* bmi = (BITMAPINFO *)&pVih->bmiHeader; 
    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 
    int channels = bmih->biBitCount/8; 

    mih->biPlanes = 1; 
    bmih->biBitCount = 24; 
    bmih->biCompression = BI_RGB; 

    IplImage *Image = cvCreateImage(cvSize(bmih->biWidth, bmih->biHeight), IPL_DEPTH_8U, channels);  

    Image->imageSize = BufferLen; 
    CopyMemory(Image->imageData, pBuffer, BufferLen); 
    cvFlip(Image); 

    //openCV Mat creation 
    Mat cvMat = Mat(Image, true); 
    imshow("Display window", cvMat);     // Show our image inside it. 
    waitKey(2); 


    return S_OK; 
} 

我的问题是,我在这里做得不对,这将使图像显示的是这样的:

我是否缺少标题信息?

回答

1

引用的代码是解决方案的一部分。您可以在此创建具有8位像素数据和未知通道/组件数的特定宽度/高度的图像对象。然后从另一个未知格式的缓冲区复制数据。

它唯一能够很好地工作的机会是所有的未知数都可以毫不费力地匹配。所以你基本上需要开始检查Sample Grabber的输入引脚上的媒体类型。那么,如果它不是你想要的,你必须分别更新你的代码。 SG的下游连接以及它是否特别连接到视频渲染器可能也很重要。

+0

好吧,我已经开始研究如何构建图。基本上,我给它一个源代码,添加一个示例抓取器过滤器,然后渲染源上的引脚。然后它将图形编译为 Source - > Sample Grabber - > MJPEG decompressor - > Color space converter - > Video renderer。所以,本质上,从样本中获得的字节被编码为MJPEG。我使用GraphEdit工具来查看是否可以重新排列过滤器,以便SampleGrabber工具位于渲染器之前,但不是骰子。是否有解码字节的简写方式,或者是否应该更改过滤器图? – Scratch17

+0

是的,这解释了这个效果:你取JPEG字节并将它们重新解释为RGB,这是一个非工作者。您可以实际重新排列过滤器。但是,在编程上,你通常设置Sample Grabber只接受你感兴趣的RGB类型,例如请参阅“设置媒体类型”下的[这里](http://msdn.microsoft.com/en-us/library/windows/desktop/dd407288%28v=vs.85%29.aspx)。 –

+0

太好了,那就是答案,谢谢!我不知道通过设置图形将自动将SampleGrabber构建到正确位置的类型来获取这种数据。非常感谢! – Scratch17