computer vision - Cubic spline / curve fitting -


i need determine parameters of illumintaion change, defined continuous piece-wise polynomial c(t), f(t) cubic curve defined 2 boundary points (t1,c) , (t2,0), f'(t1)=0 , f'(t2)=0. original paper: texture-consistent shadow removal

enter image description here

enter image description here

intensity curve sampled normal on boundary of shadow , looks this:

each row sample, displaying illumintaion change.so x number of column , y intensity of pixel.

enter image description here

i have real data (one sample avaraged samples): enter image description here

at have n samples , need determine parameters (c,t1,t2)

how can it?

i tried solving linear equation in matlab:

avr_curve average curve, obtained averaging on samples.

f(x)= x^3+a2*x^2+a1*x1+a0 cubic function

%t1,t2 selected hand t1= 10; t2= 15;  offset=10; avr_curve= [41, 40, 40, 41, 41, 42, 42, 43, 43, 43, 51, 76, 98, 104, 104, 103, 104, 105, 105, 107, 105]; %gradx= convn(avr_curve,[-1 1],'same');  a= zeros(2*offset+1,3); %b= zeros(2*offset+1,1); b= avr_curve'; %for i= 1:2*offset+1 i=t1:t2     x= i-offset-1   a(i,1)=  x^2; %a2   a(i,2)=  x; %a1   a(i,3)=  1; %a0    b(i,1)= b(i,1)-x^3; end  u= a\b;  figure,plot(avr_curve(t1:t2))   %estimated cubic curve i= 1:2*offset+1    x= i-offset-1;   fx(i)=x^3+u(1)*x^2+u(2)*x+u(3); end  figure,plot(fx(t1:t2)) 

part of avr_curve on [t1 t2] enter image description here

cubic curve got (don't looks avr_curve) enter image description here

so i'm doing wrong?

update: seems error due model cubic polynomial using 3 variables this:

f(x)= x^3+a2*x^2+a1*x1+a0 - 3 variables 

but use 4 variables seems ok:

f(x)= a3*x^3+a2*x^2+a1*x1+a0 - 4 variables  

here code in matlab:

%defined hand t1= 10; t2= 14;  avr_curve= [41, 40, 40, 41, 41, 42, 42, 43, 43, 43, 51, 76, 98, 104, 104, 103, 104, 105, 105, 107, 105]; x=         [1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,  15,  16,  17,  18,  19,  20,  21]; %x=        [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; %real x axis  %%%model 1 %%f(x)= x^3+a2*x^2+a1*x1+a0 - 3 variables %a= zeros(4,3); %b= [43  104]'; %%cubic equation @ t1  %a(1,1)= t1^2; %a2 %a(1,2)= t1; %a1 %a(1,3)= 1; %a0 %b(1,1)= b(1,1)-t1^3; %%cubic equation @ t2 %a(2,1)= t2^2; %a2 %a(2,2)= t2; %a1 %a(2,3)= 1; %a0 %b(2,1)= b(2,1)-t1^3; %%1st derivative @ t1 %a(3,1)= 2*t1; %a2 %a(3,2)= 1; %a1 %a(3,3)= 0; %a0 %b(3,1)= -3*t1^2; %%1st derivative @ t2 %a(4,1)= 2*t2; %a2 %a(4,2)= 1; %a1 %a(4,3)= 0; %a0 %b(4,1)= -3*t2^2;  %model 2 %f(x)= a3*x^3+a2*x^2+a1*x1+a0 - 4 variables a= zeros(4,4); b= [43  104]'; %cubic equation @ t1  a(1,1)= t1^3; %a3 a(1,2)= t1^2; %a2 a(1,3)= t1; %a1 a(1,4)= 1; %a0 b(1,1)= b(1,1); %cubic equation @ t2 a(2,1)= t2^3; %a3 a(2,2)= t2^2; %a2 a(2,3)= t2; %a1 a(2,4)= 1; %a0 b(2,1)= b(2,1); %1st derivative @ t1 a(3,1)= 3*t1^2; %a3 a(3,2)= 2*t1; %a2 a(3,3)= 1; %a1 a(3,4)= 0; %a0 b(3,1)= 0; %1st derivative @ t2 a(4,1)= 3*t2^2; %a3 a(4,2)= 2*t2; %a2 a(4,3)= 1; %a1 a(4,4)= 0; %a0 b(4,1)= 0;  size(a) size(b) u= a\b; u  %estimated cubic curve %dx=[1:21]; % global view dx=t1-1:t2+1; % local view in [t1 t2] x= dx   %fx(x)=x^3+u(1)*x^2+u(2)*x+u(3); % model 1   fx(x)= u(1)*x^3+u(2)*x^2+u(3)*x+u(4); % model 2 end  err= 0; x= dx   err= err+(fx(x)-avr_curve(x))^2; end  err  figure,plot(dx,avr_curve(dx),dx,fx(dx)) 

spline on interval [t1-1 t2+1] enter image description here

and on full interval

enter image description here

disclaimer

i cannot give guarantees on correctness of code or methods given below, use critical sense before using of that.

0. define problem

you have piecewise defined function

piecewise function recover

where f(t) cubic function, in order uniquely identify it, following additional conditions given

additional condition on cubic piece

you want recover best values of parameters t1, t2 , sigma minimize error given set of points.

this curve fitting in least squares sense.

1 parametrize f(t) cubic function

in order compute error between candidate cl(t) function , set of points need compute f(t), general form (being cubic) is

gerenal cubic

so seems have 4 additional parameters consider. indeed parameters totally defined free 3 parameters t1, t2 , sigma.
important not confuse free parameters dependent ones.

given additional conditions on f(t) can set linear system

solving linear system cubic

which has 1 solution (as expected) given by

parameters of cubic

this tell how compute parameters of cubic given 3 free parameters.
way cl(t) determined, it's time find best candidate.

2 minimize error

i go least squares now.
since not linear function, there no closed form computing sigma, t1 , t2.
there numerical methods, gauss-newton one.

however 1 way or required compute partial derivatives respect of 3 parameters.
i don't know how compute derivative respect of separation parameter t1.

i've searched mathse , found this question address same problem, nobody answered.

without partial derivatives least squares methods over.

so take more practical road , implemented brute force function in c try every possible triplet of parameter , return best match.

3 brute force function

given nature of problem, turned out o(n^2) in number of sample.

the algorithm proceeds follow: divide sample set in 3 parts, first 1 part of point before t1, second 1 of points between t1 , t2 , last 1 of points after t2.

the first part used compute sigma, sigma arithmetic average of points in part 1.

t1 , t2 computed through cycle, t1 set every possible point in original points set, starting second , going forward.
for every choice of t1, t2 set every possible point after t1.

at each iteration error computed , if minimum ever seen, parameters used saved.

the error computer absolute value of residuals since absolute value should fast (surely faster square) , fits purpose of metric.

4 code

#include <stdio.h> #include <math.h>  float point_on_curve(float sigma, float t1, float t2, float t) {     float a,b,c,d, k;      if (t <= t1)         return sigma;      if (t >= t2)         return 0;      k = (t1-t2)*(t1-t2)*(t1-t2);     = -2*sigma/k;     b = 3*sigma*(t1+t2)/k;     c = -6*sigma*t1*t2/k;     d = sigma*t2*t2*(3*t1-t2)/k;      return a*t*t*t + b*t*t + c*t + d; }  float compute_error(float sigma, float t1, float t2, int s, int dx, int* data, int len) {     float error=0;     unsigned int i;      (i = 0; < len; i++)         error += fabs(point_on_curve(sigma, t1, t2, s+i*dx)- data[i]);      return error; }  /*   * s starting time of samples set  * dx separation in time between 2 sample (a.k.a. sampling period)  * data array of samples  * len  number of samples  * sigma, t1, t2 pointers output parameters computed  *  * return 1 if not enough (3) samples, 0 if went ok.  */ int curve_fit(int s, int dx, int* data, unsigned int len, float* sigma, float* t1, float* t2) {     float l_sigma = 0;     float l_t1, l_t2;     float sum = 0;      float min_error, cur_error;     char error_valid = 0;      unsigned int i, j;      if (len < 3)         return 1;      (i = 0; < len; i++)     {         /* compute sigma average of points <= */         sum += data[i];         l_sigma = sum/(i+1);          /* set t1 point i+1 */         l_t1 = s+(i+1)*dx;          (j = i+2; j < len; j++)         {             /* set t2 points i+2, i+3, i+4, ... */             l_t2 = s+j*dx;              /* compute error */             cur_error = compute_error(l_sigma, l_t1, l_t2, s, dx, data, len);              if (cur_error < min_error || !error_valid)             {                 error_valid = 1;                 min_error = cur_error;                  *sigma = l_sigma;                 *t1 = l_t1;                 *t2 = l_t2;             }         }     }      return 0; }  int main() {     float sigma, t1, t2;     int data[]={41, 40, 40, 41, 41, 42, 42, 43, 43, 43, 51, 76, 98, 104, 104, 103, 104, 105, 105, 107, 105};     unsigned int len = sizeof(data)/sizeof(int);     unsigned int i;       (i = 0; < len; i++)         data[i] -= 107;             /* subtract max */       if (curve_fit(1,1,data, len, &sigma, &t1, &t2))         printf("not enough data!\n");     else          printf("parameters: sigma = %.3f, t1 = %.3f, t2 = %.3f\n", sigma, t1, t2);      return 0;   } 

please note cl(t) defined having 0 right limit, code assume case.

this why max value (107) subtracted every sample, have worked definition of cl(t) given @ beginning , late noted sample biased.

by i'm not going adapt code, can add parameter in problem , redo steps 1 if needed, or translate samples using maximum value.

the output of code is

 parameters: sigma = -65.556, t1 = 10.000, t2 = 14.000 

which match points set given, considering vertically translated -107.


Comments