directshowlib-2005 Video auf dem Kopf??

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von grisu74.

    directshowlib-2005 Video auf dem Kopf??

    Hallo zusammen,

    ich benutze die directshowlib-2005.dll Libary zum speichern von Bildern mit der Webcam.
    Leider finde ich nirgends wie ich das Videobild drehen kann.

    Das Bild zum Speichern kann ich drehen.
    Kennt sich damit jemand aus?

    Gruß Udo
    Hi

    Dazu müsstest mal zeigen wie Du an das Bild der Webcam kommst und wie Du das Bild dann in ein Video speicherst. Was mir auf die schnelle dazu einfällt ist das bei GDI32 Bildern der Scan0 unten links liegt und bei GDI+ oben links. Falls Du irgendwo die Höhe des Bildes für das Speichern im Video angeben kannst, versuche dort die Höhe als negativen Wert anzugeben.
    Mfg -Franky-
    Hi

    Ich hab mal den Code kurz überflogen. Die relevanten Stellen dürften diese sein.

    m_videoWidth = vInfoHeader.BmiHeader.Width
    M_videoHeight = vInfoHeader.BmiHeader.Height

    Bei BmiHeader.Height müsstest mal schauen wo das noch steht. Diesen mal als negativen Wert angeben.
    Mfg -Franky-
    Hallo,

    beim debuggen habe ich den wert einfach mal negativ geschrieben.
    Leider kein Erfolg.
    Das Video ist immernoch auf dem Kopf.

    Wenn ich dieses Beispiel hier verwende, ist das Bild komischerweise richtig herum.
    Kannst du dir das mal ansehen?
    codeproject.com/Articles/18511/Webcam-using-DirectShow-NET

    Leider sind meine Programmierkenntnisse zu gering das ich den Unterschied erkenne.

    Gruß Udo
    Hi

    Es muss ja nicht diese Stelle sein. Du müsstest die Stelle suchen, wo das Bild in das Video geschrieben wird. In der Function SampleCB wird das Bild ja extra gedreht damit du das richtig herum sehen kannst. capturedPic.RotateFlip(RotateFlipType.RotateNoneFlipY) Daher auch meine Vermutung das dies mit GDI32 (Bottom/Left) und GDI+ (Top/Left) zusammen hängt. Ich hab jetzt auch nicht die Zeit mir die anderen Projekte anzuschauen. Da musst mal selbst Durchdebuggen wo was passiert.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    @grisu74
    Hi nur noch mal so als Nachfrage. Den Code, den Du verwendest, schreibt ja gar kein Video. Das speichert ja nur Bilder. Was steht denn jetzt auf dem Kopf? Das Video von der WebCam oder das Bild das dann davon gespeichert wird? Falls es um das Video geht, das in einer PictureBox dargestellt wird, dann könntest Du beim Interface IAMVideoControl ansetzen. IAMVideoControl.GetCaps gibt Dir entsprechende VideoControlFlags zurück. Hier prüfst Du ob der Flag VideoControlFlag_FlipHorizontal angeboten wird. Wenn ja, dann kannst Du per IAMVideoControl.SetMode entsprechenden Flag VideoControlFlag_FlipHorizontal setzen um das Video horizontal zu spiegeln. Mehr kann ich zum Thema WebCam Capture mit DirectShow nicht sagen. DirectShow ist ja auch schon ein wenig veraltet.

    Falls ich was missverstanden hatte, was Du möchtest, bitte ich um Entschuldigung. Ich hatte mir am WE auch nur per Handy den Code, den Du verwendest, angeschaut.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    @grisu74 Diese vielen, alten Code-Beispiele aus irgendwelchen (veralteten) Foren taugen nichts. Es kommt hier bei vb-paradise.de des Öfteren vor, dass sich hier ein neues Mitglied meldet und fragt, warum sein Code zum Abgreifen der WebCam nicht geht. Und ich sage dir: Es ist immer derselbe Code (bei dir jetzt mal nicht); entnommen von derselben, alten Seite. Der Code enthält irgendwelche obskuren Functions und das Bild ist am Ende 340 × 280 Pixel groß.

    Ich habe das vor 2½ Jahren selbst mal gecodet – daher bitte ich um Nachsicht, wenn der Code noch nicht perfekt ist. Ich nutze AForge. Das kannst du dir im Visual-Studio-eigenen NuGet-Paket-Manager (siehe Anhang) herunterladen.
    Mach dir einen Start-Button und einen Stopp-Button. Wenn du den Start-Button drückst, erscheint ein Dialogfenster, auf dem du die Kamera-Qualität einstellen kannst.

    Es gibt außerdem eine Extension, die Windows auffordert, den PC während des Kamerabild-Abgreifens nicht in den Standby-Modus zu versetzen.

    Übrigens: Der
    CommonSaveFileDialog dient nur dazu, den Ordnerpfad auszuwählen, in dem manuell gemachte "Screenshots" gespeichert werden. Du brauchst also noch einen Button.

    Übrigens 2: Es kommt bei solchen Programmen vor, dass das Antivirenprogramm meldet, dass dein Programm die Webcam benutzen will. Hier klickst du dann auf "Erlauben".

    Kameraprogramm

    VB.NET-Quellcode

    1. #Disable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
    2. #Disable Warning CA1303 ' Literale nicht als lokalisierte Parameter übergeben
    3. #Disable Warning CA2007 ' Aufruf von "ConfigureAwait" für erwarteten Task erwägen
    4. #Disable Warning CA9998
    5. Public NotInheritable Class Form_Main
    6. Private gew_Kamera As AForge.Video.DirectShow.VideoCaptureDevice 'gewählte Kamera
    7. Private Shared Einzelfoto As Bitmap
    8. Public ReadOnly Property Cameras1 As AForge.Video.DirectShow.VideoCaptureDeviceForm = New AForge.Video.DirectShow.VideoCaptureDeviceForm 'alle möglichen Kameras
    9. Private FehlerNr As UInt16
    10. Private ReadOnly Deu As New System.Globalization.CultureInfo("de-DE")
    11. Private Speicherpfad As String = ""
    12. Private Einzelfotoindex As UInt16 = 1US
    13. Private ReadOnly Ausgangsfarbe As Color = Color.FromArgb(84, 184, 255)
    14. Private ReadOnly Gruen As Color = Color.FromArgb(0, 255, 0)
    15. Private Property Einzelfotobedarf As Boolean
    16. Private Sub Form_Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    17. Dim die_Bildschirme As Screen() = System.Windows.Forms.Screen.AllScreens()
    18. If die_Bildschirme.Length = 1 AndAlso (die_Bildschirme(0).Bounds.Width < 1920 OrElse die_Bildschirme(0).Bounds.Height < 1080) Then
    19. MessageBox.Show("Dieses Programm ist für große Bildschirme ausgelegt worden (mindestens 1920 × 1080). Es ist nur ein Bildschirm angeschlossen, und dieser hat nicht die nötigen Maße.",
    20. "Kameraprogramm",
    21. MessageBoxButtons.OK,
    22. MessageBoxIcon.Exclamation)
    23. Me.Close()
    24. Return
    25. End If
    26. Me.Location = New Point(0, 0)
    27. Button_Start.BackColor = Ausgangsfarbe
    28. Button_Stopp.BackColor = Ausgangsfarbe
    29. Button_Foto.BackColor = Ausgangsfarbe
    30. PictureBox1.BackColor = Color.FromArgb(0, 0, 20)
    31. Me.BackColor = Color.FromArgb(0, 0, 0)
    32. End Sub
    33. Private Async Sub Button_Start_Click(sender As Object, e As EventArgs) Handles Button_Start.Click
    34. TextBox1.Text = ""
    35. Await Task.Run(Sub() Starten())
    36. End Sub
    37. Private Sub Starten()
    38. Using SFD1 As New Microsoft.WindowsAPICodePack.Dialogs.CommonSaveFileDialog
    39. SFD1.Title = "Wo sollen die Bilder gespeichert werden?"
    40. SFD1.Filters.Add(New Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogFilter("PNG", ".png"))
    41. SFD1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
    42. Dim Result As Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult
    43. Me.Invoke(Sub() Result = SFD1.ShowDialog())
    44. If Result = Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult.Ok Then
    45. Speicherpfad = SFD1.FileName
    46. Speicherpfad = Speicherpfad.Substring(0, Speicherpfad.LastIndexOfAny({"\"c}))
    47. Else
    48. Me.Invoke(Sub() Button_Start.BackColor = Ausgangsfarbe)
    49. Return
    50. End If
    51. End Using
    52. Dim Resul As DialogResult
    53. Me.Invoke(Sub() Resul = Cameras1.ShowDialog())
    54. If Resul = DialogResult.OK Then
    55. gew_Kamera = Cameras1.VideoDevice
    56. AddHandler gew_Kamera.NewFrame, New AForge.Video.NewFrameEventHandler(AddressOf Captured)
    57. Me.Invoke(Sub() Button_Start.Enabled = False)
    58. Me.Invoke(Sub() Button_Start.BackColor = Gruen)
    59. Me.Invoke(Sub() Button_Stopp.BackColor = Ausgangsfarbe)
    60. gew_Kamera.Start()
    61. Me.Invoke(Sub() Timer1.Start())
    62. End If
    63. End Sub
    64. Private Sub Captured(sender As Object, eventArgs As AForge.Video.NewFrameEventArgs)
    65. If Einzelfotobedarf Then
    66. Einzelfoto = New Bitmap(DirectCast(eventArgs.Frame.Clone(), Bitmap))
    67. End If
    68. 'try / Catch, weil er, wenn er ausgelastet ist, zeitgleich ein Bild in die Picturebox legen will und eines entnehmen will
    69. Try
    70. If eventArgs.Frame IsNot Nothing Then
    71. If PictureBox1.Image IsNot Nothing Then
    72. PictureBox1.Image.Dispose()
    73. End If
    74. PictureBox1.Image = DirectCast(eventArgs.Frame.Clone(), Image)
    75. End If
    76. Catch ex As System.InvalidOperationException
    77. FehlerNr += 1US
    78. Me.Invoke(Sub() TextBox1.Text = FehlerNr.ToString(Deu) & " × System.Invalid Operation Exception in der Prozedur ‚Captured‘")
    79. End Try
    80. End Sub
    81. Private Sub Button_Stopp_Click(sender As Object, e As EventArgs) Handles Button_Stopp.Click
    82. If gew_Kamera IsNot Nothing Then 'If für den Fall, dass gar keine Kamera gewählt worden war.
    83. gew_Kamera.Stop()
    84. TextBox1.Text = "Kamera aus"
    85. End If
    86. TextBox1.Text = TextBox1.Text + "; fertig."
    87. Button_Start.Enabled = True
    88. Button_Start.BackColor = Ausgangsfarbe
    89. Button_Stopp.BackColor = Gruen
    90. PictureBox1.Image = Nothing
    91. Timer1.Stop()
    92. GC.Collect()
    93. End Sub
    94. Private Async Sub Button_Foto_Click(sender As Object, e As EventArgs) Handles Button_Foto.Click
    95. Await Task.Run(Sub() Speichern())
    96. End Sub
    97. Private Sub Speichern()
    98. Dim D As Date = Date.Now
    99. Einzelfotobedarf = True
    100. System.Threading.Thread.Sleep(50)
    101. Select Case Speicherpfad
    102. Case Nothing
    103. Case Else
    104. If Einzelfoto IsNot Nothing Then
    105. Einzelfoto.Save(Speicherpfad & "\manuelles Foto" & " " & Einzelfotoindex.ToString(Deu) & " " & D.Day & "-" & D.Month & "-" & D.Year & ".png", System.Drawing.Imaging.ImageFormat.Png)
    106. Einzelfotoindex += 1US
    107. End If
    108. End Select
    109. Einzelfotobedarf = False
    110. End Sub
    111. Private Sub Form_Main_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    112. Try 'du kannst nur fragen, ob die Kamera (noch) läuft, wenn eine gewählt worden war!
    113. If gew_Kamera IsNot Nothing Then
    114. If gew_Kamera.IsRunning Then
    115. gew_Kamera.Stop()
    116. End If
    117. Cameras1.Dispose()
    118. End If
    119. Catch ex As System.NullReferenceException
    120. End Try
    121. If Einzelfoto IsNot Nothing Then
    122. Einzelfoto.Dispose()
    123. End If
    124. End Sub
    125. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    126. WinApi.SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS Or EXECUTION_STATE.ES_SYSTEM_REQUIRED Or EXECUTION_STATE.ES_DISPLAY_REQUIRED)
    127. End Sub
    128. End Class
    129. Friend Module WinApi
    130. <Runtime.InteropServices.DllImport("kernel32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto, SetLastError:=True)>
    131. Public Function SetThreadExecutionState(ByVal flags As EXECUTION_STATE) As EXECUTION_STATE
    132. End Function
    133. <Flags>
    134. Public Enum EXECUTION_STATE As Integer
    135. ES_AWAYMODE_REQUIRED = &H40
    136. ES_CONTINUOUS = &H80000000
    137. ES_DISPLAY_REQUIRED = &H2
    138. ES_SYSTEM_REQUIRED = &H1
    139. End Enum
    140. End Module
    141. #Enable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
    142. #Enable Warning CA1303 ' Literale nicht als lokalisierte Parameter übergeben
    143. #Enable Warning CA2007 ' Aufruf von "ConfigureAwait" für erwarteten Task erwägen



    Bilder
    • Screenshot 2022-02-28 153308.png

      58,91 kB, 1.074×709, 77 mal angesehen
    • Kamera-Auswählen-Dialog.png

      15,99 kB, 473×265, 72 mal angesehen
    • Kaspersky meldet.png

      28,33 kB, 415×480, 77 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Bartosz“ ()

    Hallo,

    danke erst mal für die Unterstützung.
    @-Franky- Das Video steht auf dem Kopf. Das Bild kann ich mit Rotate drehen.

    Ich möchte das ganze auf einem Surface Pro nutzen. Es ist überhaupt schwer was im Netz zu finden.
    @Bartosz Ich werde dein Programm mal ausprobieren.

    Letztendlich benötige ich ein Bild für eine Mängelsoftware das direkt vor Ort aufgenommen werden kann.

    Gruß Udo
    Moin moin @grisu74

    grisu74 schrieb:

    Das Video steht auf dem Kopf.

    Wie geschrieben könntest Du in der Sub SetConfigParms hinter Dim videoControl As IAMVideoControl = DirectCast(capFilter, IAMVideoControl) versuchen, ich kenne den Verweis den Du nutzt nicht, per videoControl.GetCaps entsprechende Flags auszulesen und wenn der Flag VideoControlFlag_FlipHorizontal angeboten wird, diesen per videoControl.SetMode zu setzen.

    grisu74 schrieb:

    Es ist überhaupt schwer was im Netz zu finden.

    So würde ich das nicht sagen. Beispiele, zB auf die asbachalte API capCreateCaptureWindow sowie per DirectShow, findest wie Sand am Meer. In Bezug auf VB.NET gebe ich Dir allerdings recht. Da ist die Auswahl, die halbwegs brauchbar ist, doch sehr gering und wie @Bartosz schon angemerkt hat, kopieren die meisten immer wieder den gleichen Code der sich auf diversen Seiten wiederfindet. Beispiele per "Windows Media Foundation" für VB.NET sind sogut wie gar nicht zu finden. Dabei ist für letzteres alles sehr gut in der Microsoft Doku beschrieben.
    Mfg -Franky-