Ich habe mit der Herstellung von Bildmosaiken gespielt. Mein Skript nimmt eine große Anzahl von Bildern auf, verkleinert sie auf die Größe der Miniaturansichten und verwendet sie dann als Kacheln, um ein Zielbild zu approximieren.
Der Ansatz ist eigentlich recht erfreulich:
Ich berechne den mittleren quadratischen Fehler für jeden Daumen in jeder Kachelposition.
Zuerst habe ich nur eine gierige Platzierung verwendet: Legen Sie den Daumen mit dem geringsten Fehler auf die Kachel, die am besten passt, und dann die nächste und so weiter.
Das Problem mit gierig ist, dass Sie schließlich die unterschiedlichsten Daumen auf die am wenigsten beliebten Kacheln legen, unabhängig davon, ob sie genau übereinstimmen oder nicht. Ich zeige hier Beispiele: http://williamedwardscoder.tumblr.com/post/84505278488/making-image-mosaics
Also mache ich dann zufällige Swaps, bis das Skript unterbrochen wird. Die Ergebnisse sind ganz in Ordnung.
Ein zufälliger Austausch von zwei Kacheln ist nicht immer eine Verbesserung, aber manchmal führt eine Drehung von drei oder mehr Kacheln zu einer globalen Verbesserung, dh A <-> B
möglicherweise nicht verbessert, aber A -> B -> C -> A
1
möglicherweise.
Aus diesem Grund wähle ich, nachdem ich zwei zufällige Kacheln ausgewählt und festgestellt habe, dass sie sich nicht verbessern, eine Reihe von Kacheln aus, um zu bewerten, ob sie die dritte Kachel in einer solchen Drehung sein können. Ich untersuche nicht, ob ein Satz von vier Kacheln gewinnbringend gedreht werden kann, und so weiter. das wäre sehr bald super teuer.
Aber das braucht Zeit. Viel Zeit!
Gibt es einen besseren und schnelleren Ansatz?
Kopfgeld-Update
Ich habe verschiedene Python-Implementierungen und -Bindungen der ungarischen Methode getestet .
Das mit Abstand schnellste war das reine Python https://github.com/xtof-durr/makeSimple/blob/master/Munkres/kuhnMunkres.py
Meine Vermutung ist, dass dies ungefähr die optimale Antwort ist; Bei der Ausführung eines Testbilds waren sich alle anderen Bibliotheken über das Ergebnis einig, aber diese kuhnMunkres.py war zwar um Größenordnungen schneller, kam aber nur sehr nahe an die Punktzahl heran, auf die sich die anderen Implementierungen geeinigt hatten.
Die Geschwindigkeit ist sehr datenabhängig. Mona Lisa eilte in 13 Minuten durch kuhnMunkres.py, aber der Scarlet Chested Parakeet brauchte 16 Minuten.
Die Ergebnisse waren ähnlich wie bei zufälligen Swaps und Rotationen für den Sittich:
(kuhnMunkres.py links, zufällige Swaps rechts; Originalbild zum Vergleich )
Für das Mona Lisa-Bild, mit dem ich getestet habe, wurden die Ergebnisse jedoch merklich verbessert, und ihr klares "Lächeln" schien tatsächlich durch:
(kuhnMunkres.py links, zufällige Swaps rechts)
quelle
Antworten:
Ja, es gibt zwei bessere und schnellere Ansätze.
Anschließend können Sie Ihre Kosten anpassen, indem Sie MSE durch eine visuell genauere Entfernung ersetzen, ohne den zugrunde liegenden Algorithmus zu ändern.
quelle
Ich bin mir ziemlich sicher, dass dies ein NP-schwieriges Problem ist. Um eine „perfekte“ Lösung zu finden, müssen Sie jede Möglichkeit gründlich ausprobieren, und das ist exponentiell.
Ein Ansatz wäre, die gierige Passform zu verwenden und dann zu versuchen, sie zu verbessern. Das könnte sein, indem Sie ein schlecht platziertes Bild (eines der letzten) aufnehmen und einen anderen Platz finden, um es zu platzieren, dann dieses Bild aufnehmen und es verschieben und so weiter. Sie sind fertig, wenn Ihnen (a) die Zeit ausgeht (b) die Passform "gut genug" ist.
Wenn Sie ein probabilistisches Element einführen, kann dies zu einem simulierten Annealing- Ansatz oder einem genetischen Algorithmus führen. Vielleicht versuchen Sie nur, die Fehler gleichmäßig zu verteilen. Ich vermute, dass dies dem nahe kommt, was Sie bereits tun. Die Antwort lautet: Mit dem richtigen Algorithmus erzielen Sie möglicherweise schneller ein besseres Ergebnis, aber es gibt keine magische Abkürzung zu Nirvana.
Ja, das ähnelt dem, was Sie bereits tun. Es geht darum, eine magische Antwort zu vergessen und in zwei Algorithmen zu denken: zuerst füllen, dann optimieren.
Die Füllung könnte sein: zufällig, am besten verfügbar, zuerst am besten, gut genug, eine Art Hot Spot.
Die Optimierung kann zufällig erfolgen, das Schlimmste beheben oder (wie ich vorgeschlagen habe) einen simulierten Annealing- oder genetischen Algorithmus.
Sie benötigen eine Metrik für "Güte" und eine Menge Zeit, die Sie bereit sind, damit zu verbringen und einfach zu experimentieren. Oder jemanden finden, der es tatsächlich getan hat.
quelle
Wenn die letzten Kacheln dein Problem sind, solltest du versuchen, sie irgendwie früh zu platzieren;)
Ein Ansatz wäre, die Kachel zu betrachten, die am weitesten von den oberen x% ihrer Übereinstimmungen entfernt ist (intuitiv würde ich mit 33% gehen) und diese auf die beste Übereinstimmung zu setzen. Das ist das beste Match, das es sowieso bekommen kann.
Außerdem könnten Sie wählen, nicht die beste Übereinstimmung für die schlechteste Kachel zu verwenden, sondern diejenige, bei der der geringste Fehler im Vergleich zur besten Übereinstimmung für diesen Slot auftritt, damit Sie Ihre besten Übereinstimmungen nicht vollständig wegwerfen, um " Schadenskontrolle".
Eine andere Sache, die Sie beachten sollten, ist, dass Sie am Ende ein Bild produzieren, das von einem Auge verarbeitet werden soll. Was Sie also wirklich wollen, ist eine Kantenerkennung, um zu bestimmen, welche Positionen auf Ihrem Bild am wichtigsten sind. In ähnlicher Weise ist das, was am äußersten Rand des Bildes geschieht, für die Qualität des Effekts von geringem Wert. Überlagern Sie diese beiden Gewichte und nehmen Sie sie in Ihre Entfernungsberechnung auf. Jeder Jitter, den Sie bekommen, sollte sich daher zum Rand hin und von den Rändern weg bewegen und so viel weniger stören.
Auch wenn die Kantenerkennung aktiviert ist, möchten Sie möglicherweise das erste y% gierig platzieren (möglicherweise bis Sie eine bestimmte Schwelle für "Kanten" in den Kacheln links unterschreiten), damit die "Hot Spots" wirklich gut behandelt werden. und wechseln Sie dann für den Rest zu "Schadenskontrolle".
quelle