none
Bild einer Webcam drehen RRS feed

  • Frage

  • Hallo,

    ich habe das Bild einer Webcam, das ich je nach Bild drehen muss. Das habe ich mit

    Me.picCapture.Image.RotateFlip(RotateFlipType.Rotate90FlipXY)

    versucht.

    Hier meckert das Programm beim Ausführen an, dass ich eine Objektinstanz mit dem Schlüsselwort "new" erzeugen soll.

    Ich habe dann folgendes versucht:

    Dim picCapture As New Image bekomme dann allerdings die Mitteilung:

    "New" darf nicht für eine Klasse verwendet werden, die als "MustInherit" deklariert ist.
    Was mache ich denn falsch oder wie geht es richtig?

     


    Liebe Grüße Stefan
    Donnerstag, 13. Mai 2010 22:27

Antworten

  • Hallo Stefan,

    Wenn ich das richtig sehe ist es nicht die Image Eigenschaft die benötigt wird, sondern das Fensterhandle, damit Du Dein Bild anzeigen kannst. Isgendwo im anderen Thread stand nämlich:

    hHwnd = capCreateCaptureWindowA(iDevice, WS_VISIBLE Or WS_CHILD, 0, 0, 1280, 860, picCapture.Handle.ToInt32, 0)

    Da steht definitiv picCapture.Handle, damit ist die Image-Eigenschaft der PictureBox außen vor. Du könntest also jedes ander Steuerelement benutzen, welches ein Window hat. Ich habe mir das nicht näher angeschaut, aber ich befürchte das mit der Funktion nicht möglich ist, das Image in irgendeiner Art und Weise zu drehen. Wenn Du mit Bildsequenzen leben kannst, bleibt Dir die Möglichkeit das Image temporär zu speichern, zu bearbeitet und dann der Image-Egenschaft zu zuweisen. Das ganze könntest Du in einem Timer-Event machen, doch erhoffe Dir kein flackerfreies Bild. Das zu müsstest Du mindest 24 Bilder pro Sekunde darstellen. Wenn ich das richtig sehen sind der 5. und 6. Parameter die Größe des Bildes. Das ist viel zuviel um ein flackfreies Bild mittels der PictureBox zu erhalten. Ein eigenes Control könnte vielleicht helfen aber immer noch nicht ausreichen. Was vielleicht wirklich den Erfolg bringt ist DirectX(DirectShow) zu benutzen. Ich weiß dass das geht, ich weiß allerdings auch dass das kein "Dreizeiler" wird. Wie das genau geht musst Du dem SDK zu DirectX entnehmen. Hier schon mal ein vorab Link:

    http://msdn.microsoft.com/en-us/library/dd407331(v=VS.85).aspx

    Gruß Scotty

     

    • Als Antwort markiert Giftzwockel Freitag, 14. Mai 2010 09:47
    Freitag, 14. Mai 2010 05:20

Alle Antworten

  • Hallo Stefan,

    Wenn ich das richtig sehe ist es nicht die Image Eigenschaft die benötigt wird, sondern das Fensterhandle, damit Du Dein Bild anzeigen kannst. Isgendwo im anderen Thread stand nämlich:

    hHwnd = capCreateCaptureWindowA(iDevice, WS_VISIBLE Or WS_CHILD, 0, 0, 1280, 860, picCapture.Handle.ToInt32, 0)

    Da steht definitiv picCapture.Handle, damit ist die Image-Eigenschaft der PictureBox außen vor. Du könntest also jedes ander Steuerelement benutzen, welches ein Window hat. Ich habe mir das nicht näher angeschaut, aber ich befürchte das mit der Funktion nicht möglich ist, das Image in irgendeiner Art und Weise zu drehen. Wenn Du mit Bildsequenzen leben kannst, bleibt Dir die Möglichkeit das Image temporär zu speichern, zu bearbeitet und dann der Image-Egenschaft zu zuweisen. Das ganze könntest Du in einem Timer-Event machen, doch erhoffe Dir kein flackerfreies Bild. Das zu müsstest Du mindest 24 Bilder pro Sekunde darstellen. Wenn ich das richtig sehen sind der 5. und 6. Parameter die Größe des Bildes. Das ist viel zuviel um ein flackfreies Bild mittels der PictureBox zu erhalten. Ein eigenes Control könnte vielleicht helfen aber immer noch nicht ausreichen. Was vielleicht wirklich den Erfolg bringt ist DirectX(DirectShow) zu benutzen. Ich weiß dass das geht, ich weiß allerdings auch dass das kein "Dreizeiler" wird. Wie das genau geht musst Du dem SDK zu DirectX entnehmen. Hier schon mal ein vorab Link:

    http://msdn.microsoft.com/en-us/library/dd407331(v=VS.85).aspx

    Gruß Scotty

     

    • Als Antwort markiert Giftzwockel Freitag, 14. Mai 2010 09:47
    Freitag, 14. Mai 2010 05:20
  • Hallo Stefan,

    Möchtest Du tatsächlichen den Video-Stream oder die einzelne Bilder drehen?

    http://vbcity.com/forums/t/94053.aspx

    [Beispiel VB.NET Code zum drehen einer PictureBox mit dem Beliebigen Winkel]

    Imports System.Drawing.Drawing2D
    Imports System.Math
    
    Public Class Form1
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
        Dim bm_in As New Bitmap(picSource.Image)
    
        '// Array von Punkten, die die Bild Ecken definieren
        Dim wid As Single = bm_in.Width
        Dim hgt As Single = bm_in.Height
        Dim corners As Point() = { _
          New Point(0, 0), _
          New Point(wid, 0), _
          New Point(0, hgt), _
          New Point(wid, hgt)}
    
        '//Translation
        Dim cx As Single = wid / 2
        Dim cy As Single = hgt / 2
        Dim i As Long
        For i = 0 To 3
          corners(i).X -= cx
          corners(i).Y -= cy
        Next i
    
        '//Drehen
        Dim theta As Single = Single.Parse("270") * PI / 180.0 '//Beliebigen Winkel eingeben
        Dim sin_theta As Single = Sin(theta)
        Dim cos_theta As Single = Cos(theta)
        Dim X As Single
        Dim Y As Single
        For i = 0 To 3
          X = corners(i).X
          Y = corners(i).Y
          corners(i).X = X * cos_theta + Y * sin_theta
          corners(i).Y = -X * sin_theta + Y * cos_theta
        Next i
    
        '//Translate, so das X >= 0 und Y >=0 für alle Ecken 
        Dim xmin As Single = corners(0).X
        Dim ymin As Single = corners(0).Y
        For i = 1 To 3
          If xmin > corners(i).X Then xmin = corners(i).X
          If ymin > corners(i).Y Then ymin = corners(i).Y
        Next i
        For i = 0 To 3
          corners(i).X -= xmin
          corners(i).Y -= ymin
        Next i
    
        '//Output Bitmap als Graphisches Objekt 
        Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
        Dim gr_out As Graphics = Graphics.FromImage(bm_out)
    
        ReDim Preserve corners(2)
    
        '//Resultat in das Output Bitmap speichern
        gr_out.DrawImage(bm_in, corners)
    
        '//Endresultat
        picDest.Image = bm_out
    
    
      End Sub
    
    End Class

    Grüße,

    Robert

    Freitag, 14. Mai 2010 08:38
    Moderator
  • Hallo Robert,

    nun ja, so ein Stream ist eine komplexe Angelegenheit. Alleine wenn ich mir ansehe, dass ich Einfluss auf die Auflöung der Kamera, Anzahl der Bilder per Sekunde nehmen kann und das bei bewegten Bildern neu berechnet werden muss, sehe ich schon, was Karsten andeutet.

    Dann habe ich eigentlich noch andere Ideen zu dem Thema gehabt. Da bin ich noch nicht weit genug und stelle das Programm lieber mal hinten an.

    Euch beiden vielen Dank.

    Aber auf diesem Weg mal eine ganz banale andere Frage. Ich sehe sehr oft, dass du Beiträge bzgl. der Formatierung nachbearbeitest.
    Gibt es Einstellungen oder Empfehlungen die dazu führen, dass die Formatierung gleich in Ordnung ist?


    Liebe Grüße Stefan
    Freitag, 14. Mai 2010 10:12
  • Hallo Stefan,

    Möchtest Du tatsächlichen den Video-Stream oder die einzelne Bilder drehen?

    http://vbcity.com/forums/t/94053.aspx

    [Beispiel VB.NET Code zum drehen einer PictureBox mit dem Beliebigen Winkel]

    Imports System.Drawing.Drawing2D
    
    Imports System.Math
    
    
    
    Public Class Form1
    
    
    
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
    
    
    
      Dim bm_in As New Bitmap(picSource.Image)
    
    
    
      '// Array von Punkten, die die Bild Ecken definieren
    
      Dim wid As Single = bm_in.Width
    
      Dim hgt As Single = bm_in.Height
    
      Dim corners As Point() = { _
    
       New Point(0, 0), _
    
       New Point(wid, 0), _
    
       New Point(0, hgt), _
    
       New Point(wid, hgt)}
    
    
    
      '//Translation
    
      Dim cx As Single = wid / 2
    
      Dim cy As Single = hgt / 2
    
      Dim i As Long
    
      For i = 0 To 3
    
       corners(i).X -= cx
    
       corners(i).Y -= cy
    
      Next i
    
    
    
      '//Drehen
    
      Dim theta As Single = Single.Parse("270") * PI / 180.0 '//Beliebigen Winkel eingeben
    
      Dim sin_theta As Single = Sin(theta)
    
      Dim cos_theta As Single = Cos(theta)
    
      Dim X As Single
    
      Dim Y As Single
    
      For i = 0 To 3
    
       X = corners(i).X
    
       Y = corners(i).Y
    
       corners(i).X = X * cos_theta + Y * sin_theta
    
       corners(i).Y = -X * sin_theta + Y * cos_theta
    
      Next i
    
    
    
      '//Translate, so das X >= 0 und Y >=0 für alle Ecken 
    
      Dim xmin As Single = corners(0).X
    
      Dim ymin As Single = corners(0).Y
    
      For i = 1 To 3
    
       If xmin > corners(i).X Then xmin = corners(i).X
    
       If ymin > corners(i).Y Then ymin = corners(i).Y
    
      Next i
    
      For i = 0 To 3
    
       corners(i).X -= xmin
    
       corners(i).Y -= ymin
    
      Next i
    
    
    
      '//Output Bitmap als Graphisches Objekt 
    
      Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
    
      Dim gr_out As Graphics = Graphics.FromImage(bm_out)
    
    
    
      ReDim Preserve corners(2)
    
    
    
      '//Resultat in das Output Bitmap speichern
    
      gr_out.DrawImage(bm_in, corners)
    
    
    
      '//Endresultat
    
      picDest.Image = bm_out
    
    
    
    
    
     End Sub
    
    
    
    End Class
    
    

    Grüße,

    Robert


    Hallo Robert,

    diese Source muss man nicht wirklich verstehen, oder? Ich meine wenn Du letzendlich das Array so wie so auf 3 Elemente "zurück schneidest", warum berechnest Du vorher 4 Elemente? Ganz davon abgesehen würde ich kein Array benutzen, sondern eine List(of Point). Aber abgesehen davon ergibt das ein Standbild und ich glaube nicht dass das der OP das wollte.

    --

    Gruß Scotty

    Freitag, 14. Mai 2010 13:06
  • Hallo Stefan,

    wie ich bereits angemerkt habe, ist so etwas nicht mit einem "Dreizeiler" erledigt. Roberts Lösung geht in die Richtung, das Du mit GDI+ machen kannst. Jedoch ist GDI+ nicht hardware-beschleunigt. Dies wiederum führt automatisch bei einer hohen "Bildauflösung" zu langsamen Frame-Rates die keine flackerfreie Darstellung ermöglichen. Mit DirectX ist das möglich, da DirectX Deine Grafikkarte direkt ansteuert und den dafür ausgelegten Prozessor und Speicher bemüht. DirectX braucht auch nur ein Fensterhandle, dass kann auch ein Handle einer bspw. PictureBox sein. Doch wie ich schon sagte, das nicht eben mal so getan, da diese Technologie nicht mit Dir diskutiert, entweder es funktioniert oder nicht. Detailierte Fehlermeldungen liefert Dir DirectX, auch wenn die Managed Variante nutzt nicht. OpenGL wäre noch eine Alternative, aber frag mich nicht nach Details, ich kann zwar viel essen, aber nicht alles wissen.

    --

    Gruß Scotty

    Freitag, 14. Mai 2010 13:31
  • Hallo Karsten Sosna,

    Deswegen habe ich am Anfang die Direkte Frage gefragt:

    „Möchtest Du tatsächlichen den Video-Stream oder die einzelne Bilder drehen?“

    Nachher habe ich eine Lösung, die funktioniert, für den zweiten Teil der Frage gegeben (einzelne Bilder drehen) (die man sicher wie Du sagst noch besser schreiben kann – Danke für den Hilfreichen Hinweis).

    Bin später draufgekommen dass Stefan den Video-Stream meinte. Klar, wie Du sagst ist Hardware (DirectX, OpenGL) bearbeiten besser als Software (GDI+).

    @Stefan: Ich bearbeite die Formatierung weil die Forum Plattform zeigt manchmal sehr schlecht (klein geschrieben, verschiedene Fonts, etc.) den Beitrag an. Und wenn da noch Code inzwischen ist sieht das sehr schlecht aus und die Benutzer (jetzige, zukünftige) können das sehr schwer verstehen. Wenn ich ein Beitrag poste mache ich folgendes: schreibe es zuerst in Word, immer mit Verdana 8 und nachher Copy&Paste in den Forum Editor. Code immer durch den Knopf „Codeblock einfügen“.

    Grüße,

    Robert

    Freitag, 14. Mai 2010 14:37
    Moderator