cos, sin, atan2 und exp

  • Hallo!

    Ich hab grad den Fischaugeneffekt für ein Bild programmiert und hab ein Problem mit der Geschwindigkeit. Ich brauche für die Berechnung für einen Großteil der Pixel im Bild die Funktionen: cosinus, sinus, arcus tangens und exp. Das Problem an der Geschichte ist, dass genau diese Funktionen die Berechnung so extrem verlangsamen, dass ich mir überlegt hab, die Funktionen durch eigene Approximationen zu ersetzen. Bevor ich aber die Funktionen schreibe, wollte ich fragen, ob jemand weiß, obs solche Funktionen schon gibt? Im moment läufts noch unter C++, aber im Endeffekt brauch ichs dann in Java. Oder vielleicht gibts da eine andere Abhilfe?

    mfg

    640K ought to be enough for anybody. :eek2:

  • Ich hab vergessen, es war auch die Wurzel dabei.

    Ich hab jetzt sqrt, cos, sin und exp durch eigene Approximationen ersetzt und das Programm braucht nur noch ein fünftel der Zeit mit den normalen Funktionen! Dabei sind die Approximationen teilweise so genau, dass es überhaupt nicht bemerkbar ist. Mich würde noch interessieren, ob nur ich das Problem mit diesen Funktionen hab.

    640K ought to be enough for anybody. :eek2:

  • Für Wurzel hab ich das Newtonsche Näherungsverfahren genommen.
    Für Sinus: sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9!
    Für Cosinus: Sinus(PI/2 - x)
    Für Exponential: 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120 + x^6/720

    Für den Arcustangens hab ich noch nix richtiges..

    Für die Wurzel hab ich als Startwert einfach eine Tabelle genommen:

    Code
    [size=10][size=10][size=10][/SIZE][size=10][COLOR=#0000ff]if[/COLOR][/SIZE][size=10](x > 100000) a_1 = 500;
    [/SIZE][size=10][COLOR=#0000ff]else[/COLOR][/SIZE][size=10] [/SIZE][size=10][COLOR=#0000ff]if[/COLOR][/SIZE][size=10](x > 10000) a_1 = 100;
    [/SIZE][size=10][COLOR=#0000ff]else[/COLOR][/SIZE][size=10] [/SIZE][size=10][COLOR=#0000ff]if[/COLOR][/SIZE][size=10](x > 1000) a_1 = 50;
    [/SIZE][size=10][COLOR=#0000ff]else[/COLOR][/SIZE][size=10] [/SIZE][size=10][COLOR=#0000ff]if[/COLOR][/SIZE][size=10](x > 100) a_1 = 10;
    [/SIZE][size=10][COLOR=#0000ff]else[/COLOR][/SIZE][size=10] [/SIZE][size=10][COLOR=#0000ff]if[/COLOR][/SIZE][size=10](x > 10) a_1 = 5;[/SIZE]
    [size=10]

    [/SIZE]

    Ist zwar schirch, aber schnell und für meine Anwendung komm ich dann wirklich super hin mit nur !!!4!!! Iterationen.

    mfg
    [/SIZE][/SIZE]

    640K ought to be enough for anybody. :eek2:

  • Ja so hab ichs, aber es kommt was falsches raus.. naja es stimmt nicht mit der Funktion atan2(a, b) überein.

    atan2(a, b) = Arcustangens(a/b)

    Das sollte das gleiche sein, ist es aber nicht..

    640K ought to be enough for anybody. :eek2:

  • Im moment läufts noch unter C++, aber im Endeffekt brauch ichs dann in Java.


    Faszinierend. Rapid Prototyping mit C++? :)
    Wenn das C++-Programm nur zum Wegwerfen ist, dann ist Optimierung für die Katz...

    Ja so hab ichs, aber es kommt was falsches raus.. naja es stimmt nicht mit der Funktion atan2(a, b) überein.

    atan2(a, b) = Arcustangens(a/b)

    Das sollte das gleiche sein, ist es aber nicht..


    Die Taylorreihe konvergiert nur für |x| <= 1, aber es gilt arctan 1/x = pi/2 - arctan x. Hilft das?

    *plantsch*

  • Faszinierend. Rapid Prototyping mit C++? :)
    Wenn das C++-Programm nur zum Wegwerfen ist, dann ist Optimierung für die Katz...


    Die Taylorreihe konvergiert nur für |x| <= 1, aber es gilt arctan 1/x = pi/2 - arctan x. Hilft das?



    Ich machs deswegen in C++, weil ich mir da schon seit sehr langer Zeit eine ImageProcessing Klasse programmiert hab, die mittlerweile ziemlich groß ist und für Testzwecke sehr praktisch. Was meinst du mit "Wenn das C++-Programm nur zum Wegwerfen ist, dann ist Optimierung für die Katz..."?

    640K ought to be enough for anybody. :eek2:

  • Hmm... nicht, dass ich Ahnung hätte von deinem genauen Beispiel und so, aber:
    wenn du die Werte nur so ca. brauchst, was hältst du davon Tabellen für sin und so zu machen? Also sin(3) => sin_arr[3] in der Art? Über Schönheit lässt sich streiten, aber sollte wohl recht flott sein...

  • Ich hab mal sowas gemacht, und auch ne Tabelle verwendet. Wenn das Fischauge längere Zeit gleich groß ist, brauchst nichtmal eine Sinus-Tabelle, sondern kannst gleich eine Pixel-Matrix nehmen.
    Die ist dann so groß, wie das Quadrat, in dem der Effekt angewandt wird, und in jeder Zelle steht die Abweichung drin. d.h. du hast z.B. an der Position [5,6] die Werte [2,-1], und addierst einfach die Position, an der der Effekt startet zum Zellenindex und der Abweichung, und hast die Position im unverzerrten Bild, wo du deinen Farbwert holen kannst. (Wenn dus interpolieren willst, nimmst natürlich floats für den inhalt).

    Auf nem Celeron 1300 war eine Delphi-Implementation mit 200x200 Pixel Effekt und Interpolation flüssig.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Ich hab mal meine Implementation auf einem Pentium 3 1300 getestet mit einem Bild von 800*600 Pixel und es braucht ca 100 ms. Wenn ich ein Bild mit 320*240 nehm, dauerts ca. 50 ms. Auf einem P4 2,66 GHz nur 10 ms. Ich glaub die Matrix brauch ich nicht, obwohls eine gute Idee ist. Danke für die Hilfe!

    640K ought to be enough for anybody. :eek2:

  • Wie war das überhaupt gedacht? Einfach nur auf ein Bild ein Fischauge draufrendern, und das wars? Dann hat die Matrix natürlich keinen Sinn, weil das Berechnen derselben so lang dauert, wie die Berechnung des Effekts.

    Die Matrix zahlt sich natürlich erst bei mehrmaliger Anwendung aus. Also wenn man als User mit der Maus das Fischauge bewegen können soll, oda so. Aber du wirst scho wissen, was du tust.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Nein, es wird auf ein Video angewandt und der Benutzer soll den Wölbungsgrad verändern können. Aber wenn ichs mir so recht überleg, ist die extra Matrix eine Super Idee. Auch wenn der Benutzer die Wölbung ändern kann, kann man ja die gleiche Matrix verwenden, solange der Wölbungsgrad gleich ist und nur für einen neuen Wölbungsgrad wieder berechnen. Das spart sicher Sauviel Zeit. Danke@Wolfi!

    Wegen dem arctan hab ich noch immer keine Lösung...

    640K ought to be enough for anybody. :eek2:

  • Ich würds vorberechnen, man muss sich ja nicht auf Grad beschränken. Wenn die Tabelle 100000 Einträge hat, wirds schon sehr genau, und die 400000 (oder 800000) Byte Speicher kratzen einen heutzutage doch kaum noch. Rechenzeit sparen ist grad bei Videos sicher gscheiter.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Was meinst du mit "Wenn das C++-Programm nur zum Wegwerfen ist, dann ist Optimierung für die Katz..."?


    Du hast "im Endeffekt brauch ichs dann in Java" geschrieben. Wenn dein Endprodukt ein Java-Programm ist, hat es wenig Sinn, ein C++-Programm zu optimieren :)

    Was den arctan betrifft, wenn du etwas mehr Infos posten würdest, mit was für Werten du ihn aufrufst, was rauskommt und was rauskommen sollte, und vielleicht sogar den Code deiner arctan-Funktion, dann könnte man dir sicher besser helfen. "Funktoniert nicht" enthält gerade mal ein Bit an Information, das ist zuwenig, um Code zu debuggen.

    *plantsch*

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!