高阶Zernike多项式的数值稳定性


9

我正在尝试为某些图像计算更高阶(例如m=0n=46)的Zernike矩。但是,我遇到了一个关于径向多项式的问题(请参阅Wikipedia)。这是在间隔[0 1]上定义的多项式。请参阅下面的MATLAB代码

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

但是,这显然会遇到的数值问题RHO > 0.9有很多噪声的多项式

我试着将其重构,polyval以为它可能具有一些更好的幕后算法,但这并没有解决任何问题。将其转换为符号计算确实可以创建所需的图形,但即使对于如图所示的简单图形,其速度也令人难以置信。

有没有一种数值稳定的方法来评估这种高阶多项式?


3
通常最好使用正交多项式,这里是Jacobi多项式。您是否尝试过mathworks.com/help/symbolic/jacobip.html 及其关系
[Rñ[R=-1个ñ-/2[RPñ-/201个-2[R2
gammatester,

@gammatester可行!您能否详细解释为什么会这样?
桑奇塞斯18/12/13

很高兴听到它起作用。不幸的是,由于两个原因,我无法给出明确的答案。首先:尽管众所周知,正交多项式具有比标准形式更好的稳定性,但我不知道形式证明(尤其是在这种情况下)。其次,我不使用Matlab,也无法给出实现的Jacobi多项式的数据。
gammatester

1
@Sanchises这里没有免费的午餐:仅仅因为多项式多项式并不意味着以幂为单位的直接公式是计算它的正确方法,而准确地计算Jacobi多项式本身并不是一件容易的事-您不会做通过系数,所以它并不便宜。
基里尔

2
使用Jacobi多项式的原因是您摆脱了公式中的灾难性抵消(请查看所有系数非常大的振荡因子!),并且默认的Jacobi多项式求值过程在库中已仔细实现,因此可以保证准确地说。这里的大部分工作都是为了确保对Jacobi多项式进行精确评估。
基里尔

Answers:


7

本文中,Honarvar和Paramesran提出了一种有趣的方法,以一种非常不错的递归方式来计算径向Zernike多项式。递归公式非常简单,无需大整数除法或乘法:

[Rñρ=ρ[Rñ-1个|-1个|ρ+[Rñ-1个+1个ρ-[Rñ-2ρ
我建议您看一下Honarvar和Paramesran论文中的图1,该图清楚地说明了不同Zernike多项式之间的相关性。

这是在以下Octave脚本中实现的:

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)

例如,此代码产生的图形显示 =22ñ=112,灾难性的取消发生在附近 ρ=0.7,如果Zernike径向多项式是通过Jacobi多项式计算的。因此,还必须担心低度Zernike多项式的准确性。

在此处输入图片说明

递归方法似乎更适合以稳定的方式计算这些高阶Zernike多项式。尽管如此,对于=0ñ=46,Jacobi和递归方法之间的最大差是(only?)1.4e-10,这对于您的应用程序可能足够准确。


您的图看起来像Matlab中的错误jacobiPD,而不像任何一般的灾难性取消一样。
基里尔

@Kiril:我JacobiPD他的回答中使用了Sanchises'。这对于低阶多项式非常有效。例如,ñ=30,任意 和任意 ρ,两种方法之间的差异小于6.9e-13。尽管的总和中的各个项JacobiPD很小,但乘以后可能会变大factorial(n+a) * factorial(n+b)。而且,它们具有交替的符号,这是灾难性抵消的完美配方。
WIM

(续)例如 =22ñ=112表达式 1/(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最终。您可以将其称为错误,但精确度无限,答案是正确的。您能否解释“没有一般性灾难性取消”的含义?
WIM

1
@wim我没有注意到这不是Matlab的。如果某人的Jacobi多项式实现足以达到他们的目的,那就没问题了。我只说这是一个错误,因为我误解了,并认为这是一个内置函数(我希望库函数非常可靠)。所谓“泛型”,是指如果您不知道函数的实现方式,就不能将错误的输出称为“灾难性取消”,就像各种错误的笼统术语一样,但这只是我对什么的误解。代码正在做。
基里尔

1
需要明确的是:我的代码不是递归的。这是迭代标准的三项递归关系(类似于Chebyshev多项式),通常比例如多项式的Horner形式更稳定。
gammatester

8

一个可能的解决方案(由@gammatester建议)是使用Jacobi多项式。这就避免了通过“朴素”多项式求和将大多项式系数相加的灾难性抵消问题。

径向Zernike多项式可以由Jacobi多项式表示如下(请参见等式(6)

[Rñρ=-1个ñ-/2ρPñ-/201个-2ρ2

但是,在MATLAB中,jacobiP(n,a,b,x)对于的大向量/矩阵,使用慢得无法接受x=rho。该jacobiP函数实际上是Symbolic Toolbox的一部分,多项式的求值被推迟到Symbolic引擎,该引擎将速度换成任意精度。因此,必须手动执行Jacobi多项式。

由于Jacobi函数的参数都是非负的(α=β=0ñ=ñ-/2),我们可以使用以下表达式(请参阅Wikipedia,请注意,我填写了s

Pñαβρ=ñ+αñ+βs=0ñ[1个sñ+α-sβ+sñ-sX-1个2ñ-sX+1个2s]

在MATLAB中,这转化为(雅可比p olice d epartment P olynomial, ' d ouble'实现)

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

实际径向Zernike多项式因此(为m=abs(m)

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

注意:此自我回答仅是一种实用的解决方案;随意标签上的另一个答案,解释为什么这个工程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.