7 Stimmen

Bilineare Interpolation - DirectX vs. GDI+

Ich habe eine C#-Anwendung, für die ich GDI+-Code geschrieben habe, der Bitmap/TextureBrush-Rendering verwendet, um 2D-Bilder darzustellen, auf die verschiedene Bildverarbeitungsfunktionen angewendet werden können. Dieser Code ist ein neuer Pfad in einer Anwendung, die bestehenden DX9-Code nachahmt, und sie teilen eine gemeinsame Bibliothek, um alle Vektor- und Matrix (z.B. ViewToWorld/WorldToView) Operationen durchzuführen. Meine Testumgebung besteht aus DX9-Ausgabebildern, die ich mit der Ausgabe des neuen GDI+-Codes vergleiche.

Ein einfacher Testfall, der in einem Ansichtsfenster gerendert wird, das mit den Bitmap-Abmessungen übereinstimmt (d. h. kein Zoom oder Schwenk) tut stimmen pixelgenau überein (kein binärer Unterschied) - aber sobald das Bild vergrößert wird, erhalte ich sehr geringe Unterschiede bei 5-10 % der Pixel. Die Größe des Unterschieds beträgt 1 (gelegentlich 2)/256. Ich vermute, dass dies auf Interpolationsunterschiede zurückzuführen ist.

Frage : Für eine DX9 Ortho-Projektion (und Identität Weltraum), mit einer Kamera senkrecht und zentriert auf einem texturierten Quad, ist es vernünftig zu erwarten DirectX.Direct3D.TextureFilter.Linear um eine identische Ausgabe wie bei einem mit GDI+ TextureBrush gefüllten Rechteck/Polygon zu erzeugen, wenn man die System.Drawing.Drawing2D.InterpolationMode.Bilinear Einstellung?

Für diesen Fall (Vergrößerung) verwendet der DX9-Code dies (MinFilter, MipFilter ähnlich eingestellt):
Device.SetSamplerState(0, SamplerStageStates.MagFilter, (int)TextureFilter.Linear);

und der GDI+-Pfad verwendet wird: g.InterpolationMode = InterpolationMode.Bilinear;

Ich dachte, dass "Bilinear Interpolation" eine ziemlich spezifische Filterdefinition war, aber dann bemerkte ich, dass es eine weitere Option in GDI+ für "HighQualityBilinear" (die ich versucht habe, ohne Unterschied - was angesichts der Beschreibung der "zusätzlichen Vorfilterung zum Schrumpfen" Sinn macht)

Folgefrage: Ist es vernünftig, eine pixelgenaue Übereinstimmung zwischen DirectX und GDI+ zu erwarten (vorausgesetzt, alle externen Koordinaten sind gleich)? Wenn nicht, warum nicht?

Klarstellung: Die Bilder, die ich verwende, sind opake Graustufen (R=G=B, A=1) mit Format32bppPArgb.

Schließlich gibt es eine Reihe von anderen APIs, die ich verwenden könnte (Direct2D, WPF, GDI, etc.) - und diese Frage gilt im Allgemeinen zum Vergleich der Ausgabe von "äquivalenten" bilinear interpolierte Ausgabe Bilder über zwei dieser. Vielen Dank!

6voto

Stephen Chung Punkte 14323

DirectX läuft hauptsächlich auf der GPU und DX9 kann Shader ausführen. GDI+ läuft auf völlig anderen Algorithmen. Ich glaube nicht, dass es vernünftig ist, zu erwarten, dass die beiden exakt pixelgleiche Ergebnisse liefern.

Ich erwarte, dass DX9 eine bessere Qualität hat als GDI+, was eine Verbesserung gegenüber dem alten GDI ist, aber nicht viel. GDI+ ist seit langem bekannt, dass es Probleme mit Anti-Aliasing-Linien und auch mit der Erhaltung der Qualität bei der Bildskalierung hat (was Ihr Problem zu sein scheint). Um etwas in ähnlicher Qualität wie die neueste Generation der GPU-Texturverarbeitung zu haben, müssen Sie zu WPF-Grafiken wechseln. Dies bietet eine ähnliche Qualität wie DX.

WPF verwendet auch den Grafikprozessor (falls verfügbar) und greift auf das Software-Rendering zurück (falls kein Grafikprozessor vorhanden ist), so dass die Ergebnisse von Grafikprozessor- und Software-Rendering relativ nahe beieinander liegen.

EDIT: Obwohl dies als Antwort ausgewählt wurde, ist es nur ein erster Erklärungsversuch und geht nicht wirklich auf den wahren Grund ein. Der Leser wird stattdessen auf die Diskussionen in den Kommentaren zur Frage und auf die Antworten verwiesen.

2voto

John Nicholas Punkte 4658

Wie kommen Sie zu der Annahme, dass sie dieselbe Formel verwenden?

Selbst wenn sie dieselbe Formel verwenden und Sie akzeptieren, dass die Umsetzung unterschiedlich ist, würden Sie erwarten, dass das Ergebnis dasselbe ist?

Letztendlich soll der Code mit der Wahrnehmung arbeiten und nicht mathematisch präzise sein. Obwohl Sie dies mit CUDA bekommen können, wenn Sie wollen.

Anstatt überrascht zu sein, dass Sie unterschiedliche Ergebnisse erhalten, wäre ich sehr erstaunt, wenn Sie perfekte Pixelübereinstimmungen erhielten.

die Art und Weise, wie sie Farben darstellen, ist unterschiedlich ... Ich weiß, für eine Tatsache nvidia verwendet ein Float (vielleicht double), um Farbe wheras GDI verwendet int ich glaube, zu vertreten.

http://en.wikipedia.org/wiki/GPGPU

In DX9 Shader 2.0 erscheint, das ist, wenn die Umsetzung der Farbe von int zu 24 und 32 Bit Floats geändert.

Versuchen Sie, das Rendering von ati/amd mit dem von nvidia zu vergleichen, und Sie können deutlich sehen, dass die Farben sehr unterschiedlich sind. Ich habe das zum ersten Mal in Quake 2 bemerkt ... der Unterschied zwischen den beiden Karten war atemberaubend - natürlich liegt das an einer Vielzahl von Dingen, von denen die bilinier interp-Implementierung die geringste ist.

EDIT: die Info, wie die Spezifikation erstellt wurde, kam erst nach meiner Antwort. Wie auch immer, ich denke, die Datentypen verwendet, um es zu speichern iwll unterschiedlich sein, egal wie Sie es angeben. Außerdem wird die Implementierung von float wahrscheinlich unterschiedlich sein. Ich kann mich irren, aber ich bin ziemlich sicher, dass c# float anders implementiert als der C-Compiler, den Nvidia verwendet. (und das setzt voraus, dass GDI+ nicht einfach den Float in den entsprechenden Int konvertiert ....)

Selbst wenn ich damit falsch liege, würde ich es für außergewöhnlich halten, zu erwarten, dass 2 verschiedene Implementierungen eines Algorithmus identisch sind. Sie sind auf Geschwindigkeit optimiert, was zur Folge hat, dass der Unterschied in der Optimierung direkt zu einem Unterschied in der Bildqualität führt, da diese Geschwindigkeit von einem anderen Ansatz zum Ausschneiden von Ecken/Annäherung herrührt.

0voto

Mark Ransom Punkte 283960

Für Rundungsdifferenzen gibt es zwei Möglichkeiten. Die erste ist offensichtlich, wenn der RGB-Wert als ein Bruchteil der Werte auf beiden Seiten berechnet wird. Die zweite ist subtiler, nämlich bei der Berechnung des Verhältnisses, das zur Bestimmung des Bruchteils zwischen den beiden Punkten verwendet wird.

Es würde mich wirklich sehr überraschen, wenn zwei verschiedene Implementierungen des Algorithmus Pixel für Pixel identisch wären, denn es gibt so viele Stellen, an denen ein Unterschied von +/- 1 auftreten kann. Ohne die genauen Implementierungsdetails beider Methoden zu kennen, ist es unmöglich, genauer zu sein als das.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X