algebraic lens distortion
|
00001 /* 00002 * Copyright 2009, 2010 IPOL Image Processing On Line http://www.ipol.im/ 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00024 #include "ami_pol.h" 00025 #include "stdlib.h" 00026 #include "stdio.h" 00027 00028 00035 long double ami_horner( 00036 long double *pol , 00037 int degree , 00038 long double x , 00039 long double *fp ) 00040 { 00041 long double PPX=pol[degree],PX=pol[degree]; 00042 int k; 00043 for(k=degree-1; k>0; k--) { 00044 PX=PX*x+pol[k]; 00045 PPX=PPX*x+PX; 00046 } 00047 PX=PX*x+pol[0]; 00048 *fp=PPX; 00049 return(PX); 00050 } 00051 00060 long double ami_root_bisection( 00061 long double *pol , 00062 int degree , 00063 long double a , 00064 long double b , 00065 long double TOL ) 00066 { 00067 long double a2=a,b2=b,fa,fb,c,c0,fc,fp; 00068 int iter=0,maxiter=100000; 00069 00070 fp=0.0; /*Added by Luis Gomez*/ 00071 00072 /* we evaluate the polynomial at interval extrema */ 00073 fa=ami_horner(pol,degree,a,&fp); 00074 fb=ami_horner(pol,degree,b,&fp); 00075 /* we check if there is a root in the interval */ 00076 if(fa*fb>0) return(0.5*(a+b)); 00077 /* we evaluate the interval middle point */ 00078 c=(a2+b2)*0.5; 00079 c0=c+1e30; 00080 /* we perform Newton-Raphson or Bisection iterations */ 00081 while( (b2-a2)>(TOL*fabs(b2)+1e-10) && fabs(c-c0)>(TOL*fabs(c0)+1e-10) && (iter++)<maxiter) { 00082 fc=ami_horner(pol,degree,c,&fp); 00083 /* we try Newton-Raphson */ 00084 c0=c; 00085 if(fp!=0.) { 00086 c=c-fc/fp; 00087 /* printf("c=%f\n",(double) c); */ 00088 if( c>=a2 && c<=b2 ) continue; 00089 } 00090 /* if Newton-Raphson fails, we try bisection */ 00091 c=(a2+b2)*0.5; 00092 fc=ami_horner(pol,degree,c,&fp); 00093 c0=c+1e30; 00094 /* we check if we have arrive to the root */ 00095 if(fabs(fc)<TOL) break; 00096 /* we perform bisection iteration */ 00097 if((fa*fc)<0) { 00098 b2=c; 00099 fb=fc; 00100 } 00101 else { 00102 a2=c; 00103 fa=fc; 00104 } 00105 c=(a2+b2)*0.5; 00106 } 00107 if(iter>=maxiter){return((a2+b2)*0.5);} 00108 return(c); 00109 } 00110 00119 int ami_polynomial_root( 00120 double *pol , 00123 int degree , 00124 double *root_r , 00125 double *root_i ) 00128 { 00129 00130 long double a,b,*p,*p_aux,*ap,*f,fp,*pol2,fa,fb,TOL=1e-14; 00131 long double max,n_factor; 00132 int m,k,l,Nr,N=degree; 00133 00134 p=p_aux=ap=f=pol2=NULL; 00135 fp=0.0; 00136 a=b=fa=fb=max=n_factor=0.0; /*Added by Luis Gomez*/ 00137 Nr=0;/*Added by Luis Gomez*/ 00138 00139 /* WE ALLOCATE MEMORY */ 00140 p=(long double*)malloc(sizeof(long double)*(N+2)); 00141 p_aux=(long double*)malloc(sizeof(long double)*(N+2)); 00142 ap=(long double*)malloc(sizeof(long double)*(N+1)); 00143 f=(long double*)malloc(sizeof(long double)*(N+1)); 00144 pol2=(long double*)malloc(sizeof(long double)*(N+2)); 00145 00146 /* POLYNOMIAL NORMALIZATION */ 00147 if(pol[0]!=1.) { 00148 for(k=0; k<=N; k++) pol[k]/=pol[0]; 00149 } 00150 00151 /* WE REORDER THE POLYNOM */ 00152 for(k=0; k<=N; k++) pol2[k]=pol[N-k]; 00153 pol2[N+1]=0.0; /*Added by Luis Gomez*/ 00154 00155 /* WE NORMALIZE POLINOMIAL COEFFICIENTS TO AVOID POLYNOMIAL EVALUATION IN LARGE NUMBERS*/ 00156 n_factor=0; 00157 for(k=0; k<N; k++) { 00158 if(fabs(pol2[k])>10.) { 00159 max=log(fabs((double) pol2[k])/10.)/(N-k); 00160 if(max>n_factor) n_factor=max; 00161 } 00162 } 00163 00164 n_factor=exp((double) n_factor); 00165 max=n_factor; 00166 for(k=N-1; k>=0; k--) { 00167 pol2[k]/=max; 00168 max*=n_factor; 00169 } 00170 00171 /* WE COMPUTE FACTORIAL NUMBERS */ 00172 f[0]=1.; 00173 for(k=1; k<=N; k++) f[k]=f[k-1]*k; 00174 00175 /* WE COMPUTE THE INITIAL INTERVAL WHERE ALL ROOTS ARE INCLUDED */ 00176 max=fabs(pol2[0]); 00177 for(k=1; k<N; k++) { 00178 if(fabs(pol2[k])>max) 00179 max=fabs(pol2[k]); 00180 } 00181 /* WE INITIALIZE THE INTERVALS */ 00182 p[0]=-1.-max/fabs(pol2[N]); 00183 /* WE COMPUTE THE POLYNOMIAL DEGREE-1 DERIVATE ROOT */ 00184 p[1]=-(pol2[N-1]*f[N-1])/(pol2[N]*f[N]); 00185 for(k=2; k<=(N+1); k++) p[k]=-p[0]; 00186 for(k=0; k<=N; k++)p_aux[k]=p[k]; 00187 p_aux[N+1]=0.0; /*Added by Luis Gomez*/ 00188 /* WE COMPUTE THE DERIVATIVE POLINOMIAL ROOTS IN A RECURSIVE WAY */ 00189 for(k=N-2; k>=0; k--) { 00190 /* we compute polynomial derivative coefficients */ 00191 for(l=0; l<=(N-k); l++) { 00192 ap[l]=pol2[l+k]*(f[k+l]/f[l]); 00193 } 00194 /* we check the valid intervals to compute derivative polynomial roots */ 00195 m=1; 00196 fa=ami_horner(ap,N-k,p_aux[0],&fp); 00197 for(l=1; l<=(N-k); l++) { 00198 fb=ami_horner(ap,N-k,p_aux[l],&fp); 00199 if((fa*fb)<=0 || fabs(fb)<=TOL) { 00200 p[m++]=p_aux[l]; 00201 fa=fb; 00202 } 00203 } 00204 for(l=m; l<N; l++) p[l]=p[N]; 00205 /* we compute the derivative polynomial roots in each interval */ 00206 for(l=1; l<=(N-k); l++) { 00207 p_aux[l]=ami_root_bisection(ap,N-k,p[l-1],p[l],TOL); 00208 } 00209 } 00210 00211 /* WE STORE THE ROOTS */ 00212 root_i[0]=0.; /* we fit the complex component of the root to 0 */ 00213 Nr=0; 00214 for(k=1; k<=N; k++) { 00215 /* we check if the polynomial has a root in the point */ 00216 a=(p_aux[k]+p_aux[k-1])*0.5; 00217 b=(p_aux[k]+p_aux[k+1])*0.5; 00218 fa=ami_horner(pol2,degree,a,&fp); 00219 fb=ami_horner(pol2,degree,b,&fp); 00220 if(fa*fb<0 || fabs(ami_horner(pol2,degree,p_aux[k],&fp))<TOL) { 00221 root_i[Nr]=0; /* we fit the complex component of the root to 0 */ 00222 root_r[Nr++]=p_aux[k]*n_factor; /* we denormalize the root */ 00223 } 00224 } 00225 /* we free the memory */ 00226 free(p); 00227 free(ap); 00228 free(f); 00229 free(pol2); 00230 free(p_aux); 00231 /* we return the number of real roots estimated */ 00232 return(Nr); 00233 00234 }