Picturebox, richtige Koordinaten abgreifen, Bild in Darstellungsgröße speichern

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Picturebox, richtige Koordinaten abgreifen, Bild in Darstellungsgröße speichern

    Neu

    Hallo zusammen,

    aktuell möchte ich Bilder von meinen Modelleisenbahnmodellen transparent machen, in dem ich den weißen Hintergrund entfernen möchte. Klappt aktuell auch schon ganz gut.

    Im zweiten Schritt soll nun mein Bild von allen Seiten beschnitten werden, so dass am Ende ein Rahmen direkt um das Modell entsteht.

    Mit der Maus möchte ich die Y-Achse für Links/Rechts und für Oben / Unten werde ich 2 mal die X Achse festlegen. Bei der Y-Achse wird es fast immer die Kupplungshöhe sein und bei der X Achse der jeweilige höchste Punkt und der tiefste Punkt einer Aufnahme sein. Von diesen Startpunkten wird es dann noch einen kleinen Ausgleichsbereich geben, damit auch ein paar Pixel drum herum die Farbe untersucht wird. Stehen dann die Ergebnisse fest, dann soll erst einmal ein Rahmen / Linien angezeigt werden, die mir das Ganze Ergebnis anzeigen.
    Bestätige ich nun dieses Ergebnis, dann soll auch nur dieser Bereich als neues Bild abgespeichert werden.

    Nur leider bekomme ich das aktuell mit meinem Code nicht so hin.

    Da mein jetziger Code nach dem Laden des nicht transparenten Bildes dies direkt umwandelt und abspeichert, muss also die Prüfung der Farbwerte > color.Transparent sein.

    Ich hänge jetzt erst einmal meinen aktuellen Code kpl. an. Da gibt es am Ende mit Sicherheit noch optimierungsbedarf, aber erst einmal will ich das Problem gelöst haben bzw. den Grund für meine Schwierigkeiten herausbekommen.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Imaging
    2. Imports System.Drawing
    3. Public Class Form1
    4. Dim farbe As Color
    5. Dim mw_farbe As Integer
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. Dim Dateipfad As String
    8. Dateipfad = "C:\Temp\Testlok.jpg"
    9. 'Dateipfad = "D:\Temp\Testwagen.jpg"
    10. PictureBox1.Image = Image.FromFile(Dateipfad)
    11. PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
    12. Dim bild As Bitmap = PictureBox1.Image
    13. Dim Schwelle As Integer = LBl_Schwellenwert.Text ' hier Deinen Wert vorgeben
    14. For x As Int32 = 0 To bild.Width - 1
    15. For y As Int32 = 0 To bild.Height - 1
    16. farbe = bild.GetPixel(x, y)
    17. mw_farbe = (CInt(farbe.R) + CInt(farbe.G) + CInt(farbe.B)) / 3
    18. If mw_farbe < Schwelle Then
    19. bild.SetPixel(x, y, farbe)
    20. Else
    21. bild.SetPixel(x, y, Color.Pink)
    22. End If
    23. Next
    24. Next
    25. ' Transparente Farbe festlegen
    26. bild.MakeTransparent(System.Drawing.Color.Pink)
    27. bild = PictureBox1.Image
    28. 'bild.Save("C:\Temp\Test_Transparent.png", Imaging.ImageFormat.Png) 'Bitmap abspeichern
    29. 'bild = Nothing 'und aus dem ram werfen, wenn du In der Sub noch was machen willst.
    30. Dim Pic1 As New Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height)
    31. Dim g As Graphics = Graphics.FromImage(Pic1)
    32. Pic1.Save("C:\Temp\Test_Transparent.png", System.Drawing.Imaging.ImageFormat.Png)
    33. Pic1.Dispose()
    34. End Sub
    35. Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll
    36. Me.LBl_Schwellenwert.Text = Me.TrackBar1.Value
    37. End Sub
    38. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    39. Me.WindowState = FormWindowState.Maximized
    40. Me.LBl_Schwellenwert.Text = 235
    41. Me.TrackBar1.Value = Me.LBl_Schwellenwert.Text
    42. End Sub
    43. Private Sub PictureBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
    44. Me.LabelX.Text = e.X
    45. Me.LabelY.Text = e.Y
    46. Dim Bild As New Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height)
    47. Dim Farbe As Color
    48. Farbe = Bild.GetPixel(e.X, e.Y - 1)
    49. LBL_FarbeA.Text = CInt(farbe.A)
    50. LBL_FarbeR.Text = CInt(farbe.R)
    51. LBL_FarbeG.Text = CInt(farbe.G)
    52. LBL_FarbeB.Text = CInt(farbe.B)
    53. LBL_FarbeRGB.BackColor = Color.FromArgb(LBL_FarbeA.Text, LBL_FarbeR.Text, LBL_FarbeG.Text, LBL_FarbeB.Text)
    54. End Sub
    55. Private Sub Btn_Links_Eingrenzen_Click(sender As Object, e As EventArgs) Handles Btn_Links_Eingrenzen.Click
    56. Dim Bild As New Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height)
    57. Dim Weiter As Boolean = True
    58. For y As Int32 = CInt(Me.LabelY.Text) - 40 To CInt(Me.LabelY.Text) + 40
    59. For x As Int32 = 1 To Bild.Width - 1
    60. Try
    61. farbe = Bild.GetPixel(x, y)
    62. Catch ex As Exception
    63. farbe = Color.White
    64. Bild.SetPixel(x, y, Color.Pink)
    65. End Try
    66. mw_farbe = (CInt(farbe.A) + CInt(farbe.R) + CInt(farbe.G) + CInt(farbe.B)) / 3
    67. Label1.Text = mw_farbe
    68. If mw_farbe > 0 Then
    69. Dim g As System.Drawing.Graphics
    70. Dim pen1 As New System.Drawing.Pen(Color.Black, 3)
    71. g = PictureBox1.CreateGraphics
    72. x = x - 7
    73. g.DrawLine(pen1, x, 10, x, PictureBox1.Height - 10)
    74. Weiter = False
    75. Exit For
    76. Else
    77. End If
    78. Bild.SetPixel(x, y, Color.Red)
    79. Next x
    80. If Weiter = False Then
    81. Exit For
    82. End If
    83. Next y
    84. End Sub
    85. Private Sub Btn_Rechts_Eingrenzen_Click(sender As Object, e As EventArgs) Handles Btn_Rechts_Eingrenzen.Click
    86. Dim Bild As New Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height)
    87. Dim Weiter As Boolean = True
    88. For y As Int32 = CInt(Me.LabelY.Text) - 40 To CInt(Me.LabelY.Text) + 40
    89. For x As Int32 = Bild.Width - 1 To 1 Step -1
    90. Try
    91. farbe = Bild.GetPixel(x, y)
    92. Catch ex As Exception
    93. farbe = Color.White
    94. Bild.SetPixel(x, y, Color.Pink)
    95. End Try
    96. mw_farbe = (CInt(farbe.R) + CInt(farbe.G) + CInt(farbe.B)) / 3
    97. Label1.Text = mw_farbe
    98. If mw_farbe > 0 Then
    99. Dim g As System.Drawing.Graphics
    100. Dim pen1 As New System.Drawing.Pen(Color.Black, 3)
    101. g = PictureBox1.CreateGraphics
    102. x = x - 7
    103. g.DrawLine(pen1, x, 10, x, PictureBox1.Height - 10)
    104. Weiter = False
    105. Exit For
    106. End If
    107. Next x
    108. If Weiter = False Then
    109. Exit For
    110. End If
    111. Next y
    112. End Sub
    113. Private Sub Btn_Oben_Eingrenzen_Click(sender As Object, e As EventArgs) Handles Btn_Oben_Eingrenzen.Click
    114. Dim Bild As New Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height)
    115. Dim Weiter As Boolean = True
    116. For x As Int32 = CInt(Me.LabelX.Text) - 20 To CInt(Me.LabelX.Text) + 20
    117. For y As Int32 = CInt(Me.LabelY.Text) To Bild.Height - 1
    118. Try
    119. farbe = Bild.GetPixel(x, y)
    120. Catch ex As Exception
    121. farbe = Color.White
    122. Bild.SetPixel(x, y, Color.Pink)
    123. End Try
    124. mw_farbe = (CInt(farbe.R) + CInt(farbe.G) + CInt(farbe.B)) / 3
    125. Label1.Text = mw_farbe
    126. If mw_farbe > 0 Then
    127. Dim g As System.Drawing.Graphics
    128. Dim pen1 As New System.Drawing.Pen(Color.Black, 3)
    129. g = PictureBox1.CreateGraphics
    130. g.DrawLine(pen1, 10, y, PictureBox1.Width - 10, y)
    131. Weiter = False
    132. Exit For
    133. End If
    134. Next y
    135. If Weiter = False Then
    136. Exit For
    137. End If
    138. Next x
    139. End Sub
    140. Private Sub Btn_Unten_Eingrenzen_Click(sender As Object, e As EventArgs) Handles Btn_Unten_Eingrenzen.Click
    141. End Sub
    142. End Class


    Des weiteren noch ein paar Screenshots von dem bisherigen Ergebnissen
    Bild1 = Der kleine rote Punkt ist die ungefähre Stelle, an der ich die Y Achse bestimmt habe. Die beiden senkrechten Striche von außen gesehen, sind meine Hilfslinien, die mir das Ergebnis anzeigen. Sie sind also noch sehr weit weg vom Endergebnis.
    Bild2 = Auch hier kurz von dem Puffer einen Mausklick gemacht
    Testlok.jpg (2032 x 1088 Pixel) = Da ich aus rechtlichen Gründen sicher sein will, habe ich mir eine Lok eh mit CorelDraw selbst gezeichnet und diese genommen. Den Hintergrund habe ich nachträglich mit Paint.Net weiß eingefärbt und als JPG - Datei abgespeichert.
    Testwaggon.jpg (2032 x 1088 Pixel) = Hier das gleiche und etwas breiteres Bild

    Das schwarze Rechteck oben im blauen Panel soll mir eigentlich die aktuelle Farbe meines Mausklick-Koordinatenpunktes anzeigen. Wir ihr aber seht, ist dort aber kein Schwarz zu sehen. Bei dem Wagen stimmt die Anzeige eigentlich auch nicht.

    Ich befürchte, dass hat etwas mit dem Zoomen der Grafik zu tun. Der GetPixel-Befehl greift hier ggf. nicht auf die Anzeige zurück, sondern auf das Bild, welches ohne Zoom entstehen würde. Aber auch dies habe ich mal mit dem Wagenbild getestet (Ergebnis Bild 3, Zeile PictureBox1.SizeMode = PictureBoxSizeMode.Zoom habe ich deaktiviert).

    Habt Ihr eine Idee, was ich machen muss, damit mein Bild richtig erkannt wird und dann mit diesem Bereich abgespeichert werden kann?

    Bin mal auf Eure Antworten gespannt.

    Volker

    *Topic verschoben*
    Bilder
    • Testlok.jpg

      95,07 kB, 2.032×1.088, 2 mal angesehen
    • Testwagen.jpg

      97,41 kB, 2.032×1.088, 1 mal angesehen
    • Bild1.png

      47,02 kB, 1.917×1.037, 1 mal angesehen
    • Bild2.png

      48,54 kB, 1.916×1.039, 3 mal angesehen
    • Bild3.jpg

      154,17 kB, 1.912×1.039, 2 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Neu

    @Volker Bunge Ich habe das Gefühl, dass Du Dir viel zu viel Arbeit machst.
    Warum sind Deine Eisenbahn-Bilder so riesig groß (2000 x 1000 Pixel)?
    Bearbeite Deine Bilder in Paint, speichere sie als PNG ab.
    Schreibe Dir ein kleines Programm, mit dem Du Deine ansonsten fertigen Bilder transparent machst und die transparenten Bilder ebenfalls als PNG abspeicherst.
    Füge diese Bilder unter sinnvollen Namen Deinen Projektressourcen hinzu.
    Zeichne diese Bilder dahin, wo sie erscheinen sollen.
    Was für Probleme gibt es?
    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!

    Neu

    Hallo RodFromGermany,

    genau diese Bearbeitung wollte ich mir erleichtern. Mit Paint bzw. Paint.Net den weißen Hintergrund wegzubekommen ist jetzt auch nicht so einfach, gerade in den kleinen Zwischenräumen.

    Das Testbild ist tatsächlich vielleicht etwas groß, aber später sollen die Bilder auch eine gute Qualität haben.

    Die Möglichkeit, das Motiv in einem Rechteck fangen zu können, wäre halt insofern schön, das ich mit diesen Bildern dann so einiges machen könnte.

    Hast Du den eine Idee, warum mein Plan so nicht funktioniert, den Anfang und das Ende meines Bildes zu ermitteln? Das würde mich schon sehr interessieren, warum das nicht klappt bzw. wie es klappen könnte.

    Die Bilder sollen nicht als Projektrescource genutzt werden (aber das ist ja nebenbei erwähnt).

    Aufgrund der Masse an späteren Bildern wäre halt eine möglichst vollautomatische Lösung nice.

    Gruß
    Volker

    Neu

    Volker Bunge schrieb:

    den Anfang und das Ende meines Bildes zu ermitteln
    Alle Zeilen von oben und unten sowie die Spalten von rechts und von links nach dem ersten signifikanten Pixel durchsuchen.
    Wenn Du die Bilder vorher schneidest, entfällt diese Suche.
    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!