zoukankan      html  css  js  c++  java
  • Direct Show采集图像实例

    // CaptureVideo.h: interface for the CCaptureVideo class.
    //
    //////////////////////////////////////////////////////////////////////

    #if !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
    #define AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    #include 
    <atlbase.h>
    #include 
    <windows.h>
    #include 
    <dshow.h>
    #ifndef SAFE_RELEASE
    #define SAFE_RELEASE( x ) \
    if ( NULL != x ) \
    { \
        x
    ->Release( ); \
        x 
    = NULL; \
    }

    #endif
    class CSampleGrabberCB;

    class CCaptureVideo  : public CWnd
    {
        friend 
    class CSampleGrabberCB;
    public:
        
    void GrabOneFrame(BOOL bGrab);
        
    void ImageProcess(BOOL bImage);
        HRESULT Init(
    int iDeviceID,HWND hWnd);
        CCaptureVideo();
        
    virtual ~CCaptureVideo();

        BOOL bIsVideoOpen;
        
    void SwitchImageProcess(BOOL bprocess);
           
    void ImageProcessing(unsigned char*m_pDibBits,int m_height, int m_width);

    private:
        HWND m_hWnd;
        IGraphBuilder 
    *m_pGB;
        ICaptureGraphBuilder2
    * m_pCapture;
        IBaseFilter
    * m_pBF;
        IMediaControl
    * m_pMC;
        IVideoWindow
    * m_pVW;
        CComPtr 
    <ISampleGrabber> m_pGrabber;

    protected:
        
    void FreeMediaType(AM_MEDIA_TYPE& mt);
        
    bool BindFilter(int deviceId, IBaseFilter **pFilter);
        HRESULT InitCaptureGraphBuilder();
    }
    ;

    #endif // !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)

    // CaptureVideo.cpp: implementation of the CCaptureVideo class.
    //
    //////////////////////////////////////////////////////////////////////

    #include 
    "stdafx.h"
    #include 
    "CaptureVideo.h"
    #include 
    "ImageProcess.h"
    #ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif
    /////////////////////////声明全局变量//////////////////////////////////////
    BOOL bIsSavePic = FALSE;
    BOOL bIsImageProcess 
    = FALSE;
    //////////////////////////////////////////////////////////////////////
    class CSampleGrabberCB:public ISampleGrabberCB 
    {
    public:
        
    long lWidth;
        
    long lHeight;
        CCaptureVideo dlg;

        STDMETHODIMP_(ULONG) AddRef() 
    return 2; }
        STDMETHODIMP_(ULONG) Release() 
    return 1; }
        STDMETHODIMP QueryInterface(REFIID riid, 
    void ** ppv)
        
    {
            
    if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
            

                
    *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
                
    return NOERROR;
            }
     
            
            
    return E_NOINTERFACE;
        }

        
        STDMETHODIMP SampleCB( 
    double SampleTime, IMediaSample * pSample )
        
    {
            
    return 0;
        }

    //回调函数
        STDMETHODIMP BufferCB( double dblSampleTime, unsigned char* pBuffer, long lBufferSize )
        
    {
            
    if (!pBuffer)     return E_POINTER;
            
            
    if (bIsImageProcess) 
            
    {//如果条件为真则进行数字图像处理
                dlg.ImageProcessing(pBuffer, lHeight, lWidth);
            }

            
            
    return 0;
        }

    }
    ;
    CSampleGrabberCB mCB;

    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////
    CCaptureVideo::CCaptureVideo() 
    {
        
    //COM Library Intialization
        if(FAILED(CoInitialize(NULL))) 
        
    {
            AfxMessageBox(
    "CoInitialize Failed!\r\n"); 
            
    return;
        }

        m_hWnd 
    = NULL;
        m_pVW 
    = NULL;
        m_pMC 
    = NULL;
        m_pGB 
    = NULL;
        m_pCapture 
    = NULL; 
        bIsVideoOpen 
    = FALSE;
    }


    CCaptureVideo::
    ~CCaptureVideo()
    {
        
    if (bIsVideoOpen) 
        
    {    
            
    // Stop media playback
            if(m_pMC)
            
    {
                m_pMC
    ->Stop();
            }

            
            
    if(m_pVW)
            
    {
                m_pVW
    ->put_Visible(OAFALSE);
                m_pVW
    ->put_Owner(NULL);
            }

            
            SAFE_RELEASE(m_pCapture);
            SAFE_RELEASE(m_pMC);
            SAFE_RELEASE(m_pGB);
            SAFE_RELEASE(m_pBF);
            CoUninitialize( );
        }

    }


    ///////////////////////////////////////////////////////////////////////////
    ////
    ////                        DirectShow核心代码
    ////
    ///////////////////////////////////////////////////////////////////////////

    HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
    {
        HRESULT hr;
        hr 
    = InitCaptureGraphBuilder();
        
    if (FAILED(hr))
        
    {
            AfxMessageBox(
    "Failed to get video interfaces!");
            
    return hr;
        }


        
    // Bind Device Filter. We know the device because the id was passed in
        if(!BindFilter(iDeviceID, &m_pBF))
        
    {
            AfxMessageBox(
    "未找到USB摄像头!\n请检查设备后重试!");
            PostQuitMessage(
    0);
            
    return S_FALSE;
        }

        
        hr 
    = m_pGB->AddFilter(m_pBF, L"Capture Filter");
        
    // hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, // m_pBF, NULL, NULL);
        
    // create a sample grabber
        hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
        
    if!m_pGrabber )
        
    {
            AfxMessageBox(
    "Fail to create SampleGrabber, maybe qedit.dll is not registered?");
            
    return hr;
        }


        CComQIPtr
    < IBaseFilter, &IID_IBaseFilter > pGrabBase(m_pGrabber);
        
        
    //**********设置视频格式**********//
        AM_MEDIA_TYPE mt; 
        ZeroMemory(
    &mt, sizeof(AM_MEDIA_TYPE));
        mt.majortype 
    = MEDIATYPE_Video;
        mt.subtype 
    = MEDIASUBTYPE_RGB24;  //抓取24位位图
        hr = m_pGrabber->SetMediaType(&mt);

        
    if( FAILED( hr ) )
        
    {
            AfxMessageBox(
    "Fail to set media type!");
            
    return hr;
        }

        
        hr 
    = m_pGB->AddFilter( pGrabBase, L"Grabber" );
        
    if( FAILED( hr ) )
        
    {
            AfxMessageBox(
    "Fail to put sample grabber in graph");
            
    return hr;
        }


        
    // try to render preview/capture pin
        hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
        
    if( FAILED( hr ) )
            hr 
    = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);

        
    if( FAILED( hr ) )
        
    {
            AfxMessageBox(
    "Can't build the graph");
            
    return hr;
        }

        
        hr 
    = m_pGrabber->GetConnectedMediaType( &mt );
        
        
    if ( FAILED( hr) )
        
    {
            AfxMessageBox(
    "Failt to read the connected media type");
            
    return hr;
        }


        VIDEOINFOHEADER 
    * vih = (VIDEOINFOHEADER*) mt.pbFormat;
        mCB.lWidth 
    = vih->bmiHeader.biWidth;
        mCB.lHeight 
    = vih->bmiHeader.biHeight;
        FreeMediaType(mt);
        hr 
    = m_pGrabber->SetBufferSamples( FALSE );
        hr 
    = m_pGrabber->SetOneShot( FALSE );
        hr 
    = m_pGrabber->SetCallback( &mCB, 1 );
        
        
    //*********设置视频捕捉窗口********//
        m_hWnd = hWnd ; //picture控件的句柄
        hr = m_pVW->put_Owner((OAHWND)m_hWnd);
        
    if (FAILED(hr)) return hr;
        hr 
    = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
        
    if (FAILED(hr)) return hr;

        
    if (m_pVW)
        
    {    
            CRect rc;
            ::GetClientRect(m_hWnd,
    &rc);
            m_pVW
    ->SetWindowPosition(00, rc.right, rc.bottom);//让图像充满整个窗口
        }
     

        hr 
    = m_pVW->put_Visible(OATRUE);

        
    //*********开始视频捕捉********//
        hr = m_pMC->Run();
        
    if(FAILED(hr))
        
    {
            AfxMessageBox(
    "Couldn't run the graph!");
            
    return hr;
        }


        bIsVideoOpen 
    = TRUE;
        
    return S_OK;
    }


    HRESULT CCaptureVideo::InitCaptureGraphBuilder()
    {
        HRESULT hr;
        
    // 创建IGraphBuilder接口
        hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
        
    // 创建ICaptureGraphBuilder2接口
        hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **&m_pCapture);
        
    if (FAILED(hr)) return hr;
        m_pCapture
    ->SetFiltergraph(m_pGB);
        hr 
    = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
        
    if (FAILED(hr)) return hr;
        hr 
    = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);
        
    if (FAILED(hr)) return hr;
        
    return hr;
    }


    bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
    {
        
    if (deviceId < 0return false;

        
    // enumerate all video capture devices
        CComPtr<ICreateDevEnum> pCreateDevEnum;
        HRESULT hr 
    = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
        
    if (hr != NOERROR)
        
    {
            
    return false;
        }


        CComPtr
    <IEnumMoniker> pEm;
        hr 
    = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
        
    if (hr != NOERROR) 
        
    {
            
    return false;
        }


        pEm
    ->Reset();
        ULONG cFetched;
        IMoniker 
    *pM;
        
    int index = 0;
        
    while(hr = pEm->Next(1&pM, &cFetched), hr==S_OK, index <= deviceId)
        
    {
            IPropertyBag 
    *pBag;
            hr 
    = pM->BindToStorage(00, IID_IPropertyBag, (void **)&pBag);
            
    if(SUCCEEDED(hr)) 
            
    {
                VARIANT var;
                var.vt 
    = VT_BSTR;
                hr 
    = pBag->Read(L"FriendlyName"&var, NULL);
                
    if (hr == NOERROR) 
                
    {
                    
    if (index == deviceId)
                    
    {
                        pM
    ->BindToObject(00, IID_IBaseFilter, (void**)pFilter);
                    }


                    SysFreeString(var.bstrVal);
                }

                
                pBag
    ->Release();
            }

            
            pM
    ->Release();
            index
    ++;
        }

        
        
    return true;
    }


    void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
    {
        
    if (mt.cbFormat != 0
        
    {
            CoTaskMemFree((PVOID)mt.pbFormat);
            
    // Strictly unnecessary but tidier
            mt.cbFormat = 0;
            mt.pbFormat 
    = NULL;
        }

        
        
    if (mt.pUnk != NULL) 
        
    {
            mt.pUnk
    ->Release();
            mt.pUnk 
    = NULL;
        }

    }
     

    //////////////////////////////////////////////////////////////////////////////////////////

    void CCaptureVideo::SwitchImageProcess(BOOL bprocess)
    {
        bIsImageProcess 
    = bprocess;
    }


    //////////////////////////////////////////////////////////////////////////////
    /////////
    /////////                         数字图像处理       
    ////////
    ///////////////////////////////////////////////////////////////////////////////

    void CCaptureVideo::ImageProcessing(unsigned char*m_pDibBits, int m_height, int m_width)
    {    
        CImageProcess::ColorToGray(m_pDibBits,m_height, m_width); 
    //彩色转灰度
        CImageProcess::ConvertGrayToWhiteBlack(m_pDibBits, m_height, m_width, 120); //二值化
    }



    主程序


    #ifdef _DEBUG
    #pragma comment(lib,"strmbasd.lib")
    #else
    #pragma comment(lib,"STRMBASE.lib")
    #endif
    #pragma comment(lib,"strmiids.lib")
    #pragma comment(lib,"quartz.lib")

    void CUSBShowDlg::OnBUTTONOpenVideo() //打开摄像头
    {
        HWND hWnd 
    = m_StaticShow.GetSafeHwnd(); 
        HRESULT hr 
    = m_cap.Init(0,hWnd); //DirectShow初始化
    }


    void CUSBShowDlg::OnBUTTONImageProcess() //启动数字图像处理开关
    {
        m_cap.SwitchImageProcess(TRUE);
    }

  • 相关阅读:
    Linux使用定时器timerfd 和 eventfd接口实现进程线程通信
    C++面向对象实现封装线程池
    生产者与消费者问题,C++利用bind基于对象实现与面向对象实现
    C++11新特性,bind,基于对象
    [HDU
    [HDU
    [HDU
    【BZOJ3707】圈地 (几何,旋转坐标系)
    [HDU
    [Codeforces Round #595 (Div. 3)] F. Maximum Weight Subset (树形DP)
  • 原文地址:https://www.cnblogs.com/wqj1212/p/1133116.html
Copyright © 2011-2022 走看看