Ich möchte beliebige Netze laden und dicke schwarze Linien entlang der Kanten zeichnen, um ein Toon-Shading-ähnliches Aussehen zu erhalten. Mit dem Schablonenpuffer konnte ich eine schwarze Silhouette um die Objekte zeichnen. Sie können das Ergebnis hier sehen:
Was jedoch fehlt, sind die schwarzen Linien im Objekt selbst. Ich dachte darüber nach, normale Diskontinuitäten zu überprüfen: Überprüfen, ob ein benachbartes Pixel einen anderen normalen Vektor als das aktuelle hat. Wenn ja, wurde eine Kante gefunden. Leider habe ich keine Ahnung, wie ich diesen Ansatz implementieren könnte, weder in OpenGL noch in GLSL Vertex / Fragment Shader.
Ich würde mich sehr über Hilfe bei diesem oder einem anderen Ansatz zur Kantenerkennung freuen.
Bearbeiten: Ich verwende keine Texturen für meine Netze.
Genauer gesagt möchte ich eine CAD / CAM-Lösung erstellen, die so gut wie möglich aussieht (entnommen aus Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):
quelle
Antworten:
Im Allgemeinen läuft die Kantenerkennung darauf hinaus, Bereiche des Bildes mit hohem Gradientenwert zu erkennen.
In unserem Fall können wir den Gradienten grob als Ableitung der Bildfunktion sehen, daher gibt Ihnen die Größe des Gradienten eine Information darüber, wie stark sich Ihr Bild lokal ändert (in Bezug auf benachbarte Pixel / Texel).
Nun, eine Kante ist, wie Sie sagen, ein Hinweis auf Diskontinuität. Nachdem wir nun den Gradienten definiert haben, ist klar, dass diese Informationen alles sind, was wir brauchen. Sobald wir den Gradienten eines Bildes gefunden haben, müssen wir nur noch einen Schwellenwert darauf anwenden, um einen Binärwert für die Kante / Nichtkante zu erhalten.
Wie findest du diesen Gradienten ist wirklich das, was du fragst und ich muss noch antworten :)
Viele Möglichkeiten! Hier ein paar :)
Eingebaute Shader-Funktionen
Sowohl hlsl als auch glsl bieten abgeleitete Funktionen. In GLSL haben Sie dFdx und dFdy , die Ihnen Gradienteninformationen in x- und y-Richtung geben. Typischerweise werden diese Funktionen in einem Block von 2x2 Fragmenten ausgewertet.
Wenn Sie nicht an einer einzelnen Richtung interessiert sind, ist ein guter Weg, um ein kompaktes Ergebnis zu erzielen , das angibt, wie stark der Gradient in der Region ist, die Breite , die Ihnen nichts anderes als die Summe der absoluten Werte von dFdy und dFdy gibt.
Es ist wahrscheinlich, dass Sie eher an einer Kante des Gesamtbilds als an einem bestimmten Kanal interessiert sind. Daher möchten Sie möglicherweise Ihre Bildfunktion in Luma umwandeln. In diesem Sinne könnte Ihr Shader bei der Kantenerkennung Folgendes enthalten:
Bei einem hohen Schwellenwert finden Sie gröbere Kanten, und bei einem niedrigen Schwellenwert können Sie möglicherweise falsche Kanten erkennen. Sie müssen experimentieren, um den Schwellenwert zu finden, der Ihren Anforderungen besser entspricht.
Der Grund, warum diese Funktionen funktionieren, ist erwähnenswert, aber ich habe jetzt keine Zeit dafür. Ich werde diese Antwort wahrscheinlich später aktualisieren :)
Nachbearbeitung des Bildschirmbereichs
Sie könnten schicker sein, jetzt ist das Feld der Kantenerkennung in der Bildverarbeitung immens. Ich könnte Ihnen Dutzende guter Möglichkeiten nennen, um die Kantenerkennung gemäß Ihren Anforderungen zu erkennen, aber lassen Sie es uns vorerst einfach halten. Wenn Sie interessiert sind, kann ich Ihnen weitere Optionen nennen!
Die Idee wäre also ähnlich wie oben, mit dem Unterschied, dass Sie sich eine größere Nachbarschaft ansehen und eine Reihe von Gewichten für umgebende Samples verwenden könnten, wenn Sie möchten. Normalerweise führen Sie eine Faltung über Ihr Bild mit einem Kernel durch, der Ihnen als Ergebnis gute Verlaufsinformationen liefert.
Eine sehr häufige Wahl ist der Sobel-Kernel
Welche geben Ihnen Gradienten in x- und y-Richtung:
Dann können Sie wie oben erwähnt einen Schwellenwert festlegen.
Wie Sie sehen können, gibt dieser Kernel dem zentralen Pixel mehr Gewicht, sodass der Gradient + ein wenig Glättung effektiv berechnet werden, was traditionell hilfreich ist (häufig ist das Bild Gaußsch verschwommen, um kleine Kanten zu beseitigen).
Das obige funktioniert ganz gut, aber wenn Sie die Glättung nicht mögen, können Sie die Prewitt-Kernel verwenden:
(Beachten Sie, dass ich in Eile bin und bald richtig formatierten Text anstelle von Bildern schreiben werde!)
Wirklich, es gibt viel mehr Kernel und Techniken, um die Kantenerkennung auf bildprozessähnliche Weise zu finden, als Echtzeitgrafiken. Daher habe ich kompliziertere (Wortspiel nicht beabsichtigte) Methoden ausgeschlossen, da Sie mit dFdx / y-Funktionen wahrscheinlich in Ordnung wären .
quelle
Nur für den Fall, dass jemand auch Kanten erkennen muss: Hier ist ein schöner Artikel zum Anzeigen eines Drahtgitters und in diesem Artikel wird erklärt, wie nur die Kanten angezeigt werden.
quelle