Bild in Bild erkennen und extra speichern

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    Bild in Bild erkennen und extra speichern

    Hey Leute!

    Meine Ausgangssituation ist wie folgt:
    Ich habe ein Bild: spriters-resource.com/snes/str…ampionedition/sheet/5573/
    Wie ihr sehen könnt sind auf diesem Bild kleinere Bilder zu erkennen die ich gerne separieren möchte.
    Sprich: Ich möchte, in diesem fall, die einzelnen kleinen Bilder erkennen und als extra Bild abspeichern.

    Wie ist den da die beste herangehensweise?
    Dazu zu sagen ist, dass gesamt Bild auf immer eine andere Hintergrundfarbe haben kann(Aber das sollte jetzt erstmal egal sein)

    EDIT: Eine Lösung von VB1963 und mir findet ihr hier PIPP (Picture In Picture Picker)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gelöschter Benutzer“ ()

    Gelöschter Benutzer schrieb:

    Dazu zu sagen ist, dass gesamt Bild auf immer eine andere Hintergrundfarbe haben kann(Aber das sollte jetzt erstmal egal sein)
    Ich glaube, dass das immens wichtig ist!

    Nur hypothetisch angedacht:
    • Suche im Gesamtbild Pixel und alle Nachbarpixel mit einer anderen Farbe als die Hintergrundfarbe ist und merke dir dabei die äußeren Grenzseiten.
    • Da müsste, denke ich einmal, ein rechteckiger Ausschnitt eines Detailbildes gefunden worden sein.
    • Kopiere diesen Ausschnitt in ein File und überdecke nachher diesen Ausschnitt im Gesamtbild mit der bekannten Hintergrundfarbe.
    • Dann das nächste Bildlein suchen usw...
    @Kameo Auf wie viele Bilder willst Du den Algorithmus anwenden?
    Ist die Position der Ziel-Bilder in allen Quellbildern (etwa) gleich?
    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!
    @VB1963 Der Ablauf klingt schonmal ganz gut!
    Rechteckig werden glaube ich nur die wenigsten Bilder da in machen Ausgangsbildern ja auch Köpfe oder Pflanzen o.ä. enthalten sein können, was aber beim Speichern der neuen Bitmap keine probleme machen sollte(oder?)

    Das mit der Hintergrundfarbe ist natürlich wichtig, nur wollte ich mich jetzt erstmal auf eine Hintergrundfarbe konzentrieren.

    @RodFromGermany Den Algorithmus will ich auf X beliebig viele Bilder anwenden, aber maximal auf eins pro Programm Durchlauf.
    Die Position und Anzahl der Ausgangsbilder variiert von Bild zu Bild.
    Die Position der entgültigen Bilder ist ja egal, denn wenn es fertig ist soll es ja später so aussehen:
    Ausgangsbild.png -> Durchs Programm jagen -> Bild1.png, Bild2.png usw.. dabei herausspeichern

    Gelöschter Benutzer schrieb:

    aber maximal auf eins pro Programm Durchlauf.
    Wie oft findet das statt?
    Kannst Du händisch eingreifen, also z.B. einen Rahmen um ein Bild ziehen und der Algo extrapoliert gleich große Teilbilder?
    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!
    Mein Ansatz:
    Pixel Zeilenweise durchgehen und gedanklich bis zum ersten Pixel != Hintergrundfarbe markieren. Spaltenweise dasselbe machen. An Punkten wo sich die beiden Schneiden kannst du vom letzten gefunden Punkt links oben(oder ganz links oben - falls transparent raus soll, eben noch den Minima Abstand der Suche hinzuziehen). Wichtig ist dabei, dass bei jeder Kollision von Zeilen und Spalten du dort die Suche nach Unten und Rechts durchführen musst, als wär es ein neues Bild. Hört sich kompliziert an, ist es auch ein wenig, aber dürfte gut Parallelisierbar sein. Auch gut auf der GPU machbar. man könnte z.B. Zeilenweise und Spaltenweise auf der GPU anwenden und den AlphaChannel des Bildes halbieren(vorrausgesetzt AlphaChannel wird nicht verwendet, ansonsten kann man einfach eine extra leere Textur verwenden), an Stellen, an denen dann Alpha<= 64 gibt es dann Schnittpunkte, die du von Links oben abwechselnd durchgehen kannst.

    Ob er nachher performanter ist keine Ahnung, evtl. auch für dich überhaupt nicht relevant

    @VB1963:'s Algo würde ich denke ich mittels FloodFill machen, damit schließt man das finden von "Bildern in Bildern" aus
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @RodFromGermany
    Ein Programm Durchlauf bedeutet ein Bild in Einzelbilder zerlegen.
    Von Hand eingreifen ginge, würde aber den Zweck verfehlen, denn Ziel des Programms ist,das ich die Bilder nicht selbst in Photoshop zerschnibbeln muss, sondern ein Gesamt Bild durchs Programm jagen und alle Gefundenen Einzelbilder als separate *.PNG Dateien im Ordner abspeichern kann.

    @jvbsl
    Wenn ich den Ablauf richtig verstanden habe geht man bei deiner Methode Reihe für Reihe (Spalte für Spalte) durch das Bild, und sobald ein Pixel von der Hintergrundfarbe abweicht "merke" ich ihn mir und fahre dann mit dem Suchen fort.Bin ich dann das ganze Bild durchgegangen nehme ich alle "gemerkten" Pixel und exportiere ich sie als separates Bild?

    Auf GPU auslagern muss nicht unbedingt sein, es sei den die extra Codezeilen lassen sich an einer Hand abzählen, den Performance ist zweitrangig bis unwichtig
    In C# könnte man das mit unsafe Code relativ einfach realisieren, in VB bist du dann auf Get/SetPixel limitiert (zumindest wenn du es mit Frameworkmitteln machst).
    Ich würde es so machen:
    Erstmal eine Liste vom Typ Rectangle machen und dann durch alle Pixelreihen durchloopen und gucken: Ist dieser Pixel in der Hintergrundfarbe? Wenn nein, boolean setzen und Position merken. Wenn du dann wieder auf mindestens 10 Hintergrundpixel stößt, die hintereinander kommen, ist die Serie beendet und du fügst ein neues Rectangle in die Liste ein, welches die Anfangskoordinaten und die aktuelle Breite hat.
    Wenn das durch ist, hast du vielleicht 700 Rectangles. Jetzt musst du alle Rectangles, die aneinander liegen, finden und zu einem neuen Rectangle hinzufügen. Dann solltest du alle Rectangles der einzelnen Bilder haben.

    In C# wäre das halt alles sehr einfach zu realisieren, da kannst du dann auch einfach die Rectangles kopieren (bzw. Stride für Stride).
    Mfg
    Vincent

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

    Naja das mit dem merken passiert ja automatisch, durch den Zähler der Schleife und eben dann rekursiv, oder iterativ in einer Liste, wobei du nicht jeden Punkt abspeicherst, sondern nur die Kollisionspunkte
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---