Webcam Snapshot

  • VB.NET

Es gibt 33 Antworten in diesem Thema. Der letzte Beitrag () ist von Rikudo.

    Webcam Snapshot

    Hallo,

    Also so lasse ich mir meine Webcam in PictureBox2 anzeigen:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports DirectShowLib
    2. Imports System
    3. Imports System.Diagnostics
    4. Imports System.Drawing
    5. Imports System.Runtime.InteropServices
    6. Imports System.Windows.Forms
    7. Imports System.Runtime.InteropServices.ComTypes
    8. Public Class Form1
    9. Dim D As Integer = Convert.ToInt32("0X8000", 16)
    10. Public WM_GRAPHNOTIFY As Integer = D + 1
    11. Dim VideoWindow As IVideoWindow = Nothing
    12. Dim MediaControl As IMediaControl = Nothing
    13. Dim MediaEventEx As IMediaEventEx = Nothing
    14. Dim GraphBuilder As IGraphBuilder = Nothing
    15. Dim CaptureGraphBuilder As ICaptureGraphBuilder2 = Nothing
    16. Enum PlayState
    17. Stopped
    18. Paused
    19. Running
    20. Init
    21. End Enum
    22. Dim CurrentState As PlayState = PlayState.Stopped
    23. Dim rot As DsROTEntry = Nothing
    24. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    25. closeinterfaces()
    26. End Sub
    27. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    28. CaptureVideo()
    29. PictureBox1.Visible = True
    30. End Sub
    31. Private Sub CaptureVideo()
    32. Dim hr As Integer = 0
    33. Dim sourceFilter As IBaseFilter = Nothing
    34. Try
    35. GetInterfaces()
    36. hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder) 'Specifies filter graph "graphbuilder" for the capture graph builder "captureGraphBuilder" to use.
    37. sourceFilter = FindCaptureDevice()
    38. hr = GraphBuilder.AddFilter(sourceFilter, "Video Capture")
    39. hr = CaptureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, Nothing, Nothing)
    40. Marshal.ReleaseComObject(sourceFilter)
    41. SetupVideoWindow()
    42. rot = New DsROTEntry(GraphBuilder)
    43. hr = MediaControl.Run()
    44. CurrentState = PlayState.Running
    45. Catch ex As Exception
    46. MessageBox.Show("An unrecoverable error has occurred.With error : " & ex.ToString)
    47. End Try
    48. End Sub
    49. Private Sub GetInterfaces()
    50. Dim hr As Integer = 0
    51. GraphBuilder = CType(New FilterGraph, IGraphBuilder)
    52. CaptureGraphBuilder = CType(New CaptureGraphBuilder2, ICaptureGraphBuilder2)
    53. MediaControl = CType(GraphBuilder, IMediaControl)
    54. VideoWindow = CType(GraphBuilder, IVideoWindow)
    55. MediaEventEx = CType(GraphBuilder, IMediaEventEx)
    56. hr = MediaEventEx.SetNotifyWindow(Me.Handle, WM_GRAPHNOTIFY, IntPtr.Zero) 'This method designates a window as the recipient of messages generated by or sent to the current DirectShow object
    57. End Sub
    58. Public Function FindCaptureDevice() As IBaseFilter
    59. Dim hr As Integer = 0
    60. Dim classEnum As IEnumMoniker = Nothing
    61. Dim moniker As IMoniker() = New IMoniker(0) {}
    62. Dim source As Object = Nothing
    63. Dim devEnum As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum)
    64. hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, classEnum, 0)
    65. Marshal.ReleaseComObject(devEnum)
    66. If classEnum Is Nothing Then
    67. Throw New ApplicationException("No video capture device was detected.\r\n\r\n" & _
    68. "This sample requires a video capture device, such as a USB WebCam,\r\n" & _
    69. "to be installed and working properly. The sample will now close.")
    70. End If
    71. If classEnum.Next(moniker.Length, moniker, IntPtr.Zero) = 0 Then
    72. Dim iid As Guid = GetType(IBaseFilter).GUID
    73. moniker(0).BindToObject(Nothing, Nothing, iid, source)
    74. Else
    75. Throw New ApplicationException("Unable to access video capture device!")
    76. End If
    77. Marshal.ReleaseComObject(moniker(0))
    78. Marshal.ReleaseComObject(classEnum)
    79. Return CType(source, IBaseFilter)
    80. End Function
    81. Public Sub SetupVideoWindow()
    82. Dim hr As Integer = 0
    83. 'set the video window to be a child of the main window
    84. 'putowner : Sets the owning parent window for the video playback window.
    85. hr = VideoWindow.put_Owner(PictureBox1.Handle) 'Me.Handle)
    86. PictureBox1.Visible = False
    87. hr = VideoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren)
    88. 'Use helper function to position video window in client rect of main application window
    89. ResizeVideoWindow()
    90. 'Make the video window visible, now that it is properly positioned
    91. 'put_visible : This method changes the visibility of the video window.
    92. hr = VideoWindow.put_Visible(OABool.True)
    93. End Sub
    94. Public Sub ResizeVideoWindow()
    95. 'Resize the video preview window to match owner window size
    96. 'left , top , width , height
    97. If Not (VideoWindow Is Nothing) Then 'if the videopreview is not nothing
    98. VideoWindow.SetWindowPosition(0, 0, Me.Width, Me.ClientSize.Height)
    99. End If
    100. End Sub
    101. Public Sub closeinterfaces()
    102. '//stop previewing data
    103. If Not (Me.MediaControl Is Nothing) Then
    104. Me.MediaControl.StopWhenReady()
    105. End If
    106. Me.CurrentState = PlayState.Stopped
    107. '//stop recieving events
    108. If Not (Me.MediaEventEx Is Nothing) Then
    109. Me.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero)
    110. End If
    111. '// Relinquish ownership (IMPORTANT!) of the video window.
    112. '// Failing to call put_Owner can lead to assert failures within
    113. '// the video renderer, as it still assumes that it has a valid
    114. '// parent window.
    115. If Not (Me.VideoWindow Is Nothing) Then
    116. Me.VideoWindow.put_Visible(OABool.False)
    117. Me.VideoWindow.put_Owner(IntPtr.Zero)
    118. End If
    119. ' // Remove filter graph from the running object table
    120. If Not (rot Is Nothing) Then
    121. rot.Dispose()
    122. rot = Nothing
    123. End If
    124. '// Release DirectShow interfaces
    125. Marshal.ReleaseComObject(Me.MediaControl) : Me.MediaControl = Nothing
    126. Marshal.ReleaseComObject(Me.MediaEventEx) : Me.MediaEventEx = Nothing
    127. Marshal.ReleaseComObject(Me.VideoWindow) : Me.VideoWindow = Nothing
    128. Marshal.ReleaseComObject(Me.GraphBuilder) : Me.GraphBuilder = Nothing
    129. Marshal.ReleaseComObject(Me.CaptureGraphBuilder) : Me.CaptureGraphBuilder = Nothing
    130. End Sub
    131. Public Sub GrabImage()
    132. '
    133. ' Get image from clipboard and convert it to a bitmap
    134. Try
    135. MediaControl.Pause()
    136. Clipboard.SetImage(PictureBox1.Image)
    137. '
    138. If Clipboard.ContainsImage Then
    139. PictureBox2.Image = Clipboard.GetImage()
    140. End If
    141. Catch
    142. End Try
    143. End Sub
    144. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    145. MediaControl.Run()
    146. End Sub
    147. End Class


    Soweit klappt alles wunderbar. Ich nutze die DirectShow Lib um die Webcam anzusprechen.
    Nun würde ich gerne einen Schnappschuss machen.

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. GrabImage()
    3. PictureBox1.Image.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & "\Snapshot.jpg")
    4. MsgBox("Done")
    5. End Sub


    Doch ich bekomme diesen Fehler:



    Kann mir jemand helfen, das ich den Schanppschuss machen kann?
    Weil ich weiß nicht wie ich das hinkriegen soll...? ;o
    C# Developer
    Learning C++
    2 Möglichkeiten:
    1. Der Pfad ist Grütze, probier mal "c:\Temp\myImage.jpg"
    2. Das Image ist Nothing. Teste es:

      VB.NET-Quellcode

      1. If PictureBox1.Image Is Nothing Then
      2. MessageBox("Nothing")
      3. Return
      4. End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    .. Sag mal bitte die Zeile sonnst dauert das zu lange :)

    MFG BlackNetworkBit
    MFG 0x426c61636b4e6574776f726b426974
    InOffical VB-Paradise IRC-Server
    webchat.freenode.net/
    Channel : ##vbparadise
    Setzt einfach nen Breakpoint bei der ersten Zeile der Funktion, dann machste alles Schritt für Schritt und fügst Sachen zu Überwachung hinzu. So kannst du am besten Fehler finden ohne die ganzen MessageBoxen.
    Mfg
    Vincent

    RodFromGermany schrieb:

    2 Möglichkeiten:
    1. Der Pfad ist Grütze, probier mal "c:\Temp\myImage.jpg"
    2. Das Image ist Nothing. Teste es:

      VB.NET-Quellcode

      1. If PictureBox1.Image Is Nothing Then
      2. MessageBox("Nothing")
      3. Return
      4. End If


    Tatsächlich. Die msgBox poppt auf. Ist also Nothing... :(

    BlackNetworkBit schrieb:


    .. Sag mal bitte die Zeile sonnst dauert das zu lange

    MFG BlackNetworkBit


    Naja, halt der Pfad zum Speichern. Also, im Button Click event:

    C# Developer
    Learning C++
    Ok dann überprüfe ob das Bild überhaupt als Image gezählt wird.
    Vieleicht ist es auch leer ?

    MFg BlackNetworkBit
    MFG 0x426c61636b4e6574776f726b426974
    InOffical VB-Paradise IRC-Server
    webchat.freenode.net/
    Channel : ##vbparadise
    @Rikudo: Damit das Bild schnell angezeigt werden kann, wird von .NET lediglich ein leerer Rahmen bereitgestellt, das Bild wird von der Kamera sofort in die Grafikkarte geblasen.
    Sieh mal nach, ob die Kamerasoftware Capture-Routinen bereitstellt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich meine bloß das die Directshowlib vieleicht nicht das bild als Image ausgibt sondern direct auf das Control zeichnet.

    MFG BlackNetworkBit
    MFG 0x426c61636b4e6574776f726b426974
    InOffical VB-Paradise IRC-Server
    webchat.freenode.net/
    Channel : ##vbparadise
    Musst du nicht Picturebox2 speichern? Denn das Image der Picturebox1 wird doch gar nicht verändert:

    VB.NET-Quellcode

    1. Clipboard.SetImage(PictureBox1.Image)
    2. '
    3. If Clipboard.ContainsImage Then
    4. PictureBox2.Image = Clipboard.GetImage()
    5. End If
    Mfg
    Vincent

    Es wird doch über "Clipboard.GetImage" Wieder ausgelesen ?
    und solange er nicht die Picturebox1 Sauber macht ist doch alles in Ordnung oder ?
    MFg BlackNetworkBit
    MFG 0x426c61636b4e6574776f726b426974
    InOffical VB-Paradise IRC-Server
    webchat.freenode.net/
    Channel : ##vbparadise

    VincentTB schrieb:

    Musst du nicht Picturebox2 speichern? Denn das Image der Picturebox1 wird doch gar nicht verändert:

    VB.NET-Quellcode

    1. Clipboard.SetImage(PictureBox1.Image)
    2. '
    3. If Clipboard.ContainsImage Then
    4. PictureBox2.Image = Clipboard.GetImage()
    5. End If


    Auch da kreig ich die gleiche Exception wie oben.
    In Pictureboy 1 sehe ich die webcam, also das sich bewegende bild. und dieses will ich eben in ein .jpg Bild speichern.
    Und ich bin mir nicht sicher wie ich das anstellen soll.
    Ich muss ja erst in Picturebox2 laden um es frei zu bekommen, oder?,o
    C# Developer
    Learning C++

    ErfinderDesRades schrieb:


    Kenn ich.
    Ist nicht so gut, da das Video Source PopUp kommt wenn mehrere Cams angeschlossen sind. Bei DirectShow ist das nicht der Fall. Das ist der Grund warum ich DirectShow verwenden möchte...
    C# Developer
    Learning C++
    Habe jetzt mal was gebastelt damit könnte es vieleicht gehen :

    VB.NET-Quellcode

    1. Private Function ScreenShotFromControl(ByVal pb As System.Windows.Forms.PictureBox, ByVal frm As System.Windows.Forms.Form) As System.Drawing.Bitmap
    2. Dim b As New Bitmap(pb.Width, pb.Height)
    3. Using g As Graphics = Graphics.FromImage(b)
    4. g.CopyFromScreen(frm.Location.X + pb.Location.X, frm.Location.Y + pb.Location.Y, 0, 0, New Size(pb.Width, pb.Height))
    5. End Using
    6. Return b
    7. End Function


    und der aufruf ist so :

    VB.NET-Quellcode

    1. Dim bitmap As Bitmap = ScreenShotFromControl(PictureBox1, Me)
    2. PictureBox2.Image = bitmap


    Dieser Sourcecode geht nur wenn das Control sichbar ist.

    MFG BlackNetworkBit
    MFG 0x426c61636b4e6574776f726b426974
    InOffical VB-Paradise IRC-Server
    webchat.freenode.net/
    Channel : ##vbparadise