Numerische Stabilität von Zernike-Polynomen höherer Ordnung


9

Ich versuche m=0, n=46Zernike-Momente höherer Ordnung (z. B. ) für ein Bild zu berechnen . Ich habe jedoch ein Problem mit dem radialen Polynom (siehe Wikipedia ). Dies ist ein Polynom, das im Intervall [0 1] definiert ist. Siehe den MATLAB-Code unten

function R = radial_polynomial(m,n,RHO)
    R = 0;
    for k = 0:((n-m)/2)        
        R = R + (-1).^k.*factorial(n-k) ...
            ./ ( factorial(k).*factorial((n+m)./2-k) .* factorial((n-m)./2-k) ) ...
            .*RHO.^(n-2.*k);
    end
end

Dies stößt jedoch offensichtlich auf numerische Probleme in der Nähe RHO > 0.9. Ein Polynom mit viel Rauschen

Ich habe versucht, es so umzugestalten, dass ich polyvaldachte, es könnte einige bessere Algorithmen hinter den Kulissen geben, aber das hat nichts gelöst. Die Konvertierung in eine symbolische Berechnung hat zwar das gewünschte Diagramm erstellt, war jedoch selbst für ein einfaches Diagramm wie das gezeigte erstaunlich langsam.

Gibt es eine numerisch stabile Methode zur Bewertung solcher Polynome höherer Ordnung?


3
Oft ist es besser, orthogonale Polynome zu verwenden, hier Jacobi-Polynome . Haben Sie versucht, mathworks.com/help/symbolic/jacobip.html und die Beziehung
Rnm(r)=(1)(nm)/2rmP(nm)/2(m,0)(12r2)?
Gammatester

@gammatester Das funktioniert! Könnten Sie vielleicht eine Antwort darauf geben, warum dies der Fall ist?
Sanchises

Schön zu hören, dass es funktioniert. Leider kann ich aus zwei Gründen keine entschiedene Antwort geben. Erstens: Obwohl allgemein bekannt ist, dass orthogonale Polynome bessere Stabilitätseigenschaften als die Standardform haben, kenne ich keinen formalen Beweis (insbesondere in diesem Fall). Zweitens verwende ich kein Matlab und kann keine Daten für die implementierten Jacobi-Polynome angeben.
Gammatester

1
@Sanchises Hier gibt es kein kostenloses Mittagessen: Nur weil etwas ein Polynom ist, heißt das nicht, dass die direkte Potenzformel der richtige Weg ist, es zu berechnen, und die genaue Berechnung von Jacobi-Polynomen ist selbst keine triviale Angelegenheit - das tun Sie nicht es durch die Koeffizienten, also ist es nicht so billig.
Kirill

2
Der Grund für die Verwendung von Jacobi-Polynomen ist, dass Sie die katastrophale Aufhebung in Ihrer Formel beseitigen (sehen Sie sich all diese oszillierenden Faktoren mit sehr großen Koeffizienten an!) Und das standardmäßige Jacobi-Polynom-Bewertungsverfahren sorgfältig in einer Bibliothek implementiert ist, so dass dies garantiert ist um genau zu sein. Der größte Teil der Arbeit hier wird geleistet, um sicherzustellen, dass die Jacobi-Polynome genau ausgewertet werden.
Kirill

Antworten:


7

R.nm(ρ)=ρ(R.n- -1|m- -1|(ρ)+R.n- -1m+1(ρ))- -R.n- -2m(ρ)

Dies ist im folgenden Octave-Skript implementiert:

clear                                     % Tested with Octave instead of Matlab
N = 120;
n_r = 1000;
R = cell(N+1,N+1);
rho = [0:n_r]/n_r;
rho_x_2 = 2*[0:n_r]/n_r;

R{0+1,0+1} = ones(1,n_r+1);               % R^0_0  Unfortunately zero based cell indexing is not possible
R{1+1,1+1} = R{0+1,0+1}.*rho;             % R^1_1  ==>  R{...+1,...+1} etc.
for n = 2:N,
    if bitget(n,1) == 0,                  % n is even
        R{0+1,n+1} = -R{0+1,n-2+1}+rho_x_2.*R{1+1,n-1+1};                % R^0_n
        m_lo = 2;
        m_hi = n-2;
    else
        m_lo = 1;
        m_hi = n-1;
    end
    for m = m_lo:2:m_hi,
        R{m+1,n+1} = rho.*(R{m-1+1,n-1+1}+R{m+1+1,n-1+1})-R{m+1,n-2+1};  % R^m_n
    end
    R{n+1,n+1} = rho.*R{n-1+1,n-1+1};                                    % R^n_n
end;


Z = @(m,n,rho) (-1)^((n-m)/2) * rho.^m .* jacobiPD((n-m)/2,m,0,1-2*rho.^2);
m = 22;
n = 112;
figure
plot(rho,Z(m,n,rho))
hold on
plot(rho,R{m+1,n+1},'r');
xlabel("rho")
ylabel("R^{22}_{112}(rho)")
legend("via Jacobi","recursive");
%print -djpg plt.jpg

m = 0;
n = 46;
max_diff_m_0_n_46 = norm(Z(m,n,rho)-R{m+1,n+1},inf)

m=22n=112ρ=0,7

Geben Sie hier die Bildbeschreibung ein

m=0n=461.4e-10


Ihre Handlung sieht aus wie ein Fehler in Matlab jacobiPD, nicht wie eine generische katastrophale Stornierung.
Kirill

JacobiPDn=30mρ6.9e-13JacobiPDfactorial(n+a) * factorial(n+b)

m=22n=1121/(factorial(s)*factorial(n+a-s)*factorial(b+s)*factorial(n-s)) * ((x-1)/2).^(n-s).*((x+1)/2).^s * factorial(n+a) * factorial(n+b)1.4e18-2.1

1
@wim Ich habe nicht bemerkt, dass es nicht Matlab ist. Wenn jemandes Jacobi-Polynom-Implementierung für seinen Zweck gut genug ist, ist das kein Problem. Ich habe nur gesagt, dass es ein Fehler ist, weil ich es falsch verstanden habe und dachte, es sei eine eingebaute Funktion (ich erwarte, dass die Bibliotheksfunktionen sehr solide sind). Mit "generisch" meinte ich, wenn Sie nicht wissen, wie die Funktion implementiert ist, können Sie falsche Ausgaben nicht als "katastrophale Löschung" bezeichnen, wie ein Sammelbegriff für alle Arten von Fehlern, aber das war nur mein Missverständnis dessen, was Der Code tat es.
Kirill

1
Um es klar zu sagen: Mein Code ist nicht rekursiv. Es ist die iterative Standard-Drei-Term-Wiederholungsrelation (ähnlich wie bei Chebyshev-Polynomen), die normalerweise stabiler sein soll als z. B. die Horner-Form für Polynome.
Gammatester

8

Eine mögliche Lösung (von @gammatester vorgeschlagen) ist die Verwendung von Jacobi-Polynomen. Dies umgeht das Problem der katastrophalen Aufhebung beim Addieren der großen Polynomkoeffizienten durch "naive" Polynombewertung.

Das radiale Zernike-Polynom kann durch Jacobi-Polynome wie folgt ausgedrückt werden (siehe Gleichung (6) )

R.nm(ρ)=(- -1)(n- -m)/.2ρmP.(n- -m)/.2(m,0)(1- -2ρ2)

In MATLAB ist die Verwendung von jacobiP(n,a,b,x)jedoch für große Vektoren / Matrizen von unannehmbar langsam x=rho. Die jacobiPFunktion ist tatsächlich Teil der Symbolic Toolbox, und die Auswertung des Polynoms wird auf die symbolische Engine verschoben, die Geschwindigkeit gegen willkürliche Präzision eintauscht. Eine manuelle Implementierung der Jacobi-Polynome ist daher erforderlich.

α=mβ=0n=(n- -m/.2)s

P.n(α,β)(ρ)=(n+α)!(n+β)!s=0n[1s!(n+α- -s)!(β+s)!(n- -s)!(x- -12)n- -s(x+12)s]]

In MATLAB bedeutet dies (Jacobi p olice d epartment P olynomial, ' D ouble' Implementierung)

function P = jacobiPD(n,a,b,x)
    P = 0;
    for  s  0:n
        P = P + ...
            1/(factorial(s)*factorial(n+a-s)*factorial(b+s)*factorial(n-s)) * ...
            ((x-1)/2).^(n-s).*((x+1)/2).^s;
    end
    P = P*factorial(n+a) * factorial(n+b);
end

Das tatsächliche radiale Zernike-Polynom ist also (für m=abs(m))

Z = @(m,n,rho) (-1)^((n-m)/2) * rho.^m .* jacobiPD((n-m)/2,m,0,1-2*rho.^2);

Hinweis: Diese Selbstantwort ist nur eine praktische Lösung. Fühlen Sie sich frei, eine andere Antwort zu markieren, die erklärt, warum dies funktioniert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.