Seite 1 von 1

FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 18:22
von barisoezcan
Guten Abend,

ich habe da ein Problem Bilder (vom Format FITS/FIT) zu drehen.
Leider kann man das bei FITS Bilder nicht wie JPEG Bilder per rotate()-Methode (oder ähnlichem)..
Deshalb versuche ich die Bilder selber pixelweise zu "drehen".

Code: Alles auswählen

import pyfits

#Ausgangsbild
altBild = pyfits.open('Testbilder\Testbild.fits')
altpix = altBild[0].data

#Ausgangsbild das gedreht werden soll
neuBild = pyfits.open('Testbilder\Testbild.fits')
neupix = neuBild[0].data

#Zu rotierender Winkel
w = 0.5

#Pixelweise drehen
for i in range(255):
    for j in range(255):

        x = round(i * math.cos(w) - j * math.sin(w))
        y = round(i * math.sin(w) + j * math.cos(w))

        if(x < 255 and y < 255):
            neupix[j][i] = altpix[y][x]
Mein Hauptproblem ist nur, dass das Bild an der unteren linken Ecke gedreht wird, und nicht in der Mitte, wie ich es gerne hätte.
Ich hab's schon versucht, indem ich ein wenig an den Indizes spiele, aber hab' es nicht hinbekommen.
Kann mir da einer helfen?

Re: FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 18:28
von EyDu
Hallo.

Im Prinzip ist es ganz einfach: du verschiebst das Bild so, dass der gewünschte Rotationspunkt p auf (0, 0) liegt. Dann rotierst du das Bild und anschließend verschiebst du das Bild wieder um -p zurück. Das machst du jetzt natürlich nicht wirklich, sondern stellst einfach die dazugehörige Gleichung auf.

Edit: Warum range(254), der spätere Test aber auf 255? Das Erstellen des Zielbildes geht sicher auch ohne erneutes Lesen der Datei.

Re: FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 19:44
von barisoezcan
Hatte mich vertan. :)
Und ich weiss (noch nicht) wie ich ein neues FITS-Bild erzeuge, da wollte ich es erstmal mit einer schnellen, unsauberen Lösung testen.
Ich versuche deinen Lösungsvorschlag nachher mal, danke.

Re: FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 20:22
von Sirius3
Hallo barisoezcan,
wenn Du versuchst, auf Deine Art und Weise Bilder zu drehen wird es sicher Löcher geben, weil eben ein gedrehtes Raster nicht mehr exakt auf das ursprüngliche Raster passt. Außerdem wird es negative Indizes geben, so dass Du wieder von rechts in das Bild hineinläufst.
Versuch doch die Daten in ein numpy-Array zu konvertieren und mit scipy.ndimage.rotate zu rotieren.

Re: FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 20:27
von BlackJack
Ich glaube da muss man nicht viel versuchen, denn `pyfits` hat `numpy` als Abhängigkeit. Würde mich sehr wundern wenn die Daten nicht schon als `numpy`-Array zurückgegeben werden.

Re: FITS-Bilder rotieren

Verfasst: Dienstag 9. April 2013, 20:31
von EyDu
@Sirius: Es gibt keine Löcher, er iteriert über die Zielpixel. Hier bietet sich vielleicht noch eine Interpolation an, hängt natürlich von den Daten ab. An den Ecken wird es allerdings Probleme geben, da dort die Pixel nicht gesetzt werden, wenn im Quellbild kein Pixel gefunden wurde.

Re: FITS-Bilder rotieren

Verfasst: Samstag 4. Mai 2013, 01:08
von barisoezcan
Hallo,
wenn ich ein 255x255 großes Bild mit der "scipy.ndimage.filters.median_filter()"-Methode filtern möchte, bekomme ich einen "MemoryError".
Meine Vermutung: Das Bild ist wahrscheinlich zu groß dafür.
Bei Bildern bis zu der Größe von ca. 130x130 funktioniert es noch.
Gibt es eine elegante Möglichkeit so ein größeres Bild median-zufiltern?
Mir fällt nur die Möglichkeit ein, das Array mit den Bildpunktdaten zweimal (ggf. mehrfach) zu teilen und dann auf jedes dieser Teile den Filter anzuwenden.

Re: FITS-Bilder rotieren

Verfasst: Samstag 4. Mai 2013, 09:59
von BlackJack
@barisoezcan: Selbst wenn die 255×255 Pixel als RGB-Werte mit 96-Bit Gleitkommazahlen gespeichert wären, bräuchte so ein Bild nur cirka 2 MiB Speicher. Das hier läuft problemlos durch und der gesamte Prozess belegt bei mir maximal 60 MiB:

Code: Alles auswählen

#!/usr/bin/env python
from numpy.random import random
from scipy.ndimage.filters import median_filter

def main():
    image = random((3, 255, 255))
    filtered_image = median_filter(image, size=10)


if __name__ == '__main__':
    main()

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 10:56
von barisoezcan
Ich hatte als zweiten Parameter bei median_filter die Größe des Bildes angegeben (255, 255).
Das war wohl falsch.
Wofür aber ist der "size"-Parameter sonst?
"size gives the shape that is taken from the input array, at every element position, to define the input to the filter function." sagt mir jetzt nicht wirklich was...
Möglicherweise die Größe der Filtermatrix? Aber die Größe müsste dann 2x2, 3x3, 4x4, usw. sein...

P.S.: Mit size=10 funktioniert es. Je nachdem ob size kleiner oder größer ist, scheint das Bild mehr oder weniger stark gefiltert zu werden.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 11:06
von BlackJack
@barisoezcan: Du wendest einen Filter an, ohne zu wissen was der eigentlich macht? Für jedes Pixel wird ein neuer Wert berechnet, nämlich der Median aller Pixel im `size` grossen Rechteck bei dem das Pixel im Mittelpunkt liegt.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 11:25
von barisoezcan
Doch, ich weiss schon was der macht, aber nicht genau was "size" beschreibt.
Das Rechteck ist also ein Quadrat mit der Seitenlänge von "size"?
Wenn ja, dann muss die Seitenlänge des Quadrats doch eine ungerade Zahl sein, damit der Pixel in der Mitte auch wirklich in der Mitte liegen kann.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 11:30
von BlackJack
@barisoezcan: Das und was mit Pixeln am Rand passiert, ist sicher irgendwo dokumentiert.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 17:35
von barisoezcan
Wenn ich z.B. dieses Bild automatisch drehen möchte, so dass die dicke "Linie" waagerecht ist, wie muss ich dann vorgehen?
Bild

Mein Ansatz:
1.Durch das Bild laufen und die Koordinaten des linkesten und des rechtesten weissen Pixels abspeichern.
2.Mit diesen beiden Koordinaten die "Steigung" der Figur berechnen.
3.Aus der "Steigung" den Winkel berechnen.
4.Das Bild um diesen Winkel mit der rotate()-Methode drehen.

Am 2.Punkt hakt es leider, weil ich keine Formel dafür aufstellen konnte, mit der man aus beiden Koordinaten die Steigung berechnet.
Habe es mit

Code: Alles auswählen

steigung = (k2[0]/k2[1]) / (k1[0]/k1[1]) #zB fuer k2 = 160,155 und k1 = 10,15
und ähnlichem versucht.

PS: Mir ist klar, dass die Linie nach einmaligem Ausführen von diesem Algorithmus nicht genau waagerecht sein wird, aber nach 3-4 maligem Durchlaufen müsste es relativ genau sein.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 5. Mai 2013, 18:19
von EyDu
Hallo.

Das Stichwort lautet Hauptkomponentenanalyse. Das musst du auch nicht selber implementieren, matplotlib hat da schon etwas Fertiges. Ansonsten ist es eine ganze nette Übung, die Mathematik dahinter ist nicht sonderlich schwer. Damit bekommst du dann auch die optimale Rotation.

Edit: Um noch auf deine Frage einzugehen: Die Drehung kannst du mittels atan2 bestimmen. Wenn du zwei Punkte (x1, y1) und (x2, y2) hast, dann ist der Winkel atan2(y2-y1, x2-x1). Dabei "rotiert" der zweite Punkt um den ersten.

Re: FITS-Bilder rotieren

Verfasst: Mittwoch 8. Mai 2013, 17:44
von barisoezcan
EyDu hat geschrieben:Hallo.

Das Stichwort lautet Hauptkomponentenanalyse. Das musst du auch nicht selber implementieren, matplotlib hat da schon etwas Fertiges. Ansonsten ist es eine ganze nette Übung, die Mathematik dahinter ist nicht sonderlich schwer. Damit bekommst du dann auch die optimale Rotation.

Edit: Um noch auf deine Frage einzugehen: Die Drehung kannst du mittels atan2 bestimmen. Wenn du zwei Punkte (x1, y1) und (x2, y2) hast, dann ist der Winkel atan2(y2-y1, x2-x1). Dabei "rotiert" der zweite Punkt um den ersten.
Hab mir das nun ein wenig durchgelesen, aber da mir das vollkommen neu ist, komme ich nicht wirklich weiter.
Beim Erzeugen des Objektes übergibt man der Klasse PCA das gesamte numpy-Array mit den Bildpunktdaten, oder?
Und inwiefern hilft mir das die passende Rotation für mein Bild zu finden?

Re: FITS-Bilder rotieren

Verfasst: Mittwoch 8. Mai 2013, 19:17
von EyDu
Ja, du steckst das Bild (binarisiert oder in Graustufen, das hängt von deinem Problem ab) in den PCA, bekommst zwei Haupkomponenten, nimmst die Hauptkomponente mit dem größten Eigenwert und drehst dann nur noch. Um welchen Winkel du rotieren musst, sollte nach dem Wikipedia-Artikel (durch pures anschauen der Bilder) doch offensichtlich sein.

Re: FITS-Bilder rotieren

Verfasst: Donnerstag 9. Mai 2013, 23:14
von barisoezcan
EyDu hat geschrieben:Ja, du steckst das Bild (binarisiert oder in Graustufen, das hängt von deinem Problem ab) in den PCA, bekommst zwei Haupkomponenten, nimmst die Hauptkomponente mit dem größten Eigenwert und drehst dann nur noch. Um welchen Winkel du rotieren musst, sollte nach dem Wikipedia-Artikel (durch pures anschauen der Bilder) doch offensichtlich sein.
Bild
Wenn ich dieses binarisierte, median-gefilterte Bild dem PCA übergebe mittels:

Code: Alles auswählen

result = PCA(pix)
erhalte ich die Fehlermeldung:
numpy.linalg.linalg.LinAlgError: SVD did not converge

Wenn ich aber das gleiche Bild unbinarisiert und ungefiltert (unteres Bild) dem PCA übergebe, funktioniert es.
Bild

Was genau habe ich unter dieser Fehlermeldung "SVD konvergierte nicht" zu verstehen?

Ich habe es einige Male mit verschieden starker Binarisierung und Filterung getestet und erst wenn das Bild weniger "Rauschen" enthält, bekomme ich diese Fehlermeldung.
Für mich ist es wichtig, so wenig wie möglich Störung im Bild zu haben, deshalb ist also eine Binarisierung und Filterung notwendig.

Re: FITS-Bilder rotieren

Verfasst: Samstag 18. Mai 2013, 11:41
von barisoezcan
Hat niemand eine Idee? :/

Re: FITS-Bilder rotieren

Verfasst: Samstag 18. Mai 2013, 11:54
von EyDu
Hallo.

Ich tippe mal auf NaNs oder INFs in den binarisierten Bildern, das verursacht ganz gerne Probleme.

Re: FITS-Bilder rotieren

Verfasst: Sonntag 19. Mai 2013, 11:02
von barisoezcan
Habe das gesamte Bild nach der Bildvorverarbeitung (Binarisierung & Filterung) auf NaN und INF überprüft. Es gibt keine.