Bilineare Interpolation zum Vergrößern von Bitmap-Bildern

7

Ich bin Student und habe die Aufgabe, die bilineare Interpolation von Bildern durch Aufruf von CUDA-Parallelismus zu optimieren.

Das Bild wird als 24-Bit-BMP-Format angegeben. Ich habe bereits einen Leser für die .bmp und habe die Pixel in einem Array gespeichert.

Jetzt muss ich eine bilineare Interpolation für das Array durchführen. Ich verstehe die Mathematik dahinter nicht (auch nicht nach dem Wiki-Artikel und anderen Google-Ergebnissen). Aus diesem Grund kann ich keinen Algorithmus finden.

Gibt es jemanden, der mir mit einer Verbindung zu einem bestehenden bilinearen Interpolationsalgorithmus auf einem 1-D-Array helfen kann? Oder verlinken Sie vielleicht zu einer Open-Source-Bildverarbeitungsbibliothek, die bilineare und bikubische Interpolation zum Skalieren von Bildern verwendet?

    
f0rfun 10.01.2012, 19:06
quelle

3 Antworten

37

Der einfachste Weg, die bilineare Interpolation zu verstehen, ist das Verständnis der linearen Interpolation in 1D.

Diese erste Zahl sollte Rückblenden zu Mittelschulmathematik geben. An einem Ort, an dem wir f (a) wissen wollen, nehmen wir die benachbarten "bekannten" Werte und passen eine Linie zwischen ihnen an.

Wir haben also einfach die alten Gleichungen der Mittelschule verwendet: y = mx + b und y-y1 = m (x-x1). Nichts Besonderes.

Wir übertragen dieses Konzept grundsätzlich auf 2D, um eine bilineare Interpolation zu erhalten. Wir können das Problem angehen, f (a, b) für jedes a, b zu finden, indem wir drei Interpolationen durchführen. Studieren Sie die nächste Figur sorgfältig. Lassen Sie sich nicht von allen Etiketten einschüchtern. Es ist eigentlich ziemlich einfach.

Bei einer bilinearen Interpolation verwenden wir wieder die benachbarten Punkte. Jetzt sind es vier, da wir in 2D sind. Der Trick besteht darin, das Problem in einer Dimension anzugehen.

Wir projizieren unser (a, b) auf die Seiten und berechnen zuerst zwei (eindimensionale!) interpolierende Linien.

  • f (a, y ) wobei y konstant gehalten wird
  • f (a, y j + 1) wobei y j + 1 konstant gehalten wird.

Jetzt gibt es nur noch einen letzten Schritt. Du nimmst die zwei Punkte, die du berechnet hast, f (a, y j ) und f (a, y 1 <) / i>, und passen Sie eine Linie zwischen ihnen. Das ist der blaue, der in dem Diagramm von links nach rechts geht und durch f (a, b) geht. Die Interpolation entlang dieser letzten Zeile gibt Ihnen die endgültige Antwort.

Ich lasse die Mathematik für den 2D-Fall für Sie. Es ist nicht schwer, wenn Sie aus dem Diagramm arbeiten. Und wenn du selbst durchgehst, wirst du lernen, was vor sich geht.

Eine letzte kleine Notiz, es spielt keine Rolle, welche Seite Sie für die ersten beiden Interpolationen auswählen. Sie hätten oben und unten auswählen können, und dann die dritte Interpolationslinie zwischen diesen beiden gemacht. Die Antwort wäre die gleiche gewesen.

    
nsanders 10.01.2012, 20:15
quelle
9

Wenn Sie ein Bild vergrößern, indem Sie die Seiten um einen ganzzahligen Faktor skalieren, können Sie das Ergebnis als Originalbild betrachten, wobei zusätzliche Pixel zwischen den ursprünglichen Pixeln eingefügt werden.

Sehen Sie sich die Bilder in IMAGE RESIZE EXAMPLE an.

Die f(x,y)=... Formel in diesem Artikel in Wikipedia gibt Ihnen eine Methode, um die Farbe f von an zu berechnen eingefügtes Pixel:

Für jedes eingefügte Pixel kombinieren Sie die Farben der 4 ursprünglichen Pixel (Q11, Q12, Q21, Q22), die es umgeben. Die Kombination hängt vom Abstand zwischen dem eingefügten Pixel und den umgebenden Originalpixeln ab. Je näher es an einem von ihnen ist, desto näher sind die Farben:

Die ursprünglichen Pixel werden rot angezeigt. Das eingefügte Pixel wird grün dargestellt.

Das ist die Idee.

Wenn Sie die Seiten mit einem nicht ganzzahligen Faktor skalieren, bleiben die Formeln erhalten, aber jetzt müssen Sie alle Pixelfarben neu berechnen, da Sie nicht einfach die ursprünglichen Pixel verwenden und einfach zusätzliche Pixel dazwischen einfügen können.

>     
Alexey Frunze 10.01.2012 19:45
quelle
3

Lassen Sie sich nicht davon abhalten, dass 2D-Arrays in C wirklich 1D-Arrays sind. Es ist ein Implementierungsdetail. Mathematisch müssen Sie immer noch in 2D-Arrays denken.

Denken Sie über lineare Interpolation auf einem 1D-Array nach. Du kennst den Wert bei 0, 1, 2, 3, ... Nun nehme ich an, dass ich dich nach dem Wert bei 1.4 frage. Sie würden mir eine gewichtete Mischung der Werte bei 1 und 2 : (1 - 0.4)*A[1] + 0.4*A[2] geben. Einfach, oder?

Jetzt müssen Sie auf 2D erweitern. Kein Problem. Die 2D-Interpolation kann in zwei 1D-Interpolationen in der x-Achse und dann in der y-Achse zerlegt werden. Angenommen, Sie möchten (1.4, 2.8) . Holen Sie sich die 1D Interpolanten zwischen (1, 2)<->(2,2) und (1,3)<->(2,3) . Das ist dein x-Achsenschritt. Jetzt interpolieren 1D zwischen ihnen mit den entsprechenden Gewichten für y = 2.8 .

Dies sollte einfach massiv parallelisiert werden. Berechne einfach jedes interpolierte Pixel separat. Mit dem Shared Memory-Zugriff auf das Originalbild werden nur Lesevorgänge ausgeführt, sodass keine Synchronisierungsprobleme auftreten.

    
japreiss 10.01.2012 19:49
quelle