View License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video

Highlights from
Zernike polynomials

4.8 | 20 ratings Rate this file 76 Downloads (last 30 days) File Size: 6.84 KB File ID: #7687 Version:
image thumbnail

Zernike polynomials



18 May 2005 (Updated )

Zernike polynomials and functions (orthogonal basis on the unit circle).

| Watch this File

File Information

ZERNFUN.m and ZERNFUN2.m compute the Zernike functions Znm(r,theta). These functions, which form an orthogonal basis on the unit circle, are used in disciplines such as astronomy, optics, optometry, and ophthalmology to characterize functions and data on a circular domain. ZERNPOL.m computes the Zernike polynomials Znm(r), which are the radial portion of the Zernike functions.
A MATLAB Digest article describing the use of the Zernike functions for analyzing optics data (using a LASIK surgery data as an example) also is available, on the File Exchange as a PDF,

and in HTML at:


Showregions.M and Quadcc inspired this file.

This file inspired Zernfun2a.M, Zernike Polynomial Coefficients For A Given Wavefront Using Matrix Inversion In Matlab, Showregions.M, Quadcc, Zernike Decomposition, Zernike3, and Fast Computation Of Zernike Radial Polynomials.

MATLAB release MATLAB 7.3 (R2006b)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (30)
16 Dec 2016 Mathieu Gauvin

Dear Dr Fricker,

I really enjoyed reading your document "Analyzing LASIK Optical Data Using Zernike Functions". Amazing work!

I am trying to understand the format which your eyedata matrix should be and how to plot it. You probably use something fancier than imagesc here?
Is eye data simply a m x n image? I did save the topo from your example as a jpeg and cropped the axes to try to replicate your example, but I had trouble doing it. Is the raw data and code for your example available somewhere? Thanks!

26 Apr 2016 Tim

Tim (view profile)

Where can I find the eyedata for "Analyzing LASIK Optical Data Using Zernike Functions" Everywhere online points to it being found here. HELP!

Comment only
12 Apr 2016 Eureka Ocean

29 Feb 2016 Nicolás Casaballe

Hello. I think that the help of ZERNFUN has a typo. It states that "Each element k of M must be a positive integer, with possible values M(k) = -N(k) to +N(k)", which is a contradiction. Even in the examples after that, negative values are used. After examining the code, I have arrived to the conclusion that is merely the help that has a typo. Am I right?

On the other hand, the help for the ZERNPOL function does indeed use strictly positive values for M(k). Perhaps this is the source of the problem.

09 Apr 2014 Anael

Anael (view profile)

Well documented!

07 Jan 2014 Mathieu


Thanks for providing these files to the comunity !
However, did you check the othogonality of the functions created?
It seems to me that something's wrong there.
I generated 2 polynoms like it is shown in the doc :

z(idx) = zernfun(3,1,r(idx),theta(idx));
z2(idx) = zernfun(4,0,r(idx),theta(idx));

When I check the orthogonality by simply doing :


the result is not 0.

Am I doing someting wrong or is there a pb here?

Thanks in adavnce

Comment only
26 Mar 2013 Konstantin

12 Jun 2012 @JUAN CARDENAS
n = floor((-1+sqrt(1+8*p))/2);

Very good solution for using any p but
I think you were missing a '-'sign for your definition of m. (can be seen when plotting the Zernike-Polynomials)

Comment only

Thank you Paul.
An update for enabling any P order, in zernfun2, instead of:

n = ceil((-3+sqrt(9+8*p))/2);
m = 2*p - n.*(n+2);

change it by:

n = floor((-1+sqrt(1+8*p))/2);

14 Nov 2011 Shahab

Shahab (view profile)


Does anybody know about the discrete Zernike Transform (DZT)?
I am so eager to implement that.

thank you in advance

Comment only
14 Nov 2011 Vic

Vic (view profile)

Thanks for the code! I have a question about the unit of the zernike polynomials generated by this code, is it in [number of waves] or [micrometer]?

Thanks again!

Comment only
10 Mar 2011 Chauncey Graetzel

I was running into problems when using my fitted terms in another program: the same coefficients did not give the same surface.
I found the cause: the cosine and sine terms are inverted in zernfun. M>0 should be a cosine, while M<0 should be a sine.

I've corrected this, starting at line 193

if any(idx_pos)
z(:,idx_pos) = y(:,idx_pos).*cos(theta*m(idx_pos)');
if any(idx_neg)
z(:,idx_neg) = y(:,idx_neg).*sin(theta*-m(idx_neg)');

% note the required sign change "-m" in the sine term

Comment only
30 Aug 2010 Bob

Bob (view profile)

Very great functions! But the normalization with the 'norm' - option seems to be wrong. I've changed in:


% For the normalized polynomials the line 177:
y(:,j) = y(:,j)*sqrt((1+(m(j)~=0))*(n(j)+1)/pi);

% I have to replaced by:
if m(j)==0
y(:,j) = y(:,j)*sqrt((n(j)+1));
y(:,j) = y(:,j)*sqrt(2*(n(j)+1));

30 Mar 2010 Elia

Elia (view profile)

I am still becoming accustomed to MATLAB. When I run the zernfun.m by itself without any modifications, I get this error

??? Input argument "n" is undefined.
Error in ==> zernfun at 88
if ( ~any(size(n)==1) ) || ( ~any(size(m)==1) ).

However, when I initialized n, m, r, & theta, I get this error

??? Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N)
to change the limit. Be aware that exceeding your available stack space can
crash MATLAB and/or your computer.

Error in ==> meshgrid

Does anybody have any thoughts about making zernfun.m to work? Any help would be greatly appreciated.

Comment only
22 Jan 2010 Jeff

Jeff (view profile)

Paul, Thanks very much for this code. It is very much appreciated.

I think, however, that you have a bug in how you are normalizing your Zernike polynomials. Noll's paper shows that for terms with m=0 the normalization term should be (n+1)**0.5 and for terms with m!=0 the normalization term should be (2*(n+1))**0.5. In the routine zernpol.m you are normalizing all terms (including those with m=0) by (2*(n+1))**0.5.

Perhaps you have already fixed this? I have just downloaded it on 1-21-10 from this site. The creation date for the file I'm looking at is on Nov 13, 2006 12:56:48 PM.

Comment only
13 Nov 2009 Alex Kararg

I am interested in extracting the 3D Zernike descriptors of 3D shapes? Do you happen to know if there is any Matlab code?

Comment only
30 Jan 2009 Michael Black

Looks promising but I'm having a problem duplicating the LASIK example...I copied the lasik image and edited out the the lasik portion -- but all I get from the following is a big red blob -- not a decent reconstructed image...anybody know what's wrong?
% make grid coordinate matrices expressed in polar coordinates
L = size(I,1);
X = -1:2/(L-1):1;
[x,y] = meshgrid(X);
[theta,r] = cart2pol(x,y);
% Compute the required degree and order values from n=0-7, inclusive
N = [];
M = [];
for n=0:7
N = [N n*ones(1,n+1)];
M = [M -n:2:n];
is_in_circle = ( r <= 1);
Z = zernfun(N,M,r(is_in_circle),theta(is_in_circle));
a = Z\I(is_in_circle);
% Reconstruct image using Zernike coefficients
r(is_in_circle) = Z*a;
% rescale to 0-255 to display image
r = im2uint8(im2double(r));

22 Feb 2008 Ping Su

05 Feb 2008 hua housheng

23 Jan 2008 sadeq sadeghian

23 Jan 2008 sadegh sadeghian

10 Dec 2007 Alex Cht.

Valuable work, thank you.

18 Nov 2007 Mike lu

very helpful!It will be perfect if include the zernike annular polynomials

29 Aug 2007 Dong Liu

Why this error? Thank you!

??? Error: File: E:\zernike\zernpol.m Line: 151 Column: 25
"identifier" expected, "(" found.

Comment only
15 Aug 2007 smiled fisher

08 Feb 2007 Bijan Nemati

Very helpful, fast, and complete. Examples in the comments are very helpful too.

27 Nov 2006 ravi bakaraju

thank u

24 Jul 2006 hou xiaobing

thank you very much

15 Jun 2006 shijun xiang


23 Apr 2006 Udai Kiran

this the function i was looking for past few weeks

23 Aug 2005 Jose Flores

13 Nov 2006

Update to the algorithm for computing powers of R (vector of radius values).
Update to current MATLAB release.
Replaced code in ZERNFUN2 with a call to ZERNFUN.

24 Oct 2011 1.2

Updated Help documentation and screenshot.

29 Feb 2012 1.3

Removed an unneeded intermediate variable from the code.

01 Sep 2016

Updated license

Contact us