VB.Net--Winform(DirectShowLib-2005)调用高清摄像头(高拍仪)

之前写了一些关于C#调用摄像头的代码,但都是只能调用普通的摄像头,高清的摄像头立马没戏(黑屏)

在网上看过了很多的例子,都找不到有关调用高清的,最后在Microsoft的MSDN上看到用(DirectShowLib-2005)可以很好的控制高清摄像头(当然普通的也可以控制,高清的都可以了,普通的当然可以了)
也有一些小例子,但都是用C#写的,本来想着把类改改封装一下在VB里面直接调用,(在铭少的帮助下,成功调用)但是发现到具体调用的时候原类库里面的东西很多方法属性都没公开,越改越多,懒得找麻烦,果断放弃...
 
下午有空,用VB写了一个,如今网上VB的能调用高清摄像头的例子极少,所以就再次发布出来,希望有需要的朋友可以拿去用..话不多说,走起...
 
步骤一:
引用:DirectShowLib-2005(没有的去网上下)
 
步骤二:Capture类
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Collections
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Diagnostics
Imports System.Windows.Forms
Imports DirectShowLib
 
Public Class Capture
    Implements ISampleGrabberCB
    Implements IDisposable
 
#Region "Member variables"
 
    ''' graph builder interface.
    Private m_FilterGraph As IFilterGraph2 = Nothing
 
    ' Used to snap picture on Still pin
    Private m_VidControl As IAMVideoControl = Nothing
    Private m_pinStill As IPin = Nothing
 
    ''' so we can wait for the async job to finish
    Private m_PictureReady As ManualResetEvent = Nothing
 
    Private m_WantOne As Boolean = False
 
    ''' Dimensions of the image, calculated once in constructor for perf.
    Private m_videoWidth As Integer
    Private m_videoHeight As Integer
    Private m_stride As Integer
 
    ''' buffer for bitmap data.  Always release by caller
    Private m_ipBuffer As IntPtr = IntPtr.Zero
 
#If DEBUG Then
    ' Allow you to "Connect to remote graph" from GraphEdit
    Private m_rot As DsROTEntry = Nothing
#End If
#End Region
 
#Region "APIs"
    _
    Private Shared Sub CopyMemory(Destination As IntPtr, Source As IntPtr, Length As Integer)
    End Sub
#End Region
 
    ' Zero based device index and device params and output window
    Public Sub New(iDeviceNum As Integer, iWidth As Integer, iHeight As Integer, iBPP As Short, hControl As Control)
        Dim capDevices As DsDevice()
 
        ' Get the collection of video devices
        capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
 
        If iDeviceNum + 1 > capDevices.Length Then
            Throw New Exception("No video capture devices found at that index!")
        End If
 
        Try
            ' Set up the capture graph
            SetupGraph(capDevices(iDeviceNum), iWidth, iHeight, iBPP, hControl)
 
            ' tell the callback to ignore new images
            m_PictureReady = New ManualResetEvent(False)
        Catch
            Dispose()
            Throw
        End Try
    End Sub
 
    ''' release everything.
    Public Sub Dispose()
#If DEBUG Then
        If m_rot IsNot Nothing Then
            m_rot.Dispose()
        End If
#End If
        CloseInterfaces()
        If m_PictureReady IsNot Nothing Then
            m_PictureReady.Close()
        End If
    End Sub
    ' Destructor
    Protected Overrides Sub Finalize()
        Try
            Dispose()
        Finally
            MyBase.Finalize()
        End Try
    End Sub
 
    '''
    ''' Get the image from the Still pin.  The returned image can turned into a bitmap with
    ''' Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
    ''' If the image is upside down, you can fix it with
    ''' b.RotateFlip(RotateFlipType.RotateNoneFlipY);
    '''
    ''' Returned pointer to be freed by caller with Marshal.FreeCoTaskMem
    Public Function Click() As IntPtr
        Dim hr As Integer
 
        ' get ready to wait for new image
        m_PictureReady.Reset()
        m_ipBuffer = Marshal.AllocCoTaskMem(Math.Abs(m_stride) * m_videoHeight)
 
        Try
            m_WantOne = True
 
            ' If we are using a still pin, ask for a picture
            If m_VidControl IsNot Nothing Then
                ' Tell the camera to send an image
                hr = m_VidControl.SetMode(m_pinStill, VideoControlFlags.Trigger)
                DsError.ThrowExceptionForHR(hr)
            End If
 
            ' Start waiting
            If Not m_PictureReady.WaitOne(9000, False) Then
                Throw New Exception("Timeout waiting to get picture")
            End If
        Catch
            Marshal.FreeCoTaskMem(m_ipBuffer)
            m_ipBuffer = IntPtr.Zero
            Throw
        End Try
 
        ' Got one
        Return m_ipBuffer
    End Function
 
    Public ReadOnly Property Width() As Integer
        Get
            Return m_videoWidth
        End Get
    End Property
    Public ReadOnly Property Height() As Integer
        Get
            Return m_videoHeight
        End Get
    End Property
    Public ReadOnly Property Stride() As Integer
        Get
            Return m_stride
        End Get
    End Property
 
    ''' build the capture graph for grabber.
    Private Sub SetupGraph(dev As DsDevice, iWidth As Integer, iHeight As Integer, iBPP As Short, hControl As Control)
        Dim hr As Integer
 
        Dim sampGrabber As ISampleGrabber = Nothing
        Dim capFilter As IBaseFilter = Nothing
        Dim pCaptureOut As IPin = Nothing
        Dim pSampleIn As IPin = Nothing
        Dim pRenderIn As IPin = Nothing
 
        ' Get the graphbuilder object
        m_FilterGraph = TryCast(New FilterGraph(), IFilterGraph2)
 
        Try
#If DEBUG Then
            m_rot = New DsROTEntry(m_FilterGraph)
#End If
            ' add the video input device
            hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, Nothing, dev.Name, capFilter)
            DsError.ThrowExceptionForHR(hr)
 
            ' Find the still pin
            m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0)
 
            ' Didn't find one.  Is there a preview pin?
            If m_pinStill Is Nothing Then
                m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0)
            End If
 
            ' Still haven't found one.  Need to put a splitter in so we have
            ' one stream to capture the bitmap from, and one to display.  Ok, we
            ' don't *have* to do it that way, but we are going to anyway.
            If m_pinStill Is Nothing Then
                Dim pRaw As IPin = Nothing
                Dim pSmart As IPin = Nothing
 
                ' There is no still pin
                m_VidControl = Nothing
 
                ' Add a splitter
                Dim iSmartTee As IBaseFilter = DirectCast(New SmartTee(), IBaseFilter)
 
                Try
                    hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee")
                    DsError.ThrowExceptionForHR(hr)
 
                    ' Find the find the capture pin from the video device and the
                    ' input pin for the splitter, and connnect them
                    pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0)
                    pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0)
 
                    hr = m_FilterGraph.Connect(pRaw, pSmart)
                    DsError.ThrowExceptionForHR(hr)
 
                    ' Now set the capture and still pins (from the splitter)
                    m_pinStill = DsFindPin.ByName(iSmartTee, "Preview")
                    pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture")
 
                    ' If any of the default config items are set, perform the config
                    ' on the actual video device (rather than the splitter)
                    If iHeight + iWidth + iBPP > 0 Then
                        SetConfigParms(pRaw, iWidth, iHeight, iBPP)
                    End If
                Finally
                    If pRaw IsNot Nothing Then
                        Marshal.ReleaseComObject(pRaw)
                    End If
                    If pRaw IsNot pSmart Then
                        Marshal.ReleaseComObject(pSmart)
                    End If
                    If pRaw IsNot iSmartTee Then
                        Marshal.ReleaseComObject(iSmartTee)
                    End If
                End Try
            Else
                ' Get a control pointer (used in Click())
                m_VidControl = TryCast(capFilter, IAMVideoControl)
 
                pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0)
 
                ' If any of the default config items are set
                If iHeight + iWidth + iBPP > 0 Then
                    SetConfigParms(m_pinStill, iWidth, iHeight, iBPP)
                End If
            End If
 
            ' Get the SampleGrabber interface
            sampGrabber = TryCast(New SampleGrabber(), ISampleGrabber)
 
            ' Configure the sample grabber
            Dim baseGrabFlt As IBaseFilter = TryCast(sampGrabber, IBaseFilter)
            ConfigureSampleGrabber(sampGrabber)
            pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0)
 
            ' Get the default video renderer
            Dim pRenderer As IBaseFilter = TryCast(New VideoRendererDefault(), IBaseFilter)
            hr = m_FilterGraph.AddFilter(pRenderer, "Renderer")
            DsError.ThrowExceptionForHR(hr)
 
            pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0)
 
            ' Add the sample grabber to the graph
            hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber")
            DsError.ThrowExceptionForHR(hr)
 
            If m_VidControl Is Nothing Then
                ' Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn)
                DsError.ThrowExceptionForHR(hr)
 
                ' Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn)
                DsError.ThrowExceptionForHR(hr)
            Else
                ' Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn)
                DsError.ThrowExceptionForHR(hr)
 
                ' Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn)
                DsError.ThrowExceptionForHR(hr)
            End If
 
            ' Learn the video properties
            SaveSizeInfo(sampGrabber)
            ConfigVideoWindow(hControl)
 
            ' Start the graph
            Dim mediaCtrl As IMediaControl = TryCast(m_FilterGraph, IMediaControl)
            hr = mediaCtrl.Run()
            DsError.ThrowExceptionForHR(hr)
        Finally
            If sampGrabber IsNot Nothing Then
                Marshal.ReleaseComObject(sampGrabber)
                sampGrabber = Nothing
            End If
            If pCaptureOut IsNot Nothing Then
                Marshal.ReleaseComObject(pCaptureOut)
                pCaptureOut = Nothing
            End If
            If pRenderIn IsNot Nothing Then
                Marshal.ReleaseComObject(pRenderIn)
                pRenderIn = Nothing
            End If
            If pSampleIn IsNot Nothing Then
                Marshal.ReleaseComObject(pSampleIn)
                pSampleIn = Nothing
            End If
        End Try
    End Sub
 
    Private Sub SaveSizeInfo(sampGrabber As ISampleGrabber)
        Dim hr As Integer
 
        ' Get the media type from the SampleGrabber
        Dim media As New AMMediaType()
 
        hr = sampGrabber.GetConnectedMediaType(media)
        DsError.ThrowExceptionForHR(hr)
 
        If (media.formatType <> FormatType.VideoInfo) OrElse (media.formatPtr = IntPtr.Zero) Then
            Throw New NotSupportedException("Unknown Grabber Media Format")
        End If
 
        ' Grab the size info
        Dim videoInfoHeader As VideoInfoHeader = DirectCast(Marshal.PtrToStructure(media.formatPtr, GetType(VideoInfoHeader)), VideoInfoHeader)
        m_videoWidth = videoInfoHeader.BmiHeader.Width
        m_videoHeight = videoInfoHeader.BmiHeader.Height
        m_stride = m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8)
 
        DsUtils.FreeAMMediaType(media)
        media = Nothing
    End Sub
 
    ' Set the video window within the control specified by hControl
    Private Sub ConfigVideoWindow(hControl As Control)
        Dim hr As Integer
 
        Dim ivw As IVideoWindow = TryCast(m_FilterGraph, IVideoWindow)
 
        ' Set the parent
        hr = ivw.put_Owner(hControl.Handle)
        DsError.ThrowExceptionForHR(hr)
 
        ' Turn off captions, etc
        hr = ivw.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren Or WindowStyle.ClipSiblings)
        DsError.ThrowExceptionForHR(hr)
 
        ' Yes, make it visible
        hr = ivw.put_Visible(OABool.[True])
        DsError.ThrowExceptionForHR(hr)
 
        ' Move to upper left corner
        Dim rc As Rectangle = hControl.ClientRectangle
        hr = ivw.SetWindowPosition(0, 0, rc.Right, rc.Bottom)
        DsError.ThrowExceptionForHR(hr)
    End Sub
 
    Private Sub ConfigureSampleGrabber(sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As New AMMediaType()
 
        ' Set the media type to Video/RBG24
        media.majorType = MediaType.Video
        media.subType = MediaSubType.RGB24
        media.formatType = FormatType.VideoInfo
        hr = sampGrabber.SetMediaType(media)
        DsError.ThrowExceptionForHR(hr)
 
        DsUtils.FreeAMMediaType(media)
        media = Nothing
 
        ' Configure the samplegrabber
        hr = sampGrabber.SetCallback(Me, 1)
        DsError.ThrowExceptionForHR(hr)
    End Sub
 
    ' Set the Framerate, and video size
    Private Sub SetConfigParms(pStill As IPin, iWidth As Integer, iHeight As Integer, iBPP As Short)
        Dim hr As Integer
        Dim media As AMMediaType
        Dim v As VideoInfoHeader
 
        Dim videoStreamConfig As IAMStreamConfig = TryCast(pStill, IAMStreamConfig)
 
        ' Get the existing format block
        hr = videoStreamConfig.GetFormat(media)
        DsError.ThrowExceptionForHR(hr)
 
        Try
            ' copy out the videoinfoheader
            v = New VideoInfoHeader()
            Marshal.PtrToStructure(media.formatPtr, v)
 
            ' if overriding the width, set the width
            If iWidth > 0 Then
                v.BmiHeader.Width = iWidth
            End If
 
            ' if overriding the Height, set the Height
            If iHeight > 0 Then
                v.BmiHeader.Height = iHeight
            End If
 
            ' if overriding the bits per pixel
            If iBPP > 0 Then
                v.BmiHeader.BitCount = iBPP
            End If
 
            ' Copy the media structure back
            Marshal.StructureToPtr(v, media.formatPtr, False)
 
            ' Set the new format
            hr = videoStreamConfig.SetFormat(media)
            DsError.ThrowExceptionForHR(hr)
        Finally
            DsUtils.FreeAMMediaType(media)
            media = Nothing
        End Try
    End Sub
 
    ''' Shut down capture
    Private Sub CloseInterfaces()
        Dim hr As Integer
 
        Try
            If m_FilterGraph IsNot Nothing Then
                Dim mediaCtrl As IMediaControl = TryCast(m_FilterGraph, IMediaControl)
 
                ' Stop the graph
                hr = mediaCtrl.[Stop]()
            End If
        Catch ex As Exception
            Debug.WriteLine(ex)
        End Try
 
        If m_FilterGraph IsNot Nothing Then
            Marshal.ReleaseComObject(m_FilterGraph)
            m_FilterGraph = Nothing
        End If
 
        If m_VidControl IsNot Nothing Then
            Marshal.ReleaseComObject(m_VidControl)
            m_VidControl = Nothing
        End If
 
        If m_pinStill IsNot Nothing Then
            Marshal.ReleaseComObject(m_pinStill)
            m_pinStill = Nothing
        End If
    End Sub
 
    ''' sample callback, NOT USED.
    Private Function ISampleGrabberCB_SampleCB(SampleTime As Double, pSample As IMediaSample) As Integer Implements ISampleGrabberCB.SampleCB
        Marshal.ReleaseComObject(pSample)
        Return 0
    End Function
 
    ''' buffer callback, COULD BE FROM FOREIGN THREAD.
    Private Function ISampleGrabberCB_BufferCB(SampleTime As Double, pBuffer As IntPtr, BufferLen As Integer) As Integer Implements ISampleGrabberCB.BufferCB
        ' Note that we depend on only being called once per call to Click.  Otherwise
        ' a second call can overwrite the previous image.
        Debug.Assert(BufferLen = Math.Abs(m_stride) * m_videoHeight, "Incorrect buffer length")
 
        If m_WantOne Then
            m_WantOne = False
            Debug.Assert(m_ipBuffer <> IntPtr.Zero, "Unitialized buffer")
 
            ' Save the buffer
            CopyMemory(m_ipBuffer, pBuffer, BufferLen)
 
            ' Picture is ready.
            m_PictureReady.[Set]()
        End If
 
        Return 0
    End Function
 
    Public Sub Dispose1() Implements IDisposable.Dispose
 
    End Sub
End Class
 
 
步骤三:Winform.VB代码
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Imports System.IO
 
Public Class Form1
    Private cam As Capture
 
    Public Sub New()
        '
        ' Required for Windows Form Designer support
        '
        InitializeComponent()
 
        Const VIDEODEVICE As Integer = 0
        ' zero based index of video capture device to use
        Const VIDEOWIDTH As Integer = 1024
        ' Depends on video device caps
        Const VIDEOHEIGHT As Integer = 768
        ' Depends on video device caps
        Const VIDEOBITSPERPIXEL As Integer = 24
        ' BitsPerPixel values determined by device
        cam = New Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, pictureBox1)
    End Sub
 
    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            Cursor.Current = Cursors.WaitCursor
 
            ' Release any previous buffer
            If m_ip <> IntPtr.Zero Then
                Marshal.FreeCoTaskMem(m_ip)
                m_ip = IntPtr.Zero
            End If
 
            ' capture image
            m_ip = cam.Click()
            Dim b As New Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip)
 
            ' If the image is upsidedown
            b.RotateFlip(RotateFlipType.RotateNoneFlipY)
            PictureBox2.Image = b
            Dim PathPic As String = "D:\\ScreenShot"
            If PictureBox2.Image IsNot Nothing Then
                If Not Directory.Exists(PathPic) Then
                    Directory.CreateDirectory(PathPic)
                Else
                    Dim NG As String = Convert.ToString(Guid.NewGuid())
                    PictureBox2.Image.Save(PathPic & "\" & NG & ".jpg")
                End If
            End If
 
            Cursor.Current = Cursors.[Default]
        Catch ex As Exception
            MessageBox.Show("ScreenShot is Error!", "Prompt", MessageBoxButtons.OK)
        End Try
      
    End Sub
 
    Private m_ip As IntPtr = IntPtr.Zero
 
    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs)
        cam.Dispose()
        If m_ip <> IntPtr.Zero Then
            Marshal.FreeCoTaskMem(m_ip)
            m_ip = IntPtr.Zero
        End If
 
    End Sub
 
 
End Class
 
 
页面代码:大概样子(主要是类那里,前端页面随便改...由于我没什么美感,所以页面有点丑!嘻嘻~)
VB.Net--Winform(DirectShowLib-2005)调用高清摄像头(高拍仪)
posted @ 2013-05-24 11:32  ZWmaqing  阅读(3580)  评论(0)    收藏  举报