00001 #include "brip_vil_float_ops.h"
00002 
00003 
00004 
00005 #include <vcl_cassert.h>
00006 #include <vcl_fstream.h>
00007 #include <vcl_complex.h>
00008 #include <vcl_limits.h>
00009 #include <vgl/vgl_box_2d.h>
00010 #include <vgl/vgl_point_2d.h>
00011 #include <vgl/vgl_vector_2d.h>
00012 #include <vgl/vgl_polygon_scan_iterator.h>
00013 #include <vul/vul_timer.h>
00014 #include <vbl/vbl_array_1d.h>
00015 #include <vbl/vbl_array_2d.h>
00016 #include <vbl/vbl_bounding_box.h>
00017 #include <vnl/vnl_numeric_traits.h>
00018 #include <vnl/vnl_math.h>
00019 #include <vnl/vnl_double_2x3.h>
00020 #include <vnl/algo/vnl_fft_prime_factors.h>
00021 #include <vnl/algo/vnl_svd.h>
00022 #include <vil/vil_pixel_format.h>
00023 #include <vil/vil_transpose.h>
00024 
00025 #include <vil/vil_convert.h>
00026 #include <vil/vil_save.h>
00027 #include <vil/vil_new.h>
00028 
00029 #include <vil/vil_math.h>
00030 #include <vil/algo/vil_convolve_1d.h>
00031 #include <vsol/vsol_box_2d.h>
00032 #include <vsol/vsol_polygon_2d_sptr.h>
00033 #include <vsol/vsol_polygon_2d.h>
00034 #include <bsol/bsol_algs.h>
00035 #include <bsta/bsta_histogram.h>
00036 #include <bsta/bsta_joint_histogram.h>
00037 #include <brip/brip_roi.h>
00038 
00039 
00040 
00041 
00042 static float cross_corr(double area, double si1, double si2,
00043                         double si1i1, double si2i2, double si1i2,
00044                         float intensity_thresh)
00045 {
00046   if (!area)
00047     return 0.f;
00048   
00049   double u1 = si1/area, u2 = si2/area;
00050   if (u1<intensity_thresh||u2<intensity_thresh)
00051     return -1.f;
00052   double neu = si1i2 - area*u1*u2;
00053   double sd1 = vcl_sqrt(vcl_fabs(si1i1-area*u1*u1)),
00054     sd2 = vcl_sqrt(vcl_fabs(si2i2-area*u2*u2));
00055   if (!neu)
00056     return 0.f;
00057   if (!sd1||!sd2) {
00058     if (neu>0)
00059       return 1.f;
00060     else
00061       return -1.f;
00062   }
00063   double den = sd1*sd2;
00064   return float(neu/den);
00065 }
00066 
00067 
00068 
00069 
00070 vil_image_view<float>
00071 brip_vil_float_ops::convolve(vil_image_view<float> const& input,
00072                              vbl_array_2d<float> const& kernel)
00073 {
00074   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
00075   int kw = kernel.cols(); 
00076   
00077   int n = (kw-1)/2;
00078   vil_image_view<float> output;
00079   output.set_size(w,h);
00080   for (int y = n; y<(h-n); y++)
00081     for (int x = n; x<(w-n); x++)
00082     {
00083       float accum = 0;
00084       for (int j = -n; j<=n; j++)
00085         for (int i = -n; i<=n; i++)
00086         {
00087           float x1 = input(x+i,y+j);
00088           float x2 = kernel[i+n][j+n];
00089           accum += x1*x2;
00090         }
00091       output(x,y)=accum;
00092     }
00093   brip_vil_float_ops::fill_x_border(output, n, 0.0f);
00094   brip_vil_float_ops::fill_y_border(output, n, 0.0f);
00095   return output;
00096 }
00097 
00098 static void fill_1d_array(vil_image_view<float> const& input,
00099                           int y, float* output)
00100 {
00101   unsigned w = input.ni();
00102   for (unsigned x = 0; x<w; x++)
00103     output[x] = input(x,y);
00104 }
00105 
00106 
00107 void brip_vil_float_ops::half_resolution_1d(const float* input, unsigned width,
00108                                             float k0, float k1, float k2,
00109                                             float* output)
00110 {
00111   float w[5];
00112   int n = 0;
00113   for (; n<5; n++)
00114     w[n]=input[n];
00115   output[0]=k0*w[0]+ 2.0f*(k1*w[1] + k2*w[2]); 
00116   for (unsigned x = 1; x<width; ++x)
00117   {
00118     output[x]=k0*w[2]+ k1*(w[1]+w[3]) + k2*(w[0]+w[4]);
00119     
00120     w[0] = w[2];       w[1] = w[3];     w[2] = w[4];
00121     
00122     if (x+2<width)
00123       w[3] = input[n++], w[4] = input[n++];
00124     else
00125       w[3] = w[1], w[4] = w[0];
00126   }
00127 }
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 vil_image_view<float>
00137 brip_vil_float_ops::half_resolution(vil_image_view<float> const& input,
00138                                     float filter_coef)
00139 {
00140   vul_timer t;
00141   float k0 = filter_coef, k1 = 0.25f*filter_coef, k2 = 0.5f*(0.5f-filter_coef);
00142   unsigned w = input.ni(), h = input.nj();
00143   int half_w =(w+1)/2, half_h = (h+1)/2;
00144   vil_image_view<float> output;
00145   output.set_size(half_w, half_h);
00146   
00147   int n = 0;
00148   float* in0 = new float[w];  float* in1 = new float[w];
00149   float* in2 = new float[w];  float* in3 = new float[w];
00150   float* in4 = new float[w];
00151 
00152   float* out0 = new float[half_w];  float* out1 = new float[half_w];
00153   float* out2 = new float[half_w];  float* out3 = new float[half_w];
00154   float* out4 = new float[half_w];
00155   
00156   fill_1d_array(input, n++, in0);   fill_1d_array(input, n++, in1);
00157   fill_1d_array(input, n++, in2);   fill_1d_array(input, n++, in3);
00158   fill_1d_array(input, n++, in4);
00159 
00160   
00161   brip_vil_float_ops::half_resolution_1d(in0, half_w, k0, k1, k2, out0);
00162   brip_vil_float_ops::half_resolution_1d(in1, half_w, k0, k1, k2, out1);
00163   brip_vil_float_ops::half_resolution_1d(in2, half_w, k0, k1, k2, out2);
00164   brip_vil_float_ops::half_resolution_1d(in3, half_w, k0, k1, k2, out3);
00165   brip_vil_float_ops::half_resolution_1d(in4, half_w, k0, k1, k2, out4);
00166   int x=0, y;
00167   
00168   for (;x<half_w;x++)
00169     output(x,0)= k0*out0[x]+ 2.0f*(k1*out1[x]+k2*out2[x]);
00170   
00171   for (y=1; y<half_h; y++)
00172   {
00173     for (x=0; x<half_w; x++)
00174       output(x,y) = k0*out2[x]+ k1*(out1[x]+out3[x]) + k2*(out0[x]+out4[x]);
00175     
00176     float* temp0 = out0;
00177     float* temp1 = out1;
00178     out0 = out2;  out1 = out3;  out2 = out4;
00179     out3 = temp0; out4 = temp1;
00180     
00181     if (y<half_h-2)
00182     {
00183       
00184       fill_1d_array(input, n++, in3);
00185       fill_1d_array(input, n++, in4);
00186       brip_vil_float_ops::half_resolution_1d(in3, half_w, k0, k1, k2, out3);
00187       brip_vil_float_ops::half_resolution_1d(in4, half_w, k0, k1, k2, out4);
00188     }
00189   }
00190   delete [] in0;  delete [] in1; delete [] in2;
00191   delete [] in3;  delete [] in4;
00192   delete [] out0;  delete [] out1; delete [] out2;
00193   delete [] out3;  delete [] out4;
00194 #ifdef DEBUG
00195   vcl_cout << "\nDownsample a "<< w <<" x " << h << " image in "<< t.real() << " msecs.\n";
00196 #endif
00197   return output;
00198 }
00199 
00200 void brip_vil_float_ops::double_resolution_1d(const float* input, const unsigned n_input,
00201                                               const float k0, const float k1,
00202                                               const float k2, float* output)
00203 {
00204   float w[3];
00205   unsigned i = 0;
00206   w[1]=input[i]; w[2]=input[i++];
00207   w[0]=w[2];
00208   for (unsigned c = 0; c<2*n_input; c+=2)
00209   {
00210     output[c] = k0*w[1] + k2*(w[0]+w[2]);
00211     output[c+1] = k1*(w[1]+w[2]);
00212     w[0]=w[1];
00213     w[1]=w[2];
00214     if (c<2*(n_input-2))
00215       w[2]=input[i++];
00216     else
00217       w[2]=w[0];
00218   }
00219 }
00220 
00221 
00222 vil_image_view<float>
00223 brip_vil_float_ops::double_resolution(vil_image_view<float> const& input,
00224                                       float filter_coef)
00225 {
00226   unsigned ni_in = input.ni();
00227   unsigned nj_in = input.nj();
00228   unsigned ni_out = 2*ni_in;
00229   unsigned nj_out = 2*nj_in;
00230   vil_image_view<float> out(ni_out, nj_out);
00231   float* input_1d = new float[ni_in];
00232 
00233   
00234   float* output0 = new float[ni_out];
00235   float* output1 = new float[ni_out];
00236   float* output2 = new float[ni_out];
00237 
00238   
00239   float k0 = filter_coef*2.0f;
00240   float k1 = 0.5f;
00241   float k2 = 0.5f-filter_coef;
00242 
00243   
00244   unsigned i = 0;
00245   fill_1d_array(input, i++, input_1d);
00246   brip_vil_float_ops::double_resolution_1d(input_1d, ni_in, k0, k1, k2, output1);
00247   fill_1d_array(input, i++, input_1d);
00248   brip_vil_float_ops::double_resolution_1d(input_1d, ni_in, k0, k1, k2, output2);
00249   for (unsigned k = 0; k<ni_out; ++k)
00250     output0[k]=output2[k];
00251   for (unsigned r = 0; r<nj_out; r+=2)
00252   {
00253     unsigned rp = r+1;
00254     for (unsigned c=0; c<ni_out; ++c)
00255     {
00256       out(c, r) = k0*output1[c] + k2*(output0[c]+output2[c]);
00257       out(c, rp) = k1*(output1[c]+output2[c]);
00258     }
00259     float* next = output0;
00260     output0 = output1;
00261     output1 = output2;
00262     output2 = next;
00263     if (r<nj_out-4)
00264     {
00265       fill_1d_array(input, i++, input_1d);
00266       brip_vil_float_ops::double_resolution_1d(input_1d, ni_in,
00267                                                k0, k1, k2, output2);
00268     }
00269     else
00270       for (unsigned k = 0; k<ni_out; ++k)
00271         output2[k]=output0[k];
00272   }
00273   delete [] input_1d;
00274   delete [] output0;
00275   delete [] output1;
00276   delete [] output2;
00277   return out;
00278 }
00279 
00280 static double brip_vil_gaussian(double x, double sigma)
00281 {
00282   double x_on_sigma = x / sigma;
00283   return (double)vcl_exp(- x_on_sigma * x_on_sigma / 2);
00284 }
00285 
00286 unsigned brip_vil_float_ops::gaussian_radius(const double sigma,
00287                                              const double fuzz)
00288 {
00289   unsigned radius = 0;
00290   while ((float)brip_vil_gaussian((double)radius, sigma) > fuzz) ++radius;
00291   return radius;
00292 }
00293 
00294 
00295 static void brip_1d_gaussian_kernel(double sigma, double fuzz,
00296                                     unsigned& radius, double*& kernel)
00297 {
00298   radius = brip_vil_float_ops::gaussian_radius(sigma, fuzz);
00299 
00300   kernel = new double[2*radius + 1];
00301   if (!radius)
00302   {
00303     kernel[0]=1;
00304     return;
00305   }
00306   for (unsigned i=0; i<=radius; ++i)
00307     kernel[radius+i] = kernel[radius-i] = brip_vil_gaussian(double(i), sigma);
00308   double sum = 0;
00309   for (unsigned i= 0; i <= 2*radius; ++i)
00310     sum += kernel[i];                           
00311   for (unsigned i= 0; i <= 2*radius; ++i)
00312     kernel[i] /= sum;                           
00313 }
00314 
00315 vil_image_view<float>
00316 brip_vil_float_ops::gaussian(vil_image_view<float> const& input, float sigma,
00317                              float fill)
00318 {
00319   unsigned ni = input.ni(), nj = input.nj();
00320   unsigned np = input.nplanes();
00321   vil_image_view<float> dest(ni, nj, np);
00322   dest.fill(fill);
00323   unsigned r;
00324   double* ker;
00325   brip_1d_gaussian_kernel(sigma, 0.02, r, ker);
00326   for (unsigned p = 0; p<np; ++p) {
00327     vil_image_view<float> input_temp(ni, nj);
00328     vil_image_view<float> out_temp(ni, nj);
00329     vil_image_view<float> work(ni, nj);
00330     work.fill(fill);
00331     for (unsigned j = 0; j<nj; ++j)
00332       for (unsigned i = 0; i<ni; ++i)
00333         input_temp(i,j) = input(i,j,p);
00334 
00335     
00336     int ksize = 2*r + 1 ;
00337     float accum=0.0f;
00338     vil_convolve_1d(input_temp, work, ker + ksize/2,
00339                     -ksize/2, r, accum,
00340                     vil_convolve_ignore_edge,
00341                     vil_convolve_ignore_edge);
00342 
00343     
00344     vil_image_view<float> work_t = vil_transpose(work);
00345     vil_image_view<float> out_temp_t = vil_transpose(dest);
00346     vil_convolve_1d(work_t, out_temp_t, ker+ ksize/2,
00347                     -ksize/2, r, accum,
00348                     vil_convolve_ignore_edge,
00349                     vil_convolve_ignore_edge);
00350     vil_image_view<float> plane = vil_transpose(out_temp_t);
00351     for (unsigned j = 0; j<nj; ++j)
00352       for (unsigned i = 0; i<ni; ++i)
00353         dest(i,j,p) = plane(i,j);
00354   }
00355   delete ker;
00356   return dest;
00357 }
00358 
00359 vil_image_view<float>
00360 brip_vil_float_ops::absolute_value(vil_image_view<float> const& input)
00361 {
00362   unsigned ni = input.ni(), nj = input.nj();
00363   unsigned np = input.nplanes();
00364   vil_image_view<float> dest(ni, nj, np);
00365   for (unsigned p = 0; p<np; ++p)
00366     for (unsigned j = 0; j<nj; ++j)
00367       for (unsigned i = 0; i<ni; ++i)
00368         dest(i,j,p) = vcl_fabs(input(i,j,p));
00369   return dest;
00370 }
00371 
00372 #ifdef VIL_CONVOLVE_WITH_MASK_EXISTS // TODO
00373 vil_image_view<float>
00374 brip_vil_float_ops::gaussian(vil_image_view<float> const& input,
00375                              float sigma,
00376                              vil_image_view<float> const& mask)
00377 {
00378   vil_image_view<float> dest(input.ni(), input.nj());
00379 
00380   int r;
00381   double* ker;
00382   brip_1d_gaussian_kernel(sigma, 0.02, r, ker);
00383   vil_image_view<float> work(input.ni(), input.nj());
00384   work.deep_copy(input);
00385   
00386   int ksize = 2*r + 1 ;
00387   float accum=0.0f;
00388   vil_convolve_1d(input, work, mask, ker + ksize/2,
00389                   -ksize/2, r, accum,
00390                   vil_convolve_trim,
00391                   vil_convolve_trim);
00392 
00393   
00394   vil_image_view<float> work_t = vil_transpose(work);
00395   vil_image_view<float> dest_t = vil_transpose(dest);
00396   vil_convolve_1d(work_t, dest_t, vil_transpose(mask), ker+ ksize/2,
00397                   -ksize/2, r, accum,
00398                   vil_convolve_constant_extend,
00399                   vil_convolve_constant_extend);
00400 
00401   delete ker;
00402   return dest;
00403 }
00404 
00405 #endif // VIL_CONVOLVE_WITH_MASK_EXISTS
00406 
00407 
00408 
00409 
00410 bool brip_vil_float_ops::
00411 local_maximum(vbl_array_2d<float> const& neighborhood, int n, float& value)
00412 {
00413   bool local_max = true;
00414   value = 0;
00415   float center = neighborhood[n][n];
00416   for (int y = -n; y<=n; y++)
00417     for (int x = -n; x<=n; x++)
00418       local_max = local_max&&(neighborhood[y+n][x+n]<=center);
00419   if (!local_max)
00420     return false;
00421   value = center;
00422   return true;
00423 }
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 void brip_vil_float_ops::
00432 interpolate_center(vbl_array_2d<float>const& neighborhood, float& dx, float& dy)
00433 {
00434   dx = 0; dy=0;
00435   
00436   float n_m1_m1 = neighborhood[0][0];
00437   float n_m1_0 = neighborhood[0][1];
00438   float n_m1_1 = neighborhood[0][2];
00439   float n_0_m1 = neighborhood[1][0];
00440   float n_0_0 = neighborhood[1][1];
00441   float n_0_1 = neighborhood[1][2];
00442   float n_1_m1 = neighborhood[2][0];
00443   float n_1_0 = neighborhood[2][1];
00444   float n_1_1 = neighborhood[2][2];
00445 
00446   
00447   
00448   
00449   
00450   float Ix =(-n_m1_m1+n_m1_1-n_0_m1+n_0_1-n_1_m1+n_1_1)/6.0f;
00451   
00452   
00453   
00454   float Iy =(-n_m1_m1-n_m1_0-n_m1_1+n_1_m1+n_1_0+n_1_1)/6.0f;
00455   
00456   
00457   
00458   float Ixx = ((n_m1_m1+n_0_m1+n_1_m1+n_m1_1+n_0_1+n_1_1)
00459                -2.0f*(n_m1_0+n_0_0+n_1_0))/3.0f;
00460   
00461   
00462   
00463   float Ixy = (n_m1_m1-n_m1_1+n_1_m1+n_1_1)/4.0f;
00464   
00465   
00466   
00467   float Iyy = ((n_m1_m1+n_m1_0+n_m1_1+n_1_m1+n_1_0+n_1_1)
00468                -2.0f*(n_0_m1 + n_0_0 + n_1_0))/3.0f;
00469   
00470   
00471   
00472   
00473   
00474   
00475   
00476   
00477   
00478   
00479   float det = Ixx*Iyy - Ixy*Ixy;
00480   
00481   if (det>0)
00482   {
00483     dx = (Iy*Ixy - Ix*Iyy) / det;
00484     dy = (Ix*Ixy - Iy*Ixx) / det;
00485     
00486     if (vcl_fabs(dx) > 1.0 || vcl_fabs(dy) > 1.0)
00487       dx = 0; dy = 0;
00488   }
00489 }
00490 
00491 
00492 
00493 
00494 
00495 void brip_vil_float_ops::
00496 non_maximum_suppression(vil_image_view<float> const& input,
00497                         int n, float thresh,
00498                         vcl_vector<float>& x_pos,
00499                         vcl_vector<float>& y_pos,
00500                         vcl_vector<float>& value)
00501 {
00502   vul_timer t;
00503   int N = 2*n+1;
00504   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
00505   x_pos.clear();  x_pos.clear();   value.clear();
00506   vbl_array_2d<float> neighborhood(N,N);
00507   for (int y =n; y<h-n; y++)
00508     for (int x = n; x<w-n; x++)
00509     {
00510       
00511       
00512       if (input(x,y)<thresh)
00513         continue;
00514       
00515       for (int i = -n; i<=n; i++)
00516         for (int j = -n; j<=n; j++)
00517           neighborhood.put(j+n,i+n,input(x+i, y+j));
00518       
00519       float dx, dy, max_v;
00520       if (brip_vil_float_ops::local_maximum(neighborhood, n, max_v))
00521       {
00522         
00523         brip_vil_float_ops::interpolate_center(neighborhood, dx, dy);
00524         x_pos.push_back((float)x+dx);
00525         y_pos.push_back((float)y+dy);
00526         value.push_back(max_v);
00527       }
00528     }
00529 #ifdef DEBUG
00530   vcl_cout << "\nCompute non-maximum suppression on a "<< w <<" x " << h << " image in "<< t.real() << " msecs.\n";
00531 #endif
00532 }
00533 
00534 
00535 
00536 
00537 
00538 vil_image_view<float>
00539 brip_vil_float_ops::difference(vil_image_view<float> const& image_1,
00540                                vil_image_view<float> const& image_2)
00541 {
00542   unsigned w1 = image_1.ni(), h1 = image_1.nj();
00543   unsigned w2 = image_2.ni(), h2 = image_2.nj();
00544   vil_image_view<float> temp(w1, h1);
00545   if (w1!=w2||h1!=h2)
00546   {
00547     vcl_cout << "In brip_vil_float_ops::difference(..) - images are not the same dimensions\n";
00548     return temp;
00549   }
00550   vil_image_view<float> out;
00551   out.set_size(w1, h1);
00552   for (unsigned y = 0; y<h1; y++)
00553     for (unsigned x = 0; x<w1; x++)
00554       out(x,y) = image_2(x,y)-image_1(x,y);
00555   return out;
00556 }
00557 
00558 
00559 vil_image_resource_sptr brip_vil_float_ops::negate(vil_image_resource_sptr const& imgr)
00560 {
00561   vil_image_resource_sptr outr;
00562   if (!imgr)
00563     return outr;
00564 
00565   vil_pixel_format fmt = imgr->pixel_format();
00566   switch (fmt)
00567     {
00568 #define NEGATE_CASE(FORMAT, T) \
00569    case FORMAT: { \
00570     vil_image_view<T> view = imgr->get_copy_view(); \
00571     T mxv = vcl_numeric_limits<T>::max(); \
00572     vil_math_scale_and_offset_values(view, -1.0, mxv); \
00573     outr = vil_new_image_resource_of_view(view);  \
00574     break; \
00575                 }
00576       NEGATE_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00577       NEGATE_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00578       NEGATE_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00579       NEGATE_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00580       NEGATE_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00581       NEGATE_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00582 #undef NEGATE_CASE
00583     default:
00584       vcl_cout << "Unknown image format\n";
00585     }
00586   return outr;
00587 }
00588 
00589 vil_image_view<float>
00590 brip_vil_float_ops::threshold(vil_image_view<float> const & image,
00591                               const float thresh, const float level)
00592 {
00593   vil_image_view<float> out;
00594   unsigned w = image.ni(), h = image.nj();
00595   out.set_size(w, h);
00596   for (unsigned y = 0; y<h; y++)
00597     for (unsigned x = 0; x<w; x++)
00598     {
00599       if (image(x,y)>thresh)
00600         out(x,y) = level;
00601       else
00602         out(x,y) = 0;
00603     }
00604   return out;
00605 }
00606 
00607 vil_image_view<float>
00608 brip_vil_float_ops::abs_clip_to_level(vil_image_view<float> const& image,
00609                                       float thresh, float level)
00610 {
00611   vil_image_view<float> out;
00612   unsigned w = image.ni(), h = image.nj();
00613   out.set_size(w, h);
00614   for (unsigned y = 0; y<h; y++)
00615     for (unsigned x = 0; x<w; x++)
00616     {
00617       if (vcl_fabs(image(x,y))>thresh)
00618         out(x,y) = level;
00619       else
00620         out(x,y) = image(x,y);
00621     }
00622   return out;
00623 }
00624 
00625 vil_image_view<float> brip_vil_float_ops::average_NxN(vil_image_view<float> const & img, int N)
00626 {
00627   vil_image_view<float> result;
00628   unsigned w = img.ni(), h = img.nj();
00629   result.set_size (w, h);
00630 
00631   vbl_array_2d <float> averaging_filt(N, N);
00632   averaging_filt.fill( float(1.00/double(N*N)) );
00633   result = brip_vil_float_ops::convolve(img, averaging_filt);
00634   return result;
00635 }
00636 
00637 
00638 
00639 
00640 
00641 
00642 
00643 
00644 
00645 
00646 void brip_vil_float_ops::gradient_3x3(vil_image_view<float> const& input,
00647                                       vil_image_view<float>& grad_x,
00648                                       vil_image_view<float>& grad_y)
00649 {
00650   vul_timer t;
00651   unsigned w = input.ni(), h = input.nj();
00652   float scale = 1.0f/6.0f;
00653   for (unsigned y = 1; y+1<h; ++y)
00654     for (unsigned x = 1; x+1<w; ++x)
00655     {
00656       float gx = input(x+1,y-1)+input(x+1,y)+input(x+1,y-1)
00657                 -input(x-1,y-1)-input(x-1,y)-input(x-1,y-1);
00658       float gy = input(x+1,y+1)+input(x,y+1)+input(x-1,y+1)
00659                 -input(x+1,y-1)-input(x,y-1)-input(x-1,y-1);
00660       grad_x(x,y) = scale*gx;
00661       grad_y(x,y) = scale*gy;
00662     }
00663   brip_vil_float_ops::fill_x_border(grad_x, 1, 0.0f);
00664   brip_vil_float_ops::fill_y_border(grad_x, 1, 0.0f);
00665   brip_vil_float_ops::fill_x_border(grad_y, 1, 0.0f);
00666   brip_vil_float_ops::fill_y_border(grad_y, 1, 0.0f);
00667 #ifdef DEBUG
00668   vcl_cout << "\nCompute Gradient in " << t.real() << " msecs.\n";
00669 #endif
00670 }
00671 
00672 void brip_vil_float_ops::gradient_mag_3x3(vil_image_view<float> const& input,
00673                                           vil_image_view<float>& mag)
00674 {
00675   unsigned w = input.ni(), h = input.nj();
00676   float scale = 1.0f/6.0f;
00677   for (unsigned y = 1; y+1<h; ++y)
00678     for (unsigned x = 1; x+1<w; ++x)
00679     {
00680       float gx = input(x+1,y-1)+input(x+1,y)+input(x+1,y-1)
00681                 -input(x-1,y-1)-input(x-1,y)-input(x-1,y-1);
00682       float gy = input(x+1,y+1)+input(x,y+1)+input(x-1,y+1)
00683                 -input(x+1,y-1)-input(x,y-1)-input(x-1,y-1);
00684       mag(x,y) = scale*vcl_sqrt(gx*gx+gy*gy);
00685     }
00686   brip_vil_float_ops::fill_x_border(mag, 1, 0.0f);
00687   brip_vil_float_ops::fill_y_border(mag, 1, 0.0f);
00688 }
00689 
00690 void brip_vil_float_ops::
00691 gradient_mag_comp_3x3(vil_image_view<float> const& input,
00692                       vil_image_view<float>& mag,
00693                       vil_image_view<float>& gx,
00694                       vil_image_view<float>& gy)
00695 {
00696   unsigned w = input.ni(), h = input.nj();
00697   float scale = 1.0f/6.0f;
00698   for (unsigned y = 1; y+1<h; ++y)
00699     for (unsigned x = 1; x+1<w; ++x)
00700     {
00701       float ggx = input(x+1,y-1)+input(x+1,y)+input(x+1,y-1)
00702                  -input(x-1,y-1)-input(x-1,y)-input(x-1,y-1);
00703       float ggy = input(x+1,y+1)+input(x,y+1)+input(x-1,y+1)
00704                  -input(x+1,y-1)-input(x,y-1)-input(x-1,y-1);
00705       mag(x,y) = scale*vcl_sqrt(ggx*ggx+ggy*ggy);
00706       gx(x,y) = ggx*scale;
00707       gy(x,y) = ggy*scale;
00708     }
00709   brip_vil_float_ops::fill_x_border(mag, 1, 0.0f);
00710   brip_vil_float_ops::fill_y_border(mag, 1, 0.0f);
00711   brip_vil_float_ops::fill_x_border(gx, 1, 0.0f);
00712   brip_vil_float_ops::fill_y_border(gy, 1, 0.0f);
00713 }
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 void brip_vil_float_ops::hessian_3x3(vil_image_view<float> const& input,
00725                                      vil_image_view<float>& Ixx,
00726                                      vil_image_view<float>& Ixy,
00727                                      vil_image_view<float>& Iyy)
00728 {
00729   vul_timer t;
00730   unsigned w = input.ni(), h = input.nj();
00731   for (unsigned y = 1; y+1<h; ++y)
00732     for (unsigned x = 1; x+1<w; ++x)
00733     {
00734       float xx = input(x-1,y-1)+input(x-1,y)+input(x+1,y+1)+
00735                  input(x+1,y-1)+input(x+1,y)+input(x+1,y+1)-
00736                  2.0f*(input(x,y-1)+input(x,y)+input(x,y+1));
00737 
00738       float xy = (input(x-1,y-1)+input(x+1,y+1))-
00739                  (input(x-1,y+1)+input(x+1,y-1));
00740 
00741       float yy = input(x-1,y-1)+input(x,y-1)+input(x+1,y-1)+
00742                  input(x-1,y+1)+input(x,y+1)+input(x+1,y+1)-
00743                  2.0f*(input(x-1,y)+input(x,y)+input(x+1,y));
00744 
00745       Ixx(x,y) = xx/3.0f;
00746       Ixy(x,y) = xy/4.0f;
00747       Iyy(x,y) = yy/3.0f;
00748     }
00749   brip_vil_float_ops::fill_x_border(Ixx, 1, 0.0f);
00750   brip_vil_float_ops::fill_y_border(Ixx, 1, 0.0f);
00751   brip_vil_float_ops::fill_x_border(Ixy, 1, 0.0f);
00752   brip_vil_float_ops::fill_y_border(Ixy, 1, 0.0f);
00753   brip_vil_float_ops::fill_x_border(Iyy, 1, 0.0f);
00754   brip_vil_float_ops::fill_y_border(Iyy, 1, 0.0f);
00755 #ifdef DEBUG
00756   vcl_cout << "\nCompute a hessian matrix "<< w <<" x " << h << " image in "<< t.real() << " msecs.\n";
00757 #endif
00758 }
00759 
00760 vil_image_view<float>
00761 brip_vil_float_ops::beaudet(vil_image_view<float> const& Ixx,
00762                             vil_image_view<float> const& Ixy,
00763                             vil_image_view<float> const& Iyy,
00764                             bool determinant)
00765 {
00766   unsigned w = Ixx.ni(), h = Ixx.nj();
00767   vil_image_view<float> output;
00768   output.set_size(w, h);
00769   for (unsigned y = 0; y<h; y++)
00770     for (unsigned x = 0; x<w; x++)
00771     {
00772       float xx = Ixx(x,y), xy = Ixy(x,y), yy = Iyy(x,y);
00773 
00774       
00775       float det = xx*yy-xy*xy;
00776       float tr = xx+yy;
00777       float arg = tr*tr-4.f*det, lambda0 = 0, lambda1=0;
00778       if (arg>0)
00779       {
00780         lambda0 = tr+vcl_sqrt(arg);
00781         lambda1 = tr-vcl_sqrt(arg);
00782       }
00783       if (determinant)
00784         output(x,y) = det;
00785       else
00786         output(x,y) = tr;
00787     }
00788   return output;
00789 }
00790 
00791 
00792 
00793 
00794 
00795 
00796 
00797 
00798 
00799 
00800 
00801 
00802 
00803 
00804 void
00805 brip_vil_float_ops::grad_matrix_NxN(vil_image_view<float> const& input,
00806                                     unsigned n,
00807                                     vil_image_view<float>& IxIx,
00808                                     vil_image_view<float>& IxIy,
00809                                     vil_image_view<float>& IyIy)
00810 {
00811   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
00812   int N = (2*n+1)*(2*n+1);
00813   int ni = static_cast<int>(n);
00814   vil_image_view<float> grad_x, grad_y, output;
00815   grad_x.set_size(w,h);
00816   grad_y.set_size(w,h);
00817   output.set_size(w,h);
00818   brip_vil_float_ops::gradient_3x3(input, grad_x, grad_y);
00819   vul_timer t;
00820   for (int y = ni; y<h-ni;y++)
00821     for (int x = ni; x<w-ni;x++)
00822     {
00823       float xx=0, xy=0, yy=0;
00824       for (int i = -ni; i<=ni; i++)
00825         for (int j = -ni; j<=ni; j++)
00826         {
00827           float gx = grad_x(x+i, y+j), gy = grad_y(x+i, y+j);
00828           xx += gx*gx;
00829           xy += gx*gy;
00830           yy += gy*gy;
00831         }
00832       IxIx(x,y) = xx/(float)N;
00833       IxIy(x,y) = xy/(float)N;
00834       IyIy(x,y) = yy/(float)N;
00835     }
00836   brip_vil_float_ops::fill_x_border(IxIx, ni, 0.0f);
00837   brip_vil_float_ops::fill_y_border(IxIx, ni, 0.0f);
00838   brip_vil_float_ops::fill_x_border(IxIy, ni, 0.0f);
00839   brip_vil_float_ops::fill_y_border(IxIy, ni, 0.0f);
00840   brip_vil_float_ops::fill_x_border(IyIy, ni, 0.0f);
00841   brip_vil_float_ops::fill_y_border(IyIy, ni, 0.0f);
00842 #ifdef DEBUG
00843   vcl_cout << "\nCompute a gradient matrix "<< w <<" x " << h << " image in "<< t.real() << " msecs.\n";
00844 #endif
00845 }
00846 
00847 vil_image_view<float> brip_vil_float_ops::
00848 trace_grad_matrix_NxN(vil_image_view<float> const& input, unsigned n)
00849 {
00850   unsigned ni = input.ni(), nj = input.nj();
00851   vil_image_view<float> IxIx;
00852   vil_image_view<float> IxIy;
00853   vil_image_view<float> IyIy;
00854   vil_image_view<float> tr;
00855   IxIx.set_size(ni, nj);   IxIy.set_size(ni, nj);   IyIy.set_size(ni, nj);
00856   tr.set_size(ni, nj);
00857   brip_vil_float_ops::grad_matrix_NxN(input, n, IxIx, IxIy, IyIy);
00858   vil_math_image_sum<float, float, float>(IxIx, IyIy, tr);
00859   return tr;
00860 }
00861 
00862 vil_image_view<float>
00863 brip_vil_float_ops::harris(vil_image_view<float> const& IxIx,
00864                            vil_image_view<float> const& IxIy,
00865                            vil_image_view<float> const& IyIy,
00866                            double scale)
00867 {
00868   unsigned w = IxIx.ni(), h = IxIx.nj();
00869   float norm = 1e-3f; 
00870   vil_image_view<float> output;
00871   output.set_size(w, h);
00872   for (unsigned y = 0; y<h; y++)
00873     for (unsigned x = 0; x<w; x++)
00874     {
00875       float xx = IxIx(x,y), xy = IxIy(x,y), yy = IyIy(x,y);
00876       float det = xx*yy-xy*xy, trace = xx+yy;
00877       output(x,y) = float(det - scale*trace*trace)*norm;
00878     }
00879   return output;
00880 }
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892 
00893 
00894 
00895 
00896 vil_image_view<float>
00897 brip_vil_float_ops::sqrt_grad_singular_values(vil_image_view<float>& input,
00898                                               int n)
00899 {
00900   int N = (2*n+1)*(2*n+1);
00901   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
00902   vil_image_view<float> grad_x, grad_y, output;
00903   grad_x.set_size(w,h);
00904   grad_y.set_size(w,h);
00905   output.set_size(w,h);
00906   brip_vil_float_ops::gradient_3x3(input, grad_x, grad_y);
00907   vul_timer t;
00908   for (int y = n; y<h-n;y++)
00909     for (int x = n; x<w-n;x++)
00910     {
00911       float IxIx=0, IxIy=0, IyIy=0;
00912       for (int i = -n; i<=n; i++)
00913         for (int j = -n; j<=n; j++)
00914         {
00915           float gx = grad_x(x+i, y+j), gy = grad_y(x+i, y+j);
00916           IxIx += gx*gx;
00917           IxIy += gx*gy;
00918           IyIy += gy*gy;
00919         }
00920       float det = (IxIx*IyIy-IxIy*IxIy)/(float)N;
00921       output(x,y)=vcl_sqrt(vcl_fabs(det));
00922     }
00923   brip_vil_float_ops::fill_x_border(output, n, 0.0f);
00924   brip_vil_float_ops::fill_y_border(output, n, 0.0f);
00925 #ifdef DEBUG
00926   vcl_cout << "\nCompute sqrt(sigma0*sigma1) in" << t.real() << " msecs.\n";
00927 #endif
00928   return output;
00929 }
00930 
00931 vil_image_view<float> brip_vil_float_ops::
00932 max_scale_trace(vil_image_view<float> input,
00933                 float min_scale, float max_scale, float scale_inc)
00934 {
00935   unsigned ni = input.ni(), nj = input.nj();
00936   vil_image_view<float> tr_max, sc;
00937   tr_max.set_size(ni, nj);
00938   tr_max.fill(0.0f);
00939   sc.set_size(ni, nj);
00940   sc.fill(min_scale);
00941   for (float s = min_scale; s<=max_scale; s+=scale_inc)
00942   {
00943     vil_image_view<float> smooth = brip_vil_float_ops::gaussian(input, s);
00944     unsigned N = static_cast<unsigned>(2.0f*s);
00945     vil_image_view<float> tr =
00946       brip_vil_float_ops::trace_grad_matrix_NxN(smooth, N);
00947     for (unsigned r = 0; r<nj; ++r)
00948       for (unsigned c = 0; c<ni; ++c)
00949       {
00950         float trv = s*s*tr(c,r);
00951         if (trv>tr_max(c,r))
00952         {
00953           tr_max(c,r) = trv;
00954           sc(c,r) = s;
00955         }
00956       }
00957   }
00958   return sc;
00959 }
00960 
00961 
00962 vil_image_view<float> brip_vil_float_ops::
00963 max_scale_trace_value(vil_image_view<float> input,
00964                       float min_scale, float max_scale, float scale_inc)
00965 {
00966   unsigned ni = input.ni(), nj = input.nj();
00967   vil_image_view<float> tr_max, sc;
00968   tr_max.set_size(ni, nj);
00969   tr_max.fill(0.0f);
00970   sc.set_size(ni, nj);
00971   sc.fill(min_scale);
00972   for (float s = min_scale; s<=max_scale; s+=scale_inc)
00973   {
00974     vil_image_view<float> smooth = brip_vil_float_ops::gaussian(input, s);
00975     unsigned N = static_cast<unsigned>(2.0f*s);
00976     vil_image_view<float> tr =
00977       brip_vil_float_ops::trace_grad_matrix_NxN(smooth, N);
00978     for (unsigned r = 0; r<nj; ++r)
00979       for (unsigned c = 0; c<ni; ++c)
00980       {
00981         float trv = s*s*tr(c,r);
00982         if (trv>tr_max(c,r))
00983         {
00984           tr_max(c,r) = trv;
00985           sc(c,r) = s;
00986         }
00987       }
00988   }
00989   
00990   unsigned N = static_cast<unsigned>(5.0f*max_scale);
00991   unsigned njmax = nj-N;
00992   unsigned nimax = ni-N;
00993   for (unsigned r = 0; r<nj; ++r)
00994     for (unsigned c = 0; c<ni; ++c)
00995     {
00996       if (r <= N || r >= njmax || c <= N || c >= nimax)
00997         tr_max(c,r) = 0.0f;
00998     }
00999 
01000   
01001   float min_b,max_b;
01002   vil_math_value_range(tr_max,min_b,max_b);
01003   vcl_cout << "in trace max image min value: " << min_b << " max value: " << max_b << vcl_endl;
01004 
01005   vil_image_view<double> tr_normalized, tr_stretched;
01006   vil_convert_stretch_range(tr_max, tr_normalized, 0.0f, 1.0f);
01007   vil_convert_stretch_range(tr_max, tr_stretched, 0.0f, 255.0f);
01008   vil_image_view<float> tr_cast;
01009   vil_convert_cast(tr_stretched, tr_cast);
01010   vil_image_view<vxl_byte> tr_cast_byte;
01011   vil_convert_cast(tr_stretched, tr_cast_byte);
01012   vil_save_image_resource(vil_new_image_resource_of_view(tr_cast_byte), "D:\\projects\\vehicle_rec_on_models\\trace_image.png");
01013 
01014 #if 0 // commented out
01015   
01016   vil_image_view<float> modified_input = input;
01017   vil_image_view<float> const_image(ni, nj);
01018   const_image.fill(3.0f);
01019   for (unsigned r = 0; r<nj; ++r)
01020     for (unsigned c = 0; c<ni; ++c)
01021     {
01022       if (modified_input(c,r) < 120 || modified_input(c,r) > 95) = modified_input(c,r)*const_image(c,r);
01023     }
01024 
01025   vil_image_view<vxl_byte> mod_cast;
01026   vil_convert_cast(modified_input, mod_cast);
01027   vil_save_image_resource(vil_new_image_resource_of_view(mod_cast), "D:\\projects\\vehicle_rec_on_models\\modified_image.png");
01028 
01029   vil_image_view<float> tr_max2, sc2;
01030   tr_max2.set_size(ni, nj);
01031   tr_max2.fill(0.0f);
01032   sc2.set_size(ni, nj);
01033   sc2.fill(min_scale);
01034   for (float s = min_scale; s<=max_scale; s+=scale_inc)
01035   {
01036     vil_image_view<float> smooth = brip_vil_float_ops::gaussian(modified_input, s);
01037     unsigned N = static_cast<unsigned>(2.0f*s);
01038     vil_image_view<float> tr =
01039       brip_vil_float_ops::trace_grad_matrix_NxN(smooth, N);
01040     for (unsigned r = 0; r<nj; ++r)
01041       for (unsigned c = 0; c<ni; ++c)
01042       {
01043         float trv = s*s*tr(c,r);
01044         if (trv>tr_max2(c,r))
01045         {
01046           tr_max2(c,r) = trv;
01047           sc2(c,r) = s;
01048         }
01049       }
01050   }
01051   
01052   for (unsigned r = 0; r<nj; ++r)
01053     for (unsigned c = 0; c<ni; ++c)
01054     {
01055       if (r <= N || r >= njmax || c <= N || c >= nimax)
01056         tr_max2(c,r) = 0.0f;
01057     }
01058 
01059   vil_math_value_range(tr_max2,min_b,max_b);
01060   vcl_cout << "in trace max2 image min value: " << min_b << " max value: " << max_b << vcl_endl;
01061 
01062   
01063   vil_image_view<double> tr_normalized2;
01064   vil_convert_stretch_range(tr_max2, tr_normalized2, 0.0f, 1.0f);
01065 
01066   vil_image_view<double> difference_image = tr_normalized;
01067   for (unsigned r = 0; r<nj; ++r)
01068     for (unsigned c = 0; c<ni; ++c)
01069     {
01070       difference_image(c,r) = vcl_abs(difference_image(c,r) - tr_normalized2(c,r));
01071     }
01072   double min_bd, max_bd;
01073   vil_math_value_range(difference_image,min_bd,max_bd);
01074   vcl_cout << "in difference image of normalized trace images min value: " << min_bd << " max value: " << max_bd << vcl_endl;
01075   vil_image_view<vxl_byte> dif_cast;
01076   vil_convert_cast(difference_image, dif_cast);
01077   vil_save_image_resource(vil_new_image_resource_of_view(dif_cast), "D:\\projects\\vehicle_rec_on_models\\difference_image.png");
01078 
01079   vil_image_view<double> tr_stretched2;
01080   vil_convert_stretch_range(tr_max2, tr_stretched2, 0.0f, 255.0f);
01081   vil_image_view<float> tr_cast2;
01082   vil_convert_cast(tr_stretched2, tr_cast2);
01083   vil_image_view<vxl_byte> tr_cast2_byte;
01084   vil_convert_cast(tr_stretched2, tr_cast2_byte);
01085   vil_save_image_resource(vil_new_image_resource_of_view(tr_cast2_byte), "D:\\projects\\vehicle_rec_on_models\\trace_image2.png");
01086 
01087   return tr_cast2;
01088 #else // 0
01089   return tr_cast;
01090 #endif // 0
01091 }
01092 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 void
01103 brip_vil_float_ops::Lucas_KanadeMotion(vil_image_view<float> & current_frame,
01104                                        vil_image_view<float> & previous_frame,
01105                                        int n, double thresh,
01106                                        vil_image_view<float>& vx,
01107                                        vil_image_view<float>& vy)
01108 {
01109   int N = (2*n+1)*(2*n+1);
01110   int w = static_cast<int>(current_frame.ni()), h = static_cast<int>(current_frame.nj());
01111   vil_image_view<float> grad_x, grad_y, diff;
01112   grad_x.set_size(w,h);
01113   grad_y.set_size(w,h);
01114   
01115   brip_vil_float_ops::gradient_3x3(current_frame, grad_x, grad_y);
01116   diff = brip_vil_float_ops::difference(previous_frame, current_frame);
01117   vul_timer t;
01118   
01119   for (int y = n; y<h-n;y++)
01120     for (int x = n; x<w-n;x++)
01121     {
01122       float IxIx=0, IxIy=0, IyIy=0, IxIt=0, IyIt=0;
01123       for (int i = -n; i<=n; i++)
01124         for (int j = -n; j<=n; j++)
01125         {
01126           float gx = grad_x(x+i, y+j), gy = grad_y(x+i, y+j);
01127           float dt = diff(x+i, y+j);
01128           IxIx += gx*gx;
01129           IxIy += gx*gy;
01130           IyIy += gy*gy;
01131           IxIt += gx*dt;
01132           IyIt += gy*dt;
01133         }
01134       
01135       IxIx/=N;  IxIy/=N; IyIy/=N; IxIt/=N; IyIt/=N;
01136       float det = float(IxIx*IyIy-IxIy*IxIy);
01137       
01138       float dif = diff(x,y);
01139       float motion_factor = vcl_fabs(det*dif);
01140       if (motion_factor<thresh)
01141       {
01142         vx(x,y) = 0.0f;
01143         vy(x,y) = 0.0f;
01144         continue;
01145       }
01146       
01147       vx(x,y) = (IyIy*IxIt-IxIy*IyIt)/det;
01148       vy(x,y) = (-IxIy*IxIt + IxIx*IyIt)/det;
01149     }
01150   brip_vil_float_ops::fill_x_border(vx, n, 0.0f);
01151   brip_vil_float_ops::fill_y_border(vx, n, 0.0f);
01152   brip_vil_float_ops::fill_x_border(vy, n, 0.0f);
01153   brip_vil_float_ops::fill_y_border(vy, n, 0.0f);
01154 #ifdef DEBUG
01155   vcl_cout << "\nCompute Lucas-Kanade in " << t.real() << " msecs.\n";
01156 #endif
01157 }
01158 
01159 
01160 void brip_vil_float_ops::
01161 lucas_kanade_motion_on_view(vil_image_view<float> const& curr_frame,
01162                             vil_image_view<float> const& prev_frame,
01163                             const double thresh,
01164                             float& vx,
01165                             float& vy)
01166 {
01167   unsigned w = curr_frame.ni(), h = curr_frame.nj();
01168   unsigned N  = w*h;
01169   vil_image_view<float> grad_x, grad_y;
01170   grad_x.set_size(w,h);
01171   grad_y.set_size(w,h);
01172   
01173   brip_vil_float_ops::gradient_3x3(curr_frame, grad_x, grad_y);
01174   vil_image_view<float> diff =
01175     brip_vil_float_ops::difference(prev_frame, curr_frame);
01176 
01177   
01178   float IxIx=0.0f, IxIy=0.0f, IyIy=0.0f, IxIt=0.0f, IyIt=0.0f, dsum=0.0f;
01179   for (unsigned j = 0; j<h; j++)
01180     for (unsigned i = 0; i<w; i++)
01181     {
01182       float gx = grad_x(i, j), gy = grad_y(i, j);
01183       float dt = diff(i, j);
01184       dsum += dt*dt;
01185       IxIx += gx*gx;
01186       IxIy += gx*gy;
01187       IyIy += gy*gy;
01188       IxIt += gx*dt;
01189       IyIt += gy*dt;
01190     }
01191   
01192   IxIx/=(float)N;  IxIy/=(float)N; IyIy/=(float)N; IxIt/=(float)N; IyIt/=(float)N; dsum/=(float)N;
01193   float det = float(IxIx*IyIy-IxIy*IxIy);
01194   
01195   float dif = vcl_sqrt(dsum);
01196   float motion_factor = vcl_fabs(det*dif);
01197   if (motion_factor<thresh)
01198   {
01199     vx = 0.0f;
01200     vy = 0.0f;
01201     return;
01202   }
01203   
01204   vx = (IyIy*IxIt-IxIy*IyIt)/det;
01205   vy = (-IxIy*IxIt + IxIx*IyIt)/det;
01206 }
01207 
01208 
01209 
01210 
01211 
01212 
01213 void brip_vil_float_ops::
01214 velocity_by_correlation(vil_image_view<float> const& curr_image,
01215                         vil_image_view<float> const& prev_region,
01216                         const unsigned start_i, const unsigned end_i,
01217                         const unsigned start_j, const unsigned end_j,
01218                         const unsigned zero_i, const unsigned zero_j,
01219                         float& vx,
01220                         float& vy)
01221 {
01222   unsigned ni = prev_region.ni(), nj = prev_region.nj();
01223   float corr_max = -10.0f;
01224   float vx0 = static_cast<float>(zero_i);
01225   float vy0 = static_cast<float>(zero_j);
01226   float area = static_cast<float>(ni*nj);
01227   vx = 0; vy = 0;
01228   unsigned max_i = start_i, max_j = start_j;
01229   for (unsigned j = start_j; j<=end_j; ++j)
01230     for (unsigned i = start_i; i<=end_i; ++i)
01231     {
01232       float si1 = 0, si2 = 0, si1i1 = 0, si2i2 = 0, si1i2 = 0;
01233       
01234       for (unsigned r = 0; r<nj; ++r)
01235         for (unsigned c = 0; c<ni; ++c)
01236         {
01237           float I1 = prev_region(c, r);
01238           float I2 = curr_image(i+c, j+r);
01239           si1 += I1; si2 += I2;
01240           si1i1 += I1*I1;
01241           si2i2 += I2*I2;
01242           si1i2 += I1*I2;
01243         }
01244       float corr = cross_corr(area, si1, si2, si1i1, si2i2,si1i2, 1.0f);
01245       if (corr>corr_max)
01246       {
01247         corr_max = corr;
01248         max_i = i; max_j = j;
01249       }
01250 #if 0
01251       float di = i-vx0, dj = j-vy0;
01252       vcl_cout <<  di << '\t' << dj << '\t' << corr << '\n';
01253 #endif
01254     }
01255   
01256   vx = static_cast<float>(max_i)- vx0;
01257   vy = static_cast<float>(max_j) - vy0;
01258   
01259 }
01260 
01261 
01262 
01263 
01264 
01265 
01266 
01267 
01268 
01269 
01270 
01271 
01272 
01273 int brip_vil_float_ops::
01274 Horn_SchunckMotion(vil_image_view<float> const& current_frame,
01275                    vil_image_view<float> const& previous_frame,
01276                    vil_image_view<float>& vx,
01277                    vil_image_view<float>& vy,
01278                    const float alpha_coef,
01279                    const int no_of_iterations)
01280 {
01281   
01282   if (vil_image_view_deep_equality (previous_frame, current_frame ) )
01283   {
01284     vcl_cout<<"Images are same";
01285     return -1;
01286   }
01287 
01288   
01289   unsigned w = current_frame.ni(), h = current_frame.nj();
01290 
01291   vil_image_view<float> grad_x, grad_y, diff;
01292 
01293   vil_image_view<float> temp1;
01294   vil_image_view<float> temp2;
01295 
01296   vil_image_view<float> emptyimg;
01297 
01298   
01299 
01300   grad_x.set_size(w,h);
01301   grad_y.set_size(w,h);
01302   diff.set_size(w,h);
01303   temp1.set_size(w,h);
01304   temp2.set_size(w,h);
01305 
01306   emptyimg.set_size(w,h);
01307 
01308   temp1.fill(0.0);
01309   temp2.fill(0.0);
01310 
01311   
01312   for (unsigned y = 0; y<h; y++)
01313     for (unsigned x = 0; x<w; x++)
01314     {
01315       vx(x,y)=0.0f;
01316       vy(x,y)=0.0f;
01317       diff (x,y)=0.0f;
01318       grad_x (x, y)= 0.0f;
01319       grad_y (x, y)= 0.0f;
01320 
01321       emptyimg (x, y) = 0.0f;
01322     }
01323 
01324   
01325   if ( (vil_image_view_deep_equality (emptyimg, current_frame )) || (vil_image_view_deep_equality(emptyimg, previous_frame)))
01326   {
01327     vcl_cout<<"Image is empty";
01328     return -2;
01329   }
01330 
01331   
01332   brip_vil_float_ops::gradient_3x3 (current_frame , grad_x , grad_y);
01333   brip_vil_float_ops::gradient_3x3 (previous_frame , temp1 , temp2);
01334 
01335   
01336   vil_math_add_image_fraction(grad_x, 0.5, temp1, 0.5);
01337   vil_math_add_image_fraction(grad_y, 0.5, temp2, 0.5);
01338   if ( (vil_image_view_deep_equality(emptyimg, grad_x)) ||
01339        (vil_image_view_deep_equality(emptyimg, grad_y)) )
01340     {
01341       vcl_cout<<"Gradient Image is empty";
01342       return -2;
01343     }
01344 
01345   temp1.fill(0.0);
01346   temp2.fill(0.0);
01347 
01348   
01349   temp1 = brip_vil_float_ops::average_NxN(previous_frame, 3);
01350   temp2 = brip_vil_float_ops::average_NxN(current_frame, 3);
01351   if (vil_image_view_deep_equality(emptyimg, temp1) ||
01352       vil_image_view_deep_equality(emptyimg, temp2))
01353     {
01354       vcl_cout<<"Averaged Image is empty";
01355       return -2;
01356     }
01357 
01358   
01359   
01360   diff = brip_vil_float_ops::difference(temp1 , temp2);
01361   if (vil_image_view_deep_equality(emptyimg, diff) )
01362   {
01363     vcl_cout<<"Difference Image is empty";
01364     return -2;
01365   }
01366 
01367   temp1.fill(0.0);
01368   temp2.fill(0.0);
01369   
01370 #ifdef DEBUG
01371   vul_timer t;
01372 #endif
01373   for (int i=0;i<no_of_iterations;i++)
01374   {
01375     
01376     
01377     temp1 = brip_vil_float_ops::average_NxN (vx,  3);
01378     temp2 = brip_vil_float_ops::average_NxN (vy,  3);
01379     for (unsigned y = 1; y+1<h; ++y)
01380       for (unsigned x = 1; x+1<w; ++x)
01381       {
01382         float tempx = temp1(x,y);
01383         float tempy = temp2(x,y);
01384 
01385         float gx = grad_x(x, y), gy = grad_y(x, y);
01386 
01387         float dt = diff(x, y);
01388         
01389         
01390         
01391         
01392         float term =
01393           ( (gx * tempx) + (gy * tempy) + dt )/ (alpha_coef + gx*gx + gy*gy);
01394 
01395         
01396         
01397         vx(x,y) = tempx - (gx *  term);
01398         vy(x,y) = tempy - (gy *  term);
01399       }
01400 
01401 #ifdef DEBUG
01402     vcl_cout << "Iteration No " << i << '\n';
01403 #endif
01404     brip_vil_float_ops::fill_x_border(vx, 1, 0.0f);
01405     brip_vil_float_ops::fill_y_border(vx, 1, 0.0f);
01406     brip_vil_float_ops::fill_x_border(vy, 1, 0.0f);
01407     brip_vil_float_ops::fill_y_border(vy, 1, 0.0f);
01408   }
01409 #ifdef DEBUG
01410   vcl_cout << "\nCompute Horn-Schunck iteration in " << t.real() << " msecs.\n";
01411 #endif
01412   return 0;
01413 }
01414 
01415 void brip_vil_float_ops::fill_x_border(vil_image_view<float> & image,
01416                                        unsigned w, float value)
01417 {
01418   unsigned width = image.ni(), height = image.nj();
01419   if (2*w>width)
01420   {
01421     vcl_cout << "In brip_vil_float_ops::fill_x_border(..) - 2xborder exceeds image width\n";
01422     return;
01423   }
01424   for (unsigned y = 0; y<height; y++)
01425     for (unsigned x = 0; x<w; x++)
01426       image(x, y) = value;
01427 
01428   for (unsigned y = 0; y<height; y++)
01429     for (unsigned x = width-w; x<width; x++)
01430       image(x, y) = value;
01431 }
01432 
01433 void brip_vil_float_ops::fill_y_border(vil_image_view<float> & image,
01434                                        unsigned h, float value)
01435 {
01436   unsigned width = image.ni(), height = image.nj();
01437   if (2*h>height)
01438   {
01439     vcl_cout << "In brip_vil_float_ops::fill_y_border(..) - 2xborder exceeds image height\n";
01440     return;
01441   }
01442   for (unsigned y = 0; y<h; y++)
01443     for (unsigned x = 0; x<width; x++)
01444       image(x, y) = value;
01445 
01446   for (unsigned y = height-h; y<height; y++)
01447     for (unsigned x = 0; x<width; x++)
01448       image(x, y) = value;
01449 }
01450 
01451 vil_image_view<vxl_byte>
01452 brip_vil_float_ops::convert_to_byte(vil_image_view<float> const& image)
01453 {
01454   
01455   float min_val = vnl_numeric_traits<float>::maxval;
01456   float max_val = -min_val;
01457   unsigned w = image.ni(), h = image.nj();
01458   vil_image_view<vxl_byte> output;
01459   output.set_size(w,h);
01460   for (unsigned y = 0; y<h; y++)
01461     for (unsigned x = 0; x<w; x++)
01462     {
01463       min_val = vnl_math_min(min_val, image(x,y));
01464       max_val = vnl_math_max(max_val, image(x,y));
01465     }
01466   float range = max_val-min_val;
01467   if (range == 0.f)
01468     range = 1.f;
01469   else
01470     range = 255.f/range;
01471   for (unsigned y = 0; y<h; y++)
01472     for (unsigned x = 0; x<w; x++)
01473     {
01474       float v = (image(x,y)-min_val)*range;
01475       output(x,y) = (unsigned char)v;
01476     }
01477   return output;
01478 }
01479 
01480 
01481 
01482 vil_image_view<vxl_byte>
01483 brip_vil_float_ops::convert_to_byte(vil_image_view<float> const& image,
01484                                     float min_val, float max_val)
01485 {
01486   unsigned w = image.ni(), h = image.nj();
01487   vil_image_view<vxl_byte> output;
01488   output.set_size(w,h);
01489   float range = max_val-min_val;
01490   if (range == 0.f)
01491     range = 1.f;
01492   else
01493     range = 255.f/range;
01494   for (unsigned y = 0; y<h; y++)
01495     for (unsigned x = 0; x<w; x++)
01496     {
01497       float v = (image(x,y)-min_val)*range;
01498       if (v>255)
01499         v=255;
01500       if (v<0)
01501         v=0;
01502       output(x,y) = (unsigned char)v;
01503     }
01504 
01505   return output;
01506 }
01507 
01508 vil_image_view<vxl_byte> brip_vil_float_ops::
01509 convert_to_byte(vil_image_view<vxl_uint_16> const& image,
01510                 vxl_uint_16 min_val, vxl_uint_16 max_val)
01511 {
01512   unsigned ni = image.ni(), nj = image.nj();
01513   vil_image_view<vxl_byte> output;
01514   output.set_size(ni, nj);
01515   float range = static_cast<float>(max_val-min_val);
01516   if (!range)
01517     range = 1;
01518   else
01519     range = 255/range;
01520   for (unsigned r = 0; r<nj; r++)
01521     for (unsigned c = 0; c<ni; c++)
01522     {
01523       float v = float(image(c, r)-min_val)*range;
01524       if (v>255)
01525         v=255;
01526       if (v<0)
01527         v=0;
01528       output(c, r) = static_cast<unsigned char>(v);
01529     }
01530   return output;
01531 }
01532 
01533 
01534 vil_image_view<vxl_byte>
01535 brip_vil_float_ops::convert_to_byte(vil_image_resource_sptr const& image)
01536 {
01537   return brip_vil_float_ops::convert_to_grey(*image);
01538 }
01539 
01540 vil_image_view<vxl_uint_16>
01541 brip_vil_float_ops::convert_to_short(vil_image_view<float> const& image,
01542                                      float min_val, float max_val)
01543 {
01544   unsigned w = image.ni(), h = image.nj();
01545   float max_short = 65355.f;
01546   vil_image_view<vxl_uint_16> output;
01547   output.set_size(w,h);
01548   float range = max_val-min_val;
01549   if (!range)
01550     range = 1;
01551   else
01552     range = max_short/range;
01553   for (unsigned y = 0; y<h; y++)
01554     for (unsigned x = 0; x<w; x++)
01555     {
01556       float v = (image(x,y)-min_val)*range;
01557       if (v>max_short)
01558         v=max_short;
01559       if (v<0)
01560         v=0;
01561       output(x,y) = (unsigned short)v;
01562     }
01563   return output;
01564 }
01565 
01566 
01567 
01568 vil_image_view<vxl_uint_16>
01569 brip_vil_float_ops::convert_to_short(vil_image_view<float> const& image)
01570 {
01571   float minv = vnl_numeric_traits<float>::maxval;
01572   float maxv = -minv;
01573   unsigned ni = image.ni(), nj = image.nj();
01574   for (unsigned j = 0; j<nj; ++j)
01575     for (unsigned i = 0; i<ni; ++i)
01576     {
01577       float v = image(i,j);
01578       if (v<minv)
01579         minv = v;
01580       if (v>maxv)
01581         maxv = v;
01582     }
01583   return brip_vil_float_ops::convert_to_short(image, minv, maxv);
01584 }
01585 
01586 vil_image_view<vxl_uint_16>
01587 brip_vil_float_ops::convert_to_short(vil_image_resource_sptr const& image)
01588 {
01589   
01590   if (image->nplanes()==1 &&image->pixel_format()==VIL_PIXEL_FORMAT_FLOAT)
01591   {
01592     vil_image_view<float> temp = image->get_view();
01593     float vmin=0, vmax= 65355;
01594     vil_math_value_range<float>(temp, vmin, vmax);
01595     return brip_vil_float_ops::convert_to_short(temp, vmin, vmax);
01596   }
01597 
01598   
01599   if (image->nplanes()==1&&image->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
01600   {
01601     vil_image_view<unsigned char > temp = image->get_view();
01602     vil_image_view<unsigned short> short_image;
01603     unsigned width = temp.ni(), height = temp.nj();
01604     short_image.set_size(width, height);
01605     for (unsigned y = 0; y<height; y++)
01606       for (unsigned x = 0; x<width; x++)
01607         short_image(x,y) = static_cast<unsigned short>(temp(x,y));
01608     return temp;
01609   }
01610 
01611   
01612   if (image->nplanes()==1&&image->pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
01613   {
01614     vil_image_view<unsigned short > temp = image->get_view();
01615     return temp;
01616   }
01617 
01618   
01619   
01620   if (image->nplanes()==3&&image->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
01621   {
01622     vil_image_view<vxl_byte> color_image = image->get_view();
01623     unsigned width = color_image.ni(), height = color_image.nj();
01624     
01625     vil_image_view<unsigned short> short_image;
01626     short_image.set_size(width, height);
01627     for (unsigned y = 0; y<height; y++)
01628       for (unsigned x = 0; x<width; x++)
01629       {
01630         double v = color_image(x,y,0)+color_image(x,y,1)+color_image(x,y,2);
01631         v/=3.0;
01632         short_image(x,y) = static_cast<unsigned short>(v);
01633       }
01634     return short_image;
01635   }
01636 
01637   
01638   
01639   if (image->nplanes()==4&&image->pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
01640   {
01641     vil_image_view<unsigned short > mband_image = image->get_view();
01642     unsigned width = mband_image.ni(), height = mband_image.nj();
01643     
01644     vil_image_view<unsigned short> short_image;
01645     short_image.set_size(width, height);
01646     for (unsigned y = 0; y<height; y++)
01647       for (unsigned x = 0; x<width; x++)
01648       {
01649         unsigned short v = 0;
01650         for (unsigned p = 0; p<4; ++p)
01651           v += mband_image(x, y, p);
01652         v/=4;
01653         short_image(x,y) = v;
01654       }
01655     return short_image;
01656   }
01657 
01658   
01659   return vil_image_view<vxl_uint_16>();
01660 }
01661 
01662 vil_image_view<float>
01663 brip_vil_float_ops::convert_to_float(vil_image_view<vxl_byte> const& image)
01664 {
01665   vil_image_view<float> output;
01666   unsigned ni = image.ni(), nj = image.nj(), np = image.nplanes();
01667   output.set_size(ni,nj, np);
01668   for (unsigned j = 0; j<nj; j++)
01669     for (unsigned i = 0; i<ni; i++)
01670       for (unsigned p = 0; p<np; ++p)
01671         output(i,j,p) = (float)image(i,j,p);
01672   return output;
01673 }
01674 
01675 vil_image_view<float>
01676 brip_vil_float_ops::convert_to_float(vil_image_view<vxl_uint_16> const& image)
01677 {
01678   vil_image_view<float> output;
01679   unsigned w = image.ni(), h = image.nj();
01680   output.set_size(w,h);
01681   for (unsigned y = 0; y<h; y++)
01682     for (unsigned x = 0; x<w; x++)
01683       output(x,y) = (float)image(x,y);
01684   return output;
01685 }
01686 
01687 vil_image_view<bool>
01688 brip_vil_float_ops::convert_to_bool(vil_image_view<vxl_byte> const& image)
01689 {
01690   vil_image_view<bool> output;
01691   unsigned w = image.ni(), h = image.nj();
01692   output.set_size(w,h);
01693   for (unsigned y = 0; y<h; y++)
01694     for (unsigned x = 0; x<w; x++)
01695       if (image(x,y) > 128)
01696         output(x,y)=true;
01697       else
01698         output(x,y)=false;
01699   return output;
01700 }
01701 
01702 vil_image_view<float>
01703 brip_vil_float_ops::convert_to_float(vil_image_view<vil_rgb<vxl_byte> > const& image)
01704 {
01705   vil_image_view<float> output;
01706   unsigned w = image.ni(), h = image.nj();
01707   output.set_size(w,h);
01708   for (unsigned y = 0; y<h; y++)
01709     for (unsigned x = 0; x<w; x++)
01710     {
01711       vil_rgb<vxl_byte> rgb = image(x,y);
01712       output(x,y) = (float)rgb.grey();
01713     }
01714   return output;
01715 }
01716 
01717 void brip_vil_float_ops::rgb_to_ihs(vil_rgb<vxl_byte> const& rgb,
01718                                     float& i, float& h, float& s)
01719 {
01720   float r,g,b;
01721   r=rgb.R();
01722   g=rgb.G();
01723   b=rgb.B();
01724 
01725   float maxval = vnl_math_max(r,vnl_math_max(g,b));
01726   float minval = vnl_math_min(r,vnl_math_min(g,b));
01727 
01728   float delta = maxval - minval;
01729   i = maxval;
01730   if (maxval == 0)
01731     s = 0;
01732   else
01733     s = delta / maxval;
01734 
01735   if (s== 0)
01736     h = 0;                   
01737 
01738   if (r== maxval)
01739     h = (g - b) / delta ;    
01740   if (g == maxval)
01741     h = 2 + (b - r)/delta ;  
01742   if (b == maxval)
01743     h = 4 + (r - g) / delta; 
01744   h = h * 60;                
01745   if (h < 0)
01746     h = h + 360 ;            
01747   if (h >= 360)
01748     h = h - 360;             
01749 
01750   h = (vxl_byte)(h * (255.0 / 360.0));
01751   s = (vxl_byte)(s * 255.0);
01752 }
01753 
01754 void brip_vil_float_ops::ihs_to_rgb(vil_rgb<vxl_byte> & rgb,
01755                                     const float i, const float h, const float s)
01756 {
01757   
01758   float R = 0.0f;
01759   float G = 0.0f;
01760   float B = 0.0f;
01761 
01762   if (s == 0) {
01763     R=i;
01764     G=i;
01765     B=i;
01766   }
01767   else if (s > 0.0)
01768   {
01769     float ss = s, hh = h;
01770     ss *= 1.f / 255.f;
01771     hh *= 6.f / 255.f;
01772 
01773     float J = vcl_floor(hh);
01774     float F = hh - J;
01775     float P =( i * (1 - ss));
01776     float Q = (i * (1 - (ss * F)));
01777     float T = (i * (1 - (ss * (1 - F))));
01778 
01779     if (J == 0) { R=i; G=T; B=P; }
01780     if (J == 1) { R=Q; G=i; B=P; }
01781     if (J == 2) { R=P; G=i; B=T; }
01782     if (J == 3) { R=P; G=Q; B=i; }
01783     if (J == 4) { R=T; G=P; B=i; }
01784     if (J == 5) { R=i; G=P; B=Q; }
01785   }
01786   rgb.r = (vxl_byte)R;
01787   rgb.g = (vxl_byte)G;
01788   rgb.b = (vxl_byte)B;
01789 }
01790 
01791 void brip_vil_float_ops::
01792 convert_to_IHS(vil_image_view<vil_rgb<vxl_byte> > const& image,
01793                vil_image_view<float>& I,
01794                vil_image_view<float>& H,
01795                vil_image_view<float>& S)
01796 {
01797   unsigned w = image.ni(), h = image.nj();
01798   I.set_size(w,h);
01799   H.set_size(w,h);
01800   S.set_size(w,h);
01801   for (unsigned r = 0; r < h; r++)
01802     for (unsigned c = 0; c < w; c++)
01803     {
01804       float in, hue, sat;
01805       rgb_to_ihs(image(c,r), in, hue, sat);
01806       I(c,r) = in;
01807       H(c,r) = hue;
01808       S(c,r) = sat;
01809     }
01810 }
01811 
01812 void brip_vil_float_ops::
01813 convert_to_IHS(vil_image_view<vxl_byte> const& image,
01814                vil_image_view<float>& I,
01815                vil_image_view<float>& H,
01816                vil_image_view<float>& S)
01817 {
01818   unsigned w = image.ni(), h = image.nj();
01819   I.set_size(w,h);
01820   H.set_size(w,h);
01821   S.set_size(w,h);
01822   for (unsigned r = 0; r < h; r++)
01823     for (unsigned c = 0; c < w; c++)
01824     {
01825       float in, hue, sat;
01826       vil_rgb<vxl_byte> imint(image(c,r,0),image(c,r,1),image(c,r,2));
01827       rgb_to_ihs(imint, in, hue, sat);
01828       I(c,r) = in;
01829       H(c,r) = hue;
01830       S(c,r) = sat;
01831     }
01832 }
01833 
01834 #if 0 // commented out
01835 void brip_vil_float_ops::
01836 display_IHS_as_RGB(vil_image_view<float> const& I,
01837                    vil_image_view<float> const& H,
01838                    vil_image_view<float> const& S,
01839                    vil_image_view<vil_rgb<vxl_byte> >& image)
01840 {
01841   unsigned w = I.ni(), h = I.nj();
01842   image.set_size(w,h);
01843   float s = 255.0f/360.0f;
01844   for (unsigned r = 0; r < h; r++)
01845     for (unsigned c = 0; c < w; c++)
01846     {
01847       float in = I(c,r);
01848       float hue = s * H(c,r);
01849       float sat = S(c,r);
01850       if (in<0) in = 0;
01851       if (sat<0) sat = 0;
01852       if (hue<0) hue = 0;
01853       if (in>255) in = 255;
01854       if (hue>255) hue = 255;
01855       if (sat>255) sat = 255;
01856       image(c,r).r = (vxl_byte)in;
01857       image(c,r).g = (vxl_byte)hue;
01858       image(c,r).b = (vxl_byte)sat;
01859     }
01860 }
01861 #endif // 0
01862 
01863 
01864 void brip_vil_float_ops::
01865 display_IHS_as_RGB(vil_image_view<float> const& I,
01866                    vil_image_view<float> const& H,
01867                    vil_image_view<float> const& S,
01868                    vil_image_view<vil_rgb<vxl_byte> >& image)
01869 {
01870   unsigned w = I.ni(), h = I.nj();
01871   image.set_size(w,h);
01872 
01873   const float deg_to_rad = float(vnl_math::pi_over_180);
01874   for (unsigned r = 0; r < h; r++)
01875     for (unsigned c = 0; c < w; c++)
01876     {
01877       float hue = H(c,r);
01878       float sat = 2.f*S(c,r);
01879       if (sat<0)
01880         sat = 0.f;
01881       if (sat>255)
01882         sat = 255.f;
01883       float ang = deg_to_rad*hue;
01884       float cs = vcl_cos(ang), si = vcl_fabs(vcl_sin(ang));
01885       float red=0.0f, blue=0.0f;
01886       float green = si*sat;
01887       if (cs>=0)
01888         red = cs*sat;
01889       else
01890         blue = sat*(-cs);
01891       image(c,r).r = (vxl_byte)red;
01892       image(c,r).g = (vxl_byte)green;
01893       image(c,r).b = (vxl_byte)blue;
01894     }
01895 }
01896 
01897 vil_image_view<vil_rgb<vxl_byte> > brip_vil_float_ops::
01898 combine_color_planes(vil_image_view<vxl_byte> const& R,
01899                      vil_image_view<vxl_byte> const& G,
01900                      vil_image_view<vxl_byte> const& B)
01901 {
01902   unsigned w = R.ni(), h = R.nj();
01903   vil_image_view<vil_rgb<vxl_byte> > image(w,h);
01904   for (unsigned r = 0; r < h; r++)
01905     for (unsigned c = 0; c < w; c++)
01906     {
01907       image(c,r).r = R(c,r);
01908       image(c,r).g = G(c,r);
01909       image(c,r).b = B(c,r);
01910     }
01911   return image;
01912 }
01913 
01914 vil_image_view<vil_rgb<vxl_byte> >
01915 brip_vil_float_ops::combine_color_planes(vil_image_resource_sptr const& R,
01916                                          vil_image_resource_sptr const& G,
01917                                          vil_image_resource_sptr const& B)
01918 {
01919   vil_image_view<vil_rgb<vxl_byte> > view(0,0);
01920   if (!R||!G||!B)
01921     return view; 
01922   
01923   vbl_bounding_box<unsigned int, 2> b;
01924   unsigned int r_ni = R->ni(), r_nj = R->nj();
01925   unsigned int g_ni = G->ni(), g_nj = G->nj();
01926   unsigned int b_ni = B->ni(), b_nj = B->nj();
01927   b.update(r_ni, r_nj);
01928   b.update(g_ni, g_nj);
01929   b.update(b_ni, b_nj);
01930   unsigned int n_i = b.xmax(), n_j = b.ymax();
01931   view.set_size(n_i, n_j);
01932   vil_rgb<vxl_byte> zero(0, 0, 0);
01933   vil_image_view<float>    fR = brip_vil_float_ops::convert_to_float(R);
01934   vil_image_view<vxl_byte> cR = brip_vil_float_ops::convert_to_byte(fR);
01935   vil_image_view<float>    fG = brip_vil_float_ops::convert_to_float(G);
01936   vil_image_view<vxl_byte> cG = brip_vil_float_ops::convert_to_byte(fG);
01937   vil_image_view<float>    fB = brip_vil_float_ops::convert_to_float(B);
01938   vil_image_view<vxl_byte> cB = brip_vil_float_ops::convert_to_byte(fB);
01939   for (vxl_uint_16 j = 0; j<n_j; ++j)
01940     for (vxl_uint_16 i = 0; i<n_i; ++i)
01941     {
01942       vil_rgb<vxl_byte> v = zero;
01943       if (i<r_ni&&j<r_nj)
01944         v.r = cR(i,j);
01945       if (i<g_ni&&j<g_nj)
01946         v.g= cG(i,j);
01947       if (i<b_ni&&j<b_nj)
01948         v.b= cB(i,j);
01949       view(i,j)=v;
01950     }
01951   return view;
01952 }
01953 
01954 vil_image_view<float>
01955 brip_vil_float_ops::convert_to_float(vil_image_resource const& image)
01956 {
01957   vil_image_view<float> fimg;
01958   vil_pixel_format fmt = image.pixel_format();
01959   if (vil_pixel_format_num_components(image.pixel_format())==1)
01960   {
01961     if (fmt==VIL_PIXEL_FORMAT_UINT_16)
01962     {
01963       vil_image_view<unsigned short> temp=image.get_view();
01964       fimg = brip_vil_float_ops::convert_to_float(temp);
01965     }
01966     else if (fmt==VIL_PIXEL_FORMAT_BYTE)
01967     {
01968       vil_image_view<unsigned char> temp=image.get_view();
01969       fimg = brip_vil_float_ops::convert_to_float(temp);
01970     }
01971     else if (fmt==VIL_PIXEL_FORMAT_FLOAT)
01972       return image.get_view();
01973   }
01974   else if (vil_pixel_format_num_components(fmt)==3)
01975   {
01976     vil_image_view<vil_rgb<vxl_byte> > temp= image.get_view();
01977     fimg = brip_vil_float_ops::convert_to_float(temp);
01978   }
01979   else
01980   {
01981     vcl_cout << "In brip_vil_float_ops::convert_to_float - input not color or grey\n";
01982     return vil_image_view<float>();
01983   }
01984   return fimg;
01985 }
01986 
01987 
01988 
01989 vil_image_view<vxl_byte>
01990 brip_vil_float_ops::convert_to_grey(vil_image_resource const& image)
01991 {
01992   
01993   if (image.nplanes()==1 &&image.pixel_format()==VIL_PIXEL_FORMAT_FLOAT)
01994   {
01995     vil_image_view<float> temp = image.get_view();
01996     float vmin=0, vmax=255;
01997     vil_math_value_range<float>(temp, vmin, vmax);
01998     return brip_vil_float_ops::convert_to_byte(temp, vmin, vmax);
01999   }
02000   if (image.nplanes()==1 &&image.pixel_format()==VIL_PIXEL_FORMAT_BOOL)
02001   {
02002     vil_image_view<bool> temp = image.get_view();
02003     unsigned nj = temp.nj(), ni = temp.ni();
02004     vil_image_view<unsigned char> out(ni, nj);
02005     out.fill(0);
02006     for (unsigned j = 0; j<nj; ++j)
02007       for (unsigned i = 0; i<ni; ++i)
02008         if (temp(i,j)) out(i,j) = 255;
02009     return out;
02010   }
02011 
02012   
02013   
02014   if (image.nplanes()==1&&image.pixel_format()==VIL_PIXEL_FORMAT_BYTE)
02015   {
02016     vil_image_view<unsigned char > temp = image.get_view();
02017     return temp;
02018   }
02019 
02020   if (image.nplanes()==1&&image.pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
02021   {
02022     vil_image_view<unsigned short > temp = image.get_view();
02023     unsigned short vmin=0, vmax=255;
02024     vil_math_value_range<unsigned short>(temp, vmin, vmax);
02025     return brip_vil_float_ops::convert_to_byte(temp, vmin, vmax);
02026   }
02027   
02028   
02029   if (image.nplanes()==3&&image.pixel_format()==VIL_PIXEL_FORMAT_BYTE)
02030   {
02031     vil_image_view<vil_rgb<vxl_byte> > color_image = image.get_view();
02032     unsigned width = color_image.ni(), height = color_image.nj();
02033     
02034     vil_image_view<unsigned char> grey_image;
02035     grey_image.set_size(width, height);
02036     for (unsigned y = 0; y<height; y++)
02037       for (unsigned x = 0; x<width; x++)
02038         grey_image(x,y) = color_image(x,y).grey();
02039     return grey_image;
02040   }
02041   if (image.nplanes()==3&&image.pixel_format()==VIL_PIXEL_FORMAT_FLOAT)
02042   {
02043     vil_image_view<float> color_image = image.get_view();
02044     unsigned width = color_image.ni(), height = color_image.nj();
02045     
02046     vil_image_view<float> grey_image_f;
02047     grey_image_f.set_size(width, height);
02048     for (unsigned y = 0; y<height; y++)
02049       for (unsigned x = 0; x<width; x++) {
02050         float v = 0;
02051         for (unsigned p = 0; p<3; ++p)
02052           v += color_image(x,y,p);
02053         grey_image_f(x,y) = v/3.0f;
02054       }
02055     float vmin=0, vmax=255;
02056     vil_math_value_range<float>(grey_image_f, vmin, vmax);
02057     return brip_vil_float_ops::convert_to_byte(grey_image_f, vmin, vmax);
02058   }
02059   
02060   return vil_image_view<vxl_byte>();
02061 }
02062 
02063 
02064 
02065 
02066 
02067 
02068 
02069 
02070 
02071 
02072 
02073 
02074 
02075 vbl_array_2d<float> brip_vil_float_ops::load_kernel(vcl_string const& file)
02076 {
02077   vcl_ifstream instr(file.c_str(), vcl_ios::in);
02078   if (!instr)
02079   {
02080     vcl_cout << "In brip_vil_float_ops::load_kernel - failed to load kernel\n";
02081     return vbl_array_2d<float>(0,0);
02082   }
02083   unsigned n;
02084   float scale;
02085   float v =0.0f;
02086   instr >> n;
02087   instr >> scale;
02088   unsigned N = 2*n+1;
02089   vbl_array_2d<float> output(N, N);
02090   for (unsigned y = 0; y<N; y++)
02091     for (unsigned x = 0; x<N; x++)
02092     {
02093       instr >> v;
02094       output.put(x, y, v/scale);
02095     }
02096 #ifdef DEBUG
02097   vcl_cout << "The Kernel\n";
02098   for (unsigned y = 0; y<N; y++)
02099   {
02100     for (unsigned x = 0; x<N; x++)
02101       vcl_cout << ' ' <<  output[x][y];
02102     vcl_cout << '\n';
02103   }
02104 #endif
02105   return output;
02106 }
02107 
02108 static void insert_image(vil_image_view<float> const& image, int col,
02109                          vnl_matrix<float> & I)
02110 {
02111   unsigned width = image.ni(), height = image.nj(), row=0;
02112   for (unsigned y =0; y<height; y++)
02113     for (unsigned x = 0; x<width; x++, row++)
02114       I.put(row, col, image(x,y));
02115 }
02116 
02117 void brip_vil_float_ops::
02118 basis_images(vcl_vector<vil_image_view<float> > const& input_images,
02119              vcl_vector<vil_image_view<float> >& basis)
02120 {
02121   basis.clear();
02122   unsigned n_images = input_images.size();
02123   if (!n_images)
02124   {
02125     vcl_cout << "In brip_vil_float_ops::basis_images(.) - no input images\n";
02126     return;
02127   }
02128   unsigned width = input_images[0].ni(), height = input_images[0].nj();
02129   unsigned npix = width*height;
02130 
02131   
02132   vnl_matrix<float> I(npix, n_images, 0.f);
02133   for (unsigned i = 0; i<n_images; i++)
02134     insert_image(input_images[i], i, I);
02135 
02136   
02137 #ifdef DEBUG
02138   vcl_cout << "Computing Singular values of a " <<  npix << " by "
02139            << n_images << " matrix\n";
02140   vul_timer t;
02141 #endif
02142   vnl_svd<float> svd(I);
02143 #ifdef DEBUG
02144   vcl_cout << "SVD Took " << t.real() << " msecs\n"
02145            << "Eigenvalues:\n";
02146   for (unsigned i = 0; i<n_images; i++)
02147     vcl_cout << svd.W(i) << '\n';
02148 #endif
02149   
02150   unsigned rank = svd.rank();
02151   if (!rank)
02152   {
02153     vcl_cout << "In brip_vil_float_ops::basis_images(.) - I has zero rank\n";
02154     return;
02155   }
02156   vnl_matrix<float> U = svd.U();
02157   
02158   unsigned rows = U.rows();
02159   for (unsigned k = 0; k<rank; k++)
02160   {
02161     vil_image_view<float> out(width, height);
02162     unsigned x =0, y = 0;
02163     for (unsigned r = 0; r<rows; r++)
02164     {
02165       out(x, y) = U(r,k);
02166       x++;
02167       if (x>=width)
02168       {
02169         y++;
02170         x=0;
02171       }
02172       if (y>=width)
02173       {
02174         vcl_cout<<"In brip_vil_float_ops::basis_images(.) - shouldn't happen\n";
02175         return;
02176       }
02177     }
02178     basis.push_back(out);
02179   }
02180 }
02181 
02182 
02183 
02184 
02185 
02186 
02187 
02188 
02189 
02190 
02191 
02192 
02193 
02194 
02195 
02196 
02197 
02198 
02199 
02200 
02201 
02202 
02203 
02204 
02205 
02206 
02207 
02208 
02209 
02210 
02211 bool brip_vil_float_ops::fft_1d(int dir, int m, double* x, double* y)
02212 {
02213   long nn,i,i1,j,k,i2,l,l1,l2;
02214   double c1,c2,tx,ty,t1,t2,u1,u2,z;
02215 
02216   
02217   nn = 1;
02218   for (i=0;i<m;i++)
02219     nn *= 2;
02220 
02221   
02222   i2 = nn >> 1;
02223   j = 0;
02224   for (i=0;i<nn-1;i++) {
02225     if (i < j) {
02226       tx = x[i];
02227       ty = y[i];
02228       x[i] = x[j];
02229       y[i] = y[j];
02230       x[j] = tx;
02231       y[j] = ty;
02232     }
02233     k = i2;
02234     while (k <= j) {
02235       j -= k;
02236       k >>= 1;
02237     }
02238     j += k;
02239   }
02240 
02241   
02242   c1 = -1.0;
02243   c2 = 0.0;
02244   l2 = 1;
02245   for (l=0;l<m;l++) {
02246     l1 = l2;
02247     l2 <<= 1;
02248     u1 = 1.0;
02249     u2 = 0.0;
02250     for (j=0;j<l1;j++) {
02251       for (i=j;i<nn;i+=l2) {
02252         i1 = i + l1;
02253         t1 = u1 * x[i1] - u2 * y[i1];
02254         t2 = u1 * y[i1] + u2 * x[i1];
02255         x[i1] = x[i] - t1;
02256         y[i1] = y[i] - t2;
02257         x[i] += t1;
02258         y[i] += t2;
02259       }
02260       z =  u1 * c1 - u2 * c2;
02261       u2 = u1 * c2 + u2 * c1;
02262       u1 = z;
02263     }
02264     c2 = vcl_sqrt((1.0 - c1) / 2.0);
02265     if (dir == 1)
02266       c2 = -c2;
02267     c1 = vcl_sqrt((1.0 + c1) / 2.0);
02268   }
02269 
02270   
02271   if (dir == 1) {
02272     for (i=0;i<nn;i++) {
02273       x[i] /= (double)nn;
02274       y[i] /= (double)nn;
02275     }
02276   }
02277 
02278   return true;
02279 }
02280 
02281 
02282 
02283 
02284 
02285 
02286 
02287 
02288 bool brip_vil_float_ops::fft_2d(vnl_matrix<vcl_complex<double> >& c,int nx,int ny,int dir)
02289 {
02290   int i,j;
02291   int mx, my;
02292   double *real,*imag;
02293   vnl_fft_prime_factors<double> pfx (nx);
02294   vnl_fft_prime_factors<double> pfy (ny);
02295   mx = (int)pfx.pqr()[0];
02296   my = (int)pfy.pqr()[0];
02297   
02298   real = new double[nx];
02299   imag = new double[nx];
02300   if (real == 0 || imag == 0)
02301     return false;
02302   for (j=0;j<ny;j++) {
02303     for (i=0;i<nx;i++) {
02304       real[i] = c[j][i].real();
02305       imag[i] = c[j][i].imag();
02306     }
02307     brip_vil_float_ops::fft_1d(dir,mx,real,imag);
02308     for (i=0;i<nx;i++) {
02309       vcl_complex<double> v(real[i], imag[i]);
02310       c[j][i] = v;
02311     }
02312   }
02313   delete [] real;
02314   delete [] imag;
02315   
02316   real = new double[ny];
02317   imag = new double[ny];
02318   if (real == 0 || imag == 0)
02319     return false;
02320   for (i=0;i<nx;i++) {
02321     for (j=0;j<ny;j++) {
02322       real[j] = c[j][i].real();
02323       imag[j] = c[j][i].imag();
02324     }
02325     fft_1d(dir,my,real,imag);
02326     for (j=0;j<ny;j++) {
02327       vcl_complex<double> v(real[j], imag[j]);
02328       c[j][i] =  v;
02329     }
02330   }
02331   delete [] real;
02332   delete [] imag;
02333   return true;
02334 }
02335 
02336 
02337 
02338 void brip_vil_float_ops::
02339 ftt_fourier_2d_reorder(vnl_matrix<vcl_complex<double> > const& F1,
02340                        vnl_matrix<vcl_complex<double> > & F2)
02341 {
02342   int rows = static_cast<int>(F1.rows()), cols = static_cast<int>(F1.cols());
02343   int half_rows = rows/2, half_cols = cols/2;
02344   int ri, ci;
02345   for (int r = 0; r<rows; r++)
02346   {
02347     if (r<half_rows)
02348       ri = half_rows+r;
02349     else
02350       ri = r-half_rows;
02351     for (int c = 0; c<cols; c++)
02352     {
02353       if (c<half_cols)
02354         ci = half_cols+c;
02355       else
02356         ci = c-half_cols;
02357       F2[ri][ci]=F1[r][c];
02358     }
02359   }
02360 }
02361 
02362 
02363 
02364 bool brip_vil_float_ops::
02365 fourier_transform(vil_image_view<float> const& input,
02366                   vil_image_view<float>& mag,
02367                   vil_image_view<float>& phase)
02368 {
02369   unsigned w = input.ni(), h = input.nj();
02370 
02371   vnl_fft_prime_factors<float> pfx (w);
02372   vnl_fft_prime_factors<float> pfy (h);
02373   if (!pfx.pqr()[0]||!pfy.pqr()[0])
02374     return false;
02375   
02376   vnl_matrix<vcl_complex<double> > fft_matrix(h, w), fourier_matrix(h,w);
02377   for (unsigned y = 0; y<h; y++)
02378     for (unsigned x =0; x<w; x++)
02379     {
02380       vcl_complex<double> cv(input(x,y), 0.0);
02381       fft_matrix.put(y, x, cv);
02382     }
02383 #ifdef DEBUG
02384   for (unsigned r = 0; r<h; r++)
02385     for (unsigned c =0; c<w; c++)
02386     {
02387       vcl_complex<double> res = fft_matrix[r][c];
02388       vcl_cout << res << '\n';
02389     }
02390 #endif
02391 
02392   brip_vil_float_ops::fft_2d(fft_matrix, w, h, 1);
02393   brip_vil_float_ops::ftt_fourier_2d_reorder(fft_matrix, fourier_matrix);
02394   mag.set_size(w,h);
02395   phase.set_size(w,h);
02396 
02397   
02398   for (unsigned r = 0; r<h; r++)
02399     for (unsigned c = 0; c<w; c++)
02400     {
02401       float re = (float)fourier_matrix[r][c].real(),
02402         im = (float)fourier_matrix[r][c].imag();
02403       mag(c,r) = vcl_sqrt(re*re + im*im);
02404       phase(c,r) = vcl_atan2(im, re);
02405     }
02406   return true;
02407 }
02408 
02409 bool brip_vil_float_ops::
02410 inverse_fourier_transform(vil_image_view<float> const& mag,
02411                           vil_image_view<float> const& phase,
02412                           vil_image_view<float>& output)
02413 {
02414   unsigned w = mag.ni(), h = mag.nj();
02415   vnl_matrix<vcl_complex<double> > fft_matrix(h, w), fourier_matrix(h, w);
02416   for (unsigned y = 0; y<h; y++)
02417     for (unsigned x =0; x<w; x++)
02418     {
02419       float m = mag(x,y);
02420       float p = phase(x,y);
02421       vcl_complex<double> cv(m*vcl_cos(p), m*vcl_sin(p));
02422       fourier_matrix.put(y, x, cv);
02423     }
02424 
02425   brip_vil_float_ops::ftt_fourier_2d_reorder(fourier_matrix, fft_matrix);
02426   brip_vil_float_ops::fft_2d(fft_matrix, w, h, -1);
02427 
02428   output.set_size(w,h);
02429 
02430   for (unsigned y = 0; y<h; y++)
02431     for (unsigned x = 0; x<w; x++)
02432       output(x,y) = (float)fft_matrix[y][x].real();
02433   return true;
02434 }
02435 
02436 void brip_vil_float_ops::resize(vil_image_view<float> const& input,
02437                                 unsigned width, unsigned height,
02438                                 vil_image_view<float>& output)
02439 {
02440   unsigned w = input.ni(), h = input.nj();
02441   output.set_size(width, height);
02442   for (unsigned y = 0; y<height; y++)
02443     for (unsigned x = 0; x<width; x++)
02444       if (x<w && y<h)
02445         output(x,y) = input(x,y);
02446       else
02447         output(x,y) = 0; 
02448 }
02449 
02450 
02451 bool brip_vil_float_ops::
02452 resize_to_power_of_two(vil_image_view<float> const& input,
02453                        vil_image_view<float>& output)
02454 {
02455   unsigned max_exp = 13; 
02456   unsigned w = input.ni(), h = input.nj();
02457   unsigned prodw = 1, prodh = 1;
02458   
02459   unsigned nw, nh;
02460   for (nw = 1; nw<=max_exp; nw++)
02461     if (prodw>w)
02462       break;
02463     else
02464       prodw *= 2;
02465   if (nw==max_exp)
02466     return false;
02467   
02468   for (nh = 1; nh<=max_exp; nh++)
02469     if (prodh>h)
02470       break;
02471     else
02472       prodh *= 2;
02473   if (nh==max_exp)
02474     return false;
02475   brip_vil_float_ops::resize(input, prodw, prodh, output);
02476 
02477   return true;
02478 }
02479 
02480 
02481 
02482 
02483 
02484 
02485 
02486 
02487 float brip_vil_float_ops::gaussian_blocking_filter(float dir_fx,
02488                                                    float dir_fy,
02489                                                    float f0,
02490                                                    float radius,
02491                                                    float fx,
02492                                                    float fy)
02493 {
02494   
02495   float mag = vcl_sqrt(dir_fx*dir_fx + dir_fy*dir_fy);
02496   if (!mag)
02497     return 0.f;
02498   float r2 = 2.f*radius*radius;
02499   float dx = dir_fx/mag, dy = dir_fy/mag;
02500   
02501   float fx0p = dx*f0, fy0p = dy*f0;
02502   float fx0m = -dx*f0, fy0m = -dy*f0;
02503   
02504   float d2p = (fx-fx0p)*(fx-fx0p) + (fy-fy0p)*(fy-fy0p);
02505   float d2m = (fx-fx0m)*(fx-fx0m) + (fy-fy0m)*(fy-fy0m);
02506   
02507   float d = d2p;
02508   if (d2m<d2p)
02509     d = d2m;
02510   
02511   float gb = 1.f-(float)vcl_exp(-d/r2);
02512   return gb;
02513 }
02514 
02515 bool brip_vil_float_ops::
02516 spatial_frequency_filter(vil_image_view<float> const& input,
02517                          float dir_fx, float dir_fy,
02518                          float f0, float radius,
02519                          bool output_fourier_mag,
02520                          vil_image_view<float>& output)
02521 {
02522   
02523   vil_image_view<float> pow_two, mag, bmag, phase, pow_two_filt;
02524   brip_vil_float_ops::resize_to_power_of_two(input, pow_two);
02525   unsigned Nfx = pow_two.ni(), Nfy = pow_two.nj();
02526 
02527   if (!brip_vil_float_ops::fourier_transform(pow_two, mag, phase))
02528     return false;
02529   bmag.set_size(Nfx, Nfy);
02530 
02531   
02532   float Ofx = Nfx*0.5f, Ofy = Nfy*0.5f;
02533   for (unsigned fy =0; fy<Nfy; fy++)
02534     for (unsigned fx =0; fx<Nfx; fx++)
02535     {
02536       float gb = gaussian_blocking_filter(dir_fx, dir_fy, f0,
02537                                           radius,
02538                                           (float)fx-Ofx, (float)fy-Ofy);
02539       bmag(fx,fy) = mag(fx,fy)*gb;
02540     }
02541   if (output_fourier_mag)
02542   {
02543     output = bmag;
02544     return true;
02545   }
02546   
02547   pow_two_filt.set_size(Nfx, Nfy);
02548   brip_vil_float_ops::inverse_fourier_transform(bmag, phase, pow_two_filt);
02549 
02550   
02551   brip_vil_float_ops::resize(pow_two_filt, input.ni(), input.nj(), output);
02552   return true;
02553 }
02554 
02555 
02556 
02557 
02558 
02559 
02560 
02561 
02562 
02563 double brip_vil_float_ops::
02564 bilinear_interpolation(vil_image_view<float> const& input, double x, double y)
02565 {
02566   
02567   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
02568   
02569   int xr = (int)x, yr = (int)y;
02570   double fx = x-xr, fy = y-yr;
02571   if (xr<0||xr>w-2)
02572     return 0.0;
02573   if (yr<0||yr>h-2)
02574     return 0.0;
02575   double int00 = input(xr, yr), int10 = input(xr+1,yr);
02576   double int01 = input(xr, yr+1), int11 = input(xr+1,yr+1);
02577   double int0 = int00 + fy * (int01 - int00);
02578   double int1 = int10 + fy * (int11 - int10);
02579   float val = (float) (int0 + fx * (int1 - int0));
02580   return val;
02581 }
02582 
02583 
02584 
02585 
02586 bool brip_vil_float_ops::homography(vil_image_view<float> const& input,
02587                                     vgl_h_matrix_2d<double> const& H,
02588                                     vil_image_view<float>& output,
02589                                     bool output_size_fixed,
02590                                     float output_fill_value)
02591 {
02592   if (!input)
02593     return false;
02594   
02595   vil_image_view<float> gimage =
02596     brip_vil_float_ops::gaussian(input, 0.5f);
02597 
02598   
02599   
02600 
02601   
02602   
02603   
02604   vsol_box_2d_sptr input_roi, output_roi;
02605   vsol_polygon_2d_sptr input_poly, output_poly;
02606   vgl_h_matrix_2d<double> Hinv;
02607   
02608   unsigned win = gimage.ni(), hin = gimage.nj();
02609   input_roi = new vsol_box_2d();
02610   input_roi->add_point(0, 0);
02611   input_roi->add_point(win, hin);
02612   input_poly = bsol_algs::poly_from_box(input_roi);
02613   
02614   
02615   
02616   if (!output_size_fixed)
02617   {
02618     if (!bsol_algs::homography(input_poly, H, output_poly))
02619       return false;
02620     vsol_box_2d_sptr temp = output_poly->get_bounding_box();
02621     output.set_size((int)temp->width(), (int)temp->height());
02622     output.fill(output_fill_value);
02623     
02624     output_roi = new vsol_box_2d();
02625     output_roi->add_point(0, 0);
02626     output_roi->add_point(temp->width(), temp->height());
02627     vgl_h_matrix_2d<double> t; t.set_identity().set_translation(-temp->get_min_x(),-temp->get_min_y());
02628     Hinv = (t*H).get_inverse();
02629   }
02630   else 
02631   {    
02632     
02633     if (!output)
02634       return false;
02635     
02636     unsigned wout = output.ni(), hout = output.nj();
02637     output.fill(output_fill_value);
02638     output_roi = new vsol_box_2d();
02639     output_roi->add_point(0, 0);
02640     output_roi->add_point(wout, hout);
02641     output_poly = bsol_algs::poly_from_box(output_roi);
02642 
02643     
02644     vsol_polygon_2d_sptr tpoly;
02645     Hinv = H.get_inverse();
02646     if (!bsol_algs::homography(output_poly, Hinv, tpoly))
02647       return false;
02648 
02649     
02650     vsol_box_2d_sptr tbox = tpoly->get_bounding_box();
02651 
02652     
02653     vsol_box_2d_sptr temp;
02654     if (!bsol_algs::intersection(tbox, input_roi, temp))
02655       return false;
02656     input_roi = temp;
02657   }
02658   
02659   
02660 
02661   
02662   
02663   
02664 
02665   
02666   int ailow  = int(input_roi->get_min_x()+0.9999f); 
02667   int aihigh = int(input_roi->get_max_x());      
02668   int ajlow  = int(input_roi->get_min_y()+0.9999f);
02669   int ajhigh = int(input_roi->get_max_y());
02670 
02671   
02672   int bilow  = int(output_roi->get_min_x()+0.9999f);
02673   int bihigh = int(output_roi->get_max_x());
02674   int bjlow  = int(output_roi->get_min_y()+0.9999f);
02675   int bjhigh = int(output_roi->get_max_y());
02676 
02677   
02678   const vnl_matrix_fixed<double,3,3>& Minv = Hinv.get_matrix();
02679 
02680   
02681   for (int i = bilow; i<bihigh; i++)
02682     for (int j = bjlow; j<bjhigh; j++)
02683     {
02684       
02685       float val;
02686       double u = Minv[0][0] * i + Minv[0][1] * j + Minv[0][2];
02687       double v = Minv[1][0] * i + Minv[1][1] * j + Minv[1][2];
02688       double w = Minv[2][0] * i + Minv[2][1] * j + Minv[2][2];
02689       u /= w;
02690       v /= w;
02691 
02692       
02693       {
02694         int iu = (int) u;
02695         int iv = (int) v;
02696 
02697         if (iu >= ailow && iu < aihigh-1 &&
02698             iv >= ajlow && iv < ajhigh-1)
02699         {
02700           
02701           
02702           
02703           
02704           double v00 = gimage(iu, iv);
02705           double v01 = gimage(iu, iv+1);
02706           double v10 = gimage(iu+1,iv);
02707           double v11 = gimage(iu+1, iv+1);
02708 
02709           double fu = u - iu;
02710           double fv = v - iv;
02711           double v0 = v00 + fv * (v01 - v00);
02712           double v1 = v10 + fv * (v11 - v10);
02713           val = (float) (v0 + fu * (v1 - v0));
02714           
02715           output(i,j) = val;
02716         }
02717       }
02718     }
02719   return true;
02720 }
02721 
02722 
02723 
02724 vil_image_view<float>
02725 brip_vil_float_ops::rotate(vil_image_view<float> const& input,
02726                            double theta_deg)
02727 {
02728   vil_image_view<float> out;
02729   if (!input)
02730     return out;
02731   double ang = theta_deg;
02732   
02733   while (ang>360)
02734     ang-=360;
02735   while (ang<0)
02736     ang+=360;
02737   
02738   double deg_to_rad = vnl_math::pi_over_180;
02739   double rang = deg_to_rad*ang;
02740   vgl_h_matrix_2d<double> H;
02741   H.set_identity().set_rotation(rang);
02742   vil_image_view<float> temp;
02743   
02744   
02745   if (!brip_vil_float_ops::homography(input, H, temp))
02746     return out;
02747   return temp;
02748 }
02749 
02750 bool brip_vil_float_ops::chip(vil_image_view<float> const& input,
02751                               vsol_box_2d_sptr const& roi,
02752                               vil_image_view<float>& chip)
02753 {
02754   if (!input||!roi)
02755     return false;
02756   int w = static_cast<int>(input.ni()), h = static_cast<int>(input.nj());
02757   int x_min = (int)roi->get_min_x(), y_min = (int)roi->get_min_y();
02758   int x_max = (int)roi->get_max_x(), y_max = (int)roi->get_max_y();
02759   if (x_min<0)
02760     x_min = 0;
02761   if (y_min<0)
02762     y_min = 0;
02763   if (x_max>w-1)
02764     x_max=w-1;
02765   if (y_max>h-1)
02766     y_max=h-1;
02767   int rw = x_max-x_min, rh = y_max-y_min;
02768   if (rw<=0||rh<=0)
02769     return false;
02770   vil_image_view<float> temp(rw+1, rh+1, 1);
02771   for (int y = y_min; y<=y_max; y++)  
02772     for (int x =x_min; x<=x_max; x++)
02773       temp(x-x_min, y-y_min) = input(x, y);
02774   chip = temp;
02775   return true;
02776 }
02777 
02778 
02779 bool brip_vil_float_ops::chip(vil_image_resource_sptr const& image,
02780                               brip_roi_sptr const& roi,
02781                               vil_image_resource_sptr & chip)
02782 {
02783   
02784   unsigned ni = image->ni(), nj = image->nj();
02785 
02786   
02787   unsigned cm = roi->cmin(0), rm = roi->rmin(0);
02788   unsigned niv = roi->csize(0), njv = roi->rsize(0);
02789   vcl_cout << "org(" << cm << ' ' << rm << "):size(" << niv
02790            << ' ' << njv << ")\n" << vcl_flush;
02791   
02792   if (cm>ni-1||rm>nj-1||cm+niv>ni||rm+njv>nj)
02793     return false;
02794   vil_pixel_format pix_format = image->pixel_format();
02795   
02796   if (image->nplanes()==1)
02797   {
02798     if (pix_format==VIL_PIXEL_FORMAT_BYTE)
02799     {
02800       vil_image_view<unsigned char> temp = image->get_view(cm, niv, rm, njv);
02801       if (!temp) return false;
02802       chip = vil_new_image_resource_of_view(temp);
02803       return true;
02804     }
02805     else if (pix_format==VIL_PIXEL_FORMAT_UINT_16)
02806     {
02807       vil_image_view<unsigned short> temp = image->get_view(cm, niv, rm, njv);
02808       if (!temp) return false;
02809       chip = vil_new_image_resource_of_view(temp);
02810       vcl_cout << "resc(" << chip->ni() << ' ' << chip->nj()<< ")\n"
02811                << vcl_flush;
02812       return true;
02813     }
02814     else if (pix_format==VIL_PIXEL_FORMAT_FLOAT)
02815     {
02816       vil_image_view<float> temp = image->get_view(cm, niv, rm, njv);
02817       if (!temp) return false;
02818       chip = vil_new_image_resource_of_view(temp);
02819       return true;
02820     }
02821   }
02822 
02823   
02824   if (image->nplanes()==3)
02825   {
02826     if (pix_format==VIL_PIXEL_FORMAT_BYTE) 
02827     {
02828       
02829       vil_image_view<vil_rgb<vxl_byte> > temp = image->get_view(cm, niv, rm, njv);
02830       if (!temp) return false;
02831       chip = vil_new_image_resource_of_view(temp);
02832       return true;
02833     }
02834   }
02835   return false;
02836 }
02837 
02838 bool brip_vil_float_ops::
02839 chip(vcl_vector<vil_image_resource_sptr> const& images,
02840      brip_roi_sptr const& roi,
02841      vcl_vector<vil_image_resource_sptr>& chips)
02842 {
02843   for (vcl_vector<vil_image_resource_sptr>::const_iterator iit = images.begin(); iit != images.end(); ++iit) {
02844     vil_image_resource_sptr chip;
02845     if (!brip_vil_float_ops::chip(*iit, roi, chip))
02846       return false;
02847     chips.push_back(chip);
02848   }
02849   return true;
02850 }
02851 
02852 
02853 
02854 float brip_vil_float_ops::
02855 cross_correlate(vil_image_view<float> const& image1,
02856                 vil_image_view<float> const& image2,
02857                 float x, float y, int radius, float intensity_thresh)
02858 {
02859   unsigned w1 = image1.ni(), h1 = image1.nj();
02860   unsigned w2 = image1.ni(), h2 = image1.nj();
02861   
02862   if (w1!=w2||h1!=h2)
02863     return -1;
02864   if (x<radius||x>w1-radius-1||y<radius||y>h1-radius-1)
02865     return -1;
02866 
02867   
02868   
02869   int s = 2*radius+1;
02870   double area = s*s;
02871   double sI1=0, sI2=0, sI1I1=0, sI2I2=0, sI1I2=0;
02872   for (int y0 = -10*radius; y0<=10*radius; ++y0)
02873     for (int x0 = -10*radius; x0<=10*radius; ++x0)
02874     {
02875       float xp = x+0.1f*(float)x0, yp = y+0.1f*(float)y0;
02876       double v1 = brip_vil_float_ops::bilinear_interpolation(image1, xp, yp);
02877       double v2 = brip_vil_float_ops::bilinear_interpolation(image2, xp, yp);
02878       sI1 += v1;
02879       sI2 += v2;
02880       sI1I1 += v1*v1;
02881       sI2I2 += v2*v2;
02882       sI1I2 += v1*v2;
02883     }
02884   
02885   float cc = cross_corr(area, sI1, sI2, sI1I1, sI2I2, sI1I2, intensity_thresh);
02886   return cc;
02887 }
02888 
02889 
02890 
02891 static bool update_row(vil_image_view<float> const& image1,
02892                        vil_image_view<float> const& image2,
02893                        int r0, int r,
02894                        vbl_array_2d<double>& SI1,
02895                        vbl_array_2d<double>& SI2,
02896                        vbl_array_2d<double>& SI1I1,
02897                        vbl_array_2d<double>& SI2I2,
02898                        vbl_array_2d<double>& SI1I2)
02899 {
02900   unsigned w1 = image1.ni();
02901   unsigned w2 = image2.ni();
02902   int h1 = image1.nj();
02903   int h2 = image2.nj();
02904   if (w1!=w2||h1!=h2||r<0||r>=h1)
02905     return false;
02906   double i10 = image1(0,r0), i20 = image2(0,r0);
02907   SI1[r][0] = i10; SI2[r][0] = i20; SI1I1[r][0]=i10*i10;
02908   SI2I2[r][0]=i20*i20; SI1I2[r][0]=i10*i20;
02909   for (unsigned c = 1; c<w1; c++)
02910   {
02911     double i1c = image1(c,r0);
02912     double i2c = image2(c,r0);
02913     SI1[r][c]    = SI1[r][c-1]+i1c;
02914     SI2[r][c]    = SI2[r][c-1]+i2c;
02915     SI1I1[r][c]  = SI1I1[r][c-1]+ i1c*i1c;
02916     SI2I2[r][c]  = SI2I2[r][c-1]+ i2c*i2c;
02917     SI1I2[r][c]  = SI1I2[r][c-1]+ i1c*i2c;
02918   }
02919   return true;
02920 }
02921 
02922 static bool initialize_slice(vil_image_view<float> const& image1,
02923                              vil_image_view<float> const& image2,
02924                              unsigned radius,
02925                              vbl_array_2d<double>& SI1,
02926                              vbl_array_2d<double>& SI2,
02927                              vbl_array_2d<double>& SI1I1,
02928                              vbl_array_2d<double>& SI2I2,
02929                              vbl_array_2d<double>& SI1I2)
02930 {
02931   for (unsigned r = 0; r<=2*radius; r++)
02932     if (!update_row(image1, image2, r, r, SI1, SI2, SI1I1, SI2I2, SI1I2))
02933       return false;
02934   return true;
02935 }
02936 
02937 static bool collapse_slice(vbl_array_2d<double> const& SI1,
02938                            vbl_array_2d<double> const& SI2,
02939                            vbl_array_2d<double> const& SI1I1,
02940                            vbl_array_2d<double> const& SI2I2,
02941                            vbl_array_2d<double> const& SI1I2,
02942                            vbl_array_1d<double>& dSI1,
02943                            vbl_array_1d<double>& dSI2,
02944                            vbl_array_1d<double>& dSI1I1,
02945                            vbl_array_1d<double>& dSI2I2,
02946                            vbl_array_1d<double>& dSI1I2)
02947 {
02948   
02949   unsigned w = SI1.cols(), h = SI1.rows();
02950   unsigned dw = dSI1.size();
02951   if (dw!=w)
02952     return false;
02953 
02954   for (unsigned c = 0; c<w; c++)
02955   {
02956     dSI1[c]=0; dSI2[c]=0; dSI1I1[c]=0;
02957     dSI2I2[c]=0; dSI1I2[c]=0;
02958     for (unsigned r = 0; r<h; r++)
02959     {
02960       dSI1[c] += SI1[r][c];
02961       dSI2[c] += SI2[r][c];
02962       dSI1I1[c] += SI1I1[r][c];
02963       dSI2I2[c] += SI2I2[r][c];
02964       dSI1I2[c] += SI1I2[r][c];
02965     }
02966   }
02967   return true;
02968 }
02969 
02970 static bool cross_correlate_row(int radius,
02971                                 vbl_array_1d<double>& dSI1,
02972                                 vbl_array_1d<double>& dSI2,
02973                                 vbl_array_1d<double>& dSI1I1,
02974                                 vbl_array_1d<double>& dSI2I2,
02975                                 vbl_array_1d<double>& dSI1I2,
02976                                 float intensity_thresh,
02977                                 vbl_array_1d<float>& cc)
02978 {
02979   
02980   unsigned w = dSI1.size(), wc = cc.size();
02981   if (!w||!wc||w!=wc)
02982     return false;
02983   int s = 2*radius+1;
02984   double area = s*s;
02985   
02986   double si1=dSI1[s-1], si2=dSI2[s-1], si1i1=dSI1I1[s-1],
02987     si2i2=dSI2I2[s-1], si1i2=dSI1I2[s-1];
02988   cc[radius]= cross_corr(area, si1, si2, si1i1, si2i2, si1i2, intensity_thresh);
02989   
02990   for (unsigned c = radius+1; c+radius<w; c++)
02991   {
02992     si1=dSI1[c+radius]-dSI1[c-radius-1];
02993     si2=dSI2[c+radius]-dSI2[c-radius-1];
02994     si1i1=dSI1I1[c+radius]-dSI1I1[c-radius-1];
02995     si2i2=dSI2I2[c+radius]-dSI2I2[c-radius-1];
02996     si1i2=dSI1I2[c+radius]-dSI1I2[c-radius-1];
02997     cc[c] = cross_corr(area, si1, si2, si1i1, si2i2, si1i2, intensity_thresh);
02998   }
02999   return true;
03000 }
03001 
03002 static void advance_rows(vbl_array_2d<double>& S)
03003 {
03004   unsigned nr = S.rows(), nc = S.cols();
03005   for (unsigned r = 0; r<nr-1; r++)
03006     for (unsigned c =0; c<nc; c++)
03007       S[r][c]=S[r+1][c];
03008 }
03009 
03010 static bool output_cc_row(int r0, vbl_array_1d<float> const& cc,
03011                           vil_image_view<float>& out)
03012 {
03013   unsigned n = cc.size(), w = out.ni();
03014   if (n!=w)
03015     return false;
03016   for (unsigned c = 0; c<w; c++)
03017     out(c, r0) = cc[c];
03018   return true;
03019 }
03020 
03021 bool brip_vil_float_ops::
03022 cross_correlate(vil_image_view<float> const& image1,
03023                 vil_image_view<float> const& image2,
03024                 vil_image_view<float>& out,
03025                 int radius, float intensity_thresh)
03026 {
03027   vul_timer t;
03028   unsigned w = image1.ni(), h = image1.nj();
03029   unsigned w2 = image2.ni(), h2 = image2.nj();
03030   
03031   if (w!=w2||h!=h2)
03032   {
03033     vcl_cout << "In brip_vil_float_ops::cross_correlate(..) -"
03034              << " image sizes don't match\n";
03035     return out;
03036   }
03037   out.set_size(w, h);
03038   out.fill(0.f);
03039   int s = 2*radius+1;
03040   
03041   vbl_array_2d<double> SI1(s,w), SI2(s,w),
03042     SI1I1(s,w), SI2I2(s,w), SI1I2(s,w);
03043   vbl_array_1d<float> cc(w, 0.f);
03044   vbl_array_1d<double> dSI1(w, 0.0), dSI2(w, 0.0),
03045     dSI1I1(w, 0.0), dSI2I2(w, 0.0), dSI1I2(w, 0.0);
03046   initialize_slice(image1, image2, radius, SI1, SI2, SI1I1, SI2I2, SI1I2);
03047   if (!collapse_slice(SI1,  SI2,  SI1I1,  SI2I2,  SI1I2,
03048                       dSI1, dSI2, dSI1I1, dSI2I2, dSI1I2))
03049     return false;
03050   unsigned r0 = radius;
03051   for (; r0+radius+1<h; r0++)
03052   {
03053     if (r0==5)
03054       r0=5;
03055 #ifdef DEBUG
03056     vcl_cout << "r0 " << r0 << '\n';
03057 #endif
03058     if (!cross_correlate_row(radius, dSI1, dSI2, dSI1I1, dSI2I2, dSI1I2,
03059                              intensity_thresh, cc))
03060       return false;
03061 #ifdef DEBUG
03062     vcl_cout << '\n';
03063 #endif
03064     advance_rows(SI1); advance_rows(SI2);  advance_rows(SI1I1);
03065     advance_rows(SI2I2); advance_rows(SI1I2);
03066     if (!update_row(image1, image2, r0+radius+1, 2*radius,
03067                     SI1, SI2, SI1I1, SI2I2, SI1I2))
03068       return false;
03069     if (!collapse_slice(SI1,  SI2,  SI1I1,  SI2I2,  SI1I2,
03070                         dSI1, dSI2, dSI1I1, dSI2I2, dSI1I2))
03071       return false;
03072     if (!output_cc_row(r0, cc, out))
03073       return out;
03074   }
03075   
03076 #ifdef DEBUG
03077   vcl_cout << "r0 " << r0 << '\n';
03078 #endif
03079   if (!cross_correlate_row(radius, dSI1, dSI2, dSI1I1, dSI2I2, dSI1I2,
03080                            intensity_thresh, cc))
03081     return false;
03082 #ifdef DEBUG
03083   vcl_cout << '\n';
03084 #endif
03085   if (!output_cc_row(r0, cc, out))
03086     return false;
03087 #ifdef DEBUG
03088   vcl_cout << "RunningSumCrossCorrelation for " << w*h/1000.0f << " k pixels in "
03089            << t.real() << " msecs\n"<< vcl_flush;
03090 #endif
03091   return true;
03092 }
03093 
03094 vil_image_resource_sptr
03095 brip_vil_float_ops::sum(vil_image_resource_sptr const& img0,
03096                         vil_image_resource_sptr const& img1)
03097 {
03098   vil_image_view<float> op0 = brip_vil_float_ops::convert_to_float(img0);
03099   vil_image_view<float> op1 = brip_vil_float_ops::convert_to_float(img1);
03100   vil_image_view<float> sum;
03101   vil_math_image_sum(op0, op1, sum);
03102 
03103   
03104   vil_pixel_format pix_format0 = img0->pixel_format();
03105   vil_pixel_format pix_format1 = img1->pixel_format();
03106   if (pix_format0 == VIL_PIXEL_FORMAT_FLOAT ||
03107       pix_format1 == VIL_PIXEL_FORMAT_FLOAT)
03108     {
03109       return vil_new_image_resource_of_view(sum);
03110     }
03111 
03112   if (pix_format0 == VIL_PIXEL_FORMAT_UINT_16 ||
03113       pix_format1 == VIL_PIXEL_FORMAT_UINT_16)
03114     {
03115       vil_image_view<vxl_uint_16> res =
03116         brip_vil_float_ops::convert_to_short(vil_new_image_resource_of_view(sum));
03117       return vil_new_image_resource_of_view(res);
03118     }
03119 
03120   if (pix_format0 == VIL_PIXEL_FORMAT_BYTE ||
03121       pix_format1 == VIL_PIXEL_FORMAT_BYTE)
03122     {
03123       vil_image_view<vxl_byte> res =
03124         brip_vil_float_ops::convert_to_byte(sum);
03125       return vil_new_image_resource_of_view(res);
03126     }
03127   
03128   return vil_new_image_resource_of_view(sum);
03129 }
03130 
03131 
03132 vil_image_resource_sptr
03133 brip_vil_float_ops::difference(vil_image_resource_sptr const& img0,
03134                                vil_image_resource_sptr const& img1)
03135 {
03136   vil_image_view<float> op0 = brip_vil_float_ops::convert_to_float(img0);
03137   vil_image_view<float> op1 = brip_vil_float_ops::convert_to_float(img1);
03138   vil_image_view<float> diff;
03139   vil_math_image_difference(op0, op1, diff);
03140 
03141   
03142   vil_pixel_format pix_format0 = img0->pixel_format();
03143   vil_pixel_format pix_format1 = img1->pixel_format();
03144   if (pix_format0 == VIL_PIXEL_FORMAT_FLOAT ||
03145       pix_format1 == VIL_PIXEL_FORMAT_FLOAT)
03146     {
03147       return vil_new_image_resource_of_view(diff);
03148     }
03149 
03150   if (pix_format0 == VIL_PIXEL_FORMAT_UINT_16 ||
03151       pix_format1 == VIL_PIXEL_FORMAT_UINT_16)
03152     {
03153       vil_image_view<vxl_uint_16> res =
03154         brip_vil_float_ops::convert_to_short(vil_new_image_resource_of_view(diff));
03155       return vil_new_image_resource_of_view(res);
03156     }
03157 
03158   if (pix_format0 == VIL_PIXEL_FORMAT_BYTE ||
03159       pix_format1 == VIL_PIXEL_FORMAT_BYTE)
03160     {
03161       vil_image_view<vxl_byte> res = brip_vil_float_ops::convert_to_byte(diff);
03162       return vil_new_image_resource_of_view(res);
03163     }
03164   
03165   return vil_new_image_resource_of_view(diff);
03166 }
03167 
03168 
03169 
03170 float brip_vil_float_ops::entropy_i(const unsigned i, const unsigned j,
03171                                     const unsigned i_radius,
03172                                     const unsigned j_radius,
03173                                     vil_image_view<float> const& intensity,
03174                                     const float range, const unsigned bins)
03175 {
03176   bsta_histogram<float> hi(range, bins);
03177   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03178   for (int dj = -jr; dj<=jr; ++dj)
03179     for (int di = -ir; di<=ir; ++di)
03180     {
03181       float inten = intensity(i+di, j+dj);
03182       hi.upcount(inten, 1.0f);
03183     }
03184   return hi.entropy();
03185 }
03186 
03187 
03188 
03189 float brip_vil_float_ops::entropy_g(const unsigned i, const unsigned j,
03190                                     const unsigned i_radius,
03191                                     const unsigned j_radius,
03192                                     vil_image_view<float> const& gradx,
03193                                     vil_image_view<float> const& grady,
03194                                     const float range, const unsigned bins)
03195 {
03196   bsta_histogram<float> hg(range, bins);
03197   static const float deg_rad = (float)(vnl_math::deg_per_rad);
03198   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03199   for (int dj = -jr; dj<=jr; ++dj)
03200     for (int di = -ir; di<=ir; ++di)
03201     {
03202       float Ix = gradx(i+di, j+dj), Iy = grady(i+di, j+dj);
03203       float ang = deg_rad*vcl_atan2(Iy, Ix) + 180.0f;
03204       float mag = vcl_abs(Ix)+vcl_abs(Iy);
03205       hg.upcount(ang, mag);
03206     }
03207   return hg.entropy();
03208 }
03209 
03210 
03211 
03212 float brip_vil_float_ops::entropy_hs(const unsigned i, const unsigned j,
03213                                      const unsigned i_radius,
03214                                      const unsigned j_radius,
03215                                      vil_image_view<float> const& hue,
03216                                      vil_image_view<float> const& sat,
03217                                      const float range, const unsigned bins)
03218 {
03219   bsta_histogram<float> hg(range, bins);
03220   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03221   for (int dj = -jr; dj<=jr; ++dj)
03222     for (int di = -ir; di<=ir; ++di)
03223     {
03224       float h = hue(i+di, j+dj), s = sat(i+di, j+dj);
03225       hg.upcount(h, s);
03226     }
03227   return hg.entropy();
03228 }
03229 
03230 vil_image_view<float>
03231 brip_vil_float_ops::entropy(const unsigned i_radius,
03232                             const unsigned j_radius,
03233                             const unsigned step,
03234                             vil_image_resource_sptr const& img,
03235                             const float sigma,
03236                             const bool intensity,
03237                             const bool gradient,
03238                             const bool ihs)
03239 {
03240   vil_image_view<float> ent;
03241   if (!intensity&&!gradient&&!ihs)
03242   {
03243     vcl_cout << "In brip_vil_float_ops::entropy(.) - No computation to do\n";
03244     return ent;
03245   }
03246 
03247   vil_image_view<float> fimage = brip_vil_float_ops::convert_to_float(img);
03248   vil_image_view<float> gimage =
03249     brip_vil_float_ops::gaussian(fimage, sigma);
03250 
03251   unsigned ni = img->ni(), nj = img->nj();
03252   ent.set_size(ni/step+1, nj/step+1);
03253   ent.fill(0.0f);
03254   if (intensity)
03255     for (unsigned j = j_radius; j<(nj-j_radius); j+=step)
03256       for (unsigned i = i_radius; i<(ni-i_radius); i+=step)
03257         ent(i/step,j/step) =
03258           brip_vil_float_ops::entropy_i(i, j, i_radius, j_radius, gimage);
03259 
03260   if (gradient)
03261   {
03262     vil_image_view<float> grad_x, grad_y;
03263     grad_x.set_size(ni, nj);
03264     grad_y.set_size(ni, nj);
03265     brip_vil_float_ops::gradient_3x3 (gimage , grad_x , grad_y);
03266     for (unsigned j = j_radius; j<(nj-j_radius); j+=step)
03267       for (unsigned i = i_radius; i<(ni-i_radius); i+=step)
03268         ent(i/step,j/step) +=
03269           brip_vil_float_ops::entropy_g(i, j, i_radius, j_radius,
03270                                         grad_x, grad_y);
03271   }
03272   if (ihs&&img->nplanes()==3)
03273   {
03274     vil_image_view<float> inten, hue, sat;
03275     vil_image_view<vil_rgb<vxl_byte> > cimage = img->get_view();
03276     brip_vil_float_ops::convert_to_IHS(cimage, inten, hue, sat);
03277     for (unsigned j = j_radius; j<(nj-j_radius); j+=step)
03278       for (unsigned i = i_radius; i<(ni-i_radius); i+=step)
03279         ent(i/step,j/step) +=
03280           brip_vil_float_ops::entropy_hs(i, j, i_radius, j_radius,
03281                                          hue, sat);
03282   }
03283   return ent;
03284 }
03285 
03286 float brip_vil_float_ops::minfo_i(const unsigned i0, const unsigned j0,
03287                                   const unsigned i1, const unsigned j1,
03288                                   const unsigned i_radius,
03289                                   const unsigned j_radius,
03290                                   vil_image_view<float> const& int0,
03291                                   vil_image_view<float> const& int1,
03292                                   const float range, const unsigned bins)
03293 {
03294   bsta_histogram<float> hi0(range, bins);
03295   bsta_histogram<float> hi1(range, bins);
03296   bsta_joint_histogram<float> hji(range, bins);
03297   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03298   for (int dj = -jr; dj<=jr; ++dj)
03299     for (int di = -ir; di<=ir; ++di)
03300     {
03301       float inten0 = int0(i0+di, j0+dj);
03302       float inten1 = int1(i1+di, j1+dj);
03303       hi0.upcount(inten0, 1.0f);
03304       hi1.upcount(inten1, 1.0f);
03305       hji.upcount(inten0, 1.0f, inten1, 1.0f);
03306     }
03307   float H0 = hi0.entropy();
03308   float H1 = hi1.entropy();
03309   float HJ = hji.entropy();
03310   float minfo_i = H0 + H1 - HJ;
03311 #ifdef DEBUG
03312   if (minfo<0)
03313     vcl_cout << "intensity MI LT 0 " << minfo << vcl_endl;
03314 #endif
03315   return minfo_i;
03316 }
03317 
03318 float brip_vil_float_ops::minfo_g(const unsigned i0, const unsigned j0,
03319                                   const unsigned i1, const unsigned j1,
03320                                   const unsigned i_radius,
03321                                   const unsigned j_radius,
03322                                   vil_image_view<float> const& gradx0,
03323                                   vil_image_view<float> const& grady0,
03324                                   vil_image_view<float> const& gradx1,
03325                                   vil_image_view<float> const& grady1,
03326                                   const float range, const unsigned bins)
03327 {
03328   bsta_histogram<float> hg0(range, bins);
03329   bsta_histogram<float> hg1(range, bins);
03330   bsta_joint_histogram<float> hjg(range, bins);
03331   static const float deg_rad = (float)(vnl_math::deg_per_rad);
03332   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03333   for (int dj = -jr; dj<=jr; ++dj)
03334     for (int di = -ir; di<=ir; ++di)
03335     {
03336       float Ix0 = gradx0(i0+di, j0+dj), Iy0 = grady0(i0+di, j0+dj);
03337       float Ix1 = gradx1(i1+di, j1+dj), Iy1 = grady1(i1+di, j1+dj);
03338       float ang0 = deg_rad*vcl_atan2(Iy0, Ix0) + 180.0f;
03339       float ang1 = deg_rad*vcl_atan2(Iy1, Ix1) + 180.0f;
03340       float mag0 = vcl_abs(Ix0)+vcl_abs(Iy0);
03341       float mag1 = vcl_abs(Ix1)+vcl_abs(Iy1);
03342       hg0.upcount(ang0, mag0);
03343       hg1.upcount(ang1, mag1);
03344       hjg.upcount(ang0, mag0, ang1, mag1);
03345     }
03346   float H0 = hg0.entropy();
03347   float H1 = hg1.entropy();
03348   float HJ = hjg.entropy();
03349   float minfo_g = H0 + H1 - HJ;
03350 #ifdef DEBUG
03351   if (minfo<0)
03352     vcl_cout << "gradient MI LT 0 " << minfo << vcl_endl;
03353 #endif
03354   return minfo_g;
03355 }
03356 
03357 float brip_vil_float_ops::minfo_hs(const unsigned i0, const unsigned j0,
03358                                    const unsigned i1, const unsigned j1,
03359                                    const unsigned i_radius,
03360                                    const unsigned j_radius,
03361                                    vil_image_view<float> const& hue0,
03362                                    vil_image_view<float> const& sat0,
03363                                    vil_image_view<float> const& hue1,
03364                                    vil_image_view<float> const& sat1,
03365                                    const float range, const unsigned bins)
03366 {
03367   bsta_histogram<float> hh0(range, bins);
03368   bsta_histogram<float> hh1(range, bins);
03369   bsta_joint_histogram<float> hjh(range, bins);
03370   int ir = static_cast<int>(i_radius), jr = static_cast<int>(j_radius);
03371   for (int dj = -jr; dj<=jr; ++dj)
03372     for (int di = -ir; di<=ir; ++di)
03373     {
03374       float h0 = hue0(i0+di, j0+dj), s0 = sat0(i0+di, j0+dj);
03375       float h1 = hue1(i1+di, j1+dj), s1 = sat1(i1+di, j1+dj);
03376       hh0.upcount(h0, s0);
03377       hh1.upcount(h1, s1);
03378       hjh.upcount(h0, s0, h1, s1);
03379     }
03380   float H0 = hh0.entropy();
03381   float H1 = hh1.entropy();
03382   float HJ = hjh.entropy();
03383   float minfo_h = H0 + H1 - HJ;
03384 #ifdef DEBUG
03385   if (minfo<0)
03386     vcl_cout << "color MI LT 0 " << minfo << vcl_endl;
03387 #endif
03388   return minfo_h;
03389 }
03390 
03391 bool brip_vil_float_ops::minfo(const unsigned i_radius,
03392                                const unsigned j_radius,
03393                                const unsigned step,
03394                                vil_image_resource_sptr const& img0,
03395                                vil_image_resource_sptr const& img1,
03396                                vil_image_view<float>& MI0,
03397                                vil_image_view<float>& MI1,
03398                                const float sigma,
03399                                const bool intensity,
03400                                const bool gradient,
03401                                const bool ihs)
03402 {
03403   if (!intensity&&!gradient&&!ihs)
03404   {
03405     vcl_cout << "In brip_vil_float_ops::minforopy(.) - No computation to do\n";
03406     return false;
03407   }
03408 
03409   vil_image_view<float> fimage0 = brip_vil_float_ops::convert_to_float(img0);
03410   vil_image_view<float> gimage0 =
03411     brip_vil_float_ops::gaussian(fimage0, sigma);
03412 
03413   vil_image_view<float> fimage1 = brip_vil_float_ops::convert_to_float(img1);
03414   vil_image_view<float> gimage1 =
03415     brip_vil_float_ops::gaussian(fimage1, sigma);
03416 
03417   unsigned ni0 = img0->ni(), nj0 = img0->nj();
03418   unsigned ni1 = img1->ni(), nj1 = img1->nj();
03419   unsigned ilimit = 2*i_radius +1, jlimit = 2*j_radius+1;
03420   if (ni0<ilimit||nj0<jlimit||ni1<ilimit||nj1<jlimit)
03421   {
03422     vcl_cout << "In brip_vil_float_ops::minfo(...) - image too small\n";
03423     return false;
03424   }
03425   MI0.set_size(ni0/step+1, nj0/step+1); MI0.fill(0.0f);
03426   MI1.set_size(ni1/step+1, nj1/step+1); MI1.fill(0.0f);
03427   if (intensity)
03428     for (unsigned j0 = j_radius; j0<(nj0-j_radius); j0+=step)
03429       for (unsigned i0 = i_radius; i0<(ni0-i_radius); i0+=step)
03430         for (unsigned j1 = j_radius; j1<(nj1-j_radius); j1+=step)
03431           for (unsigned i1 = i_radius; i1<(ni1-i_radius); i1+=step)
03432           {
03433             float minfo = brip_vil_float_ops::minfo_i(i0, j0,i1, j1,
03434                                                       i_radius, j_radius,
03435                                                       gimage0, gimage1);
03436             MI0(i0/step,j0/step) = minfo;
03437             MI1(i1/step,j1/step) = minfo;
03438           }
03439   if (gradient)
03440   {
03441     vil_image_view<float> grad_x0, grad_y0, grad_x1, grad_y1;
03442     grad_x0.set_size(ni0, nj0);
03443     grad_y0.set_size(ni0, nj0);
03444     grad_x1.set_size(ni1, nj1);
03445     grad_y1.set_size(ni1, nj1);
03446     brip_vil_float_ops::gradient_3x3 (gimage0 , grad_x0 , grad_y0);
03447     brip_vil_float_ops::gradient_3x3 (gimage1 , grad_x1 , grad_y1);
03448     for (unsigned j0 = j_radius; j0<(nj0-j_radius); j0+=step)
03449       for (unsigned i0 = i_radius; i0<(ni0-i_radius); i0+=step)
03450         for (unsigned j1 = j_radius; j1<(nj1-j_radius); j1+=step)
03451           for (unsigned i1 = i_radius; i1<(ni1-i_radius); i1+=step)
03452           {
03453             float minfo = brip_vil_float_ops::minfo_g(i0, j0,i1, j1,
03454                                                       i_radius, j_radius,
03455                                                       grad_x0, grad_y0,
03456                                                       grad_x1, grad_y1);
03457             MI0(i0/step,j0/step) += minfo;
03458             MI1(i1/step,j1/step) += minfo;
03459           }
03460   }
03461   if (ihs&&img0->nplanes()==3&&img1->nplanes()==3)
03462   {
03463     vil_image_view<float> inten0, hue0, sat0;
03464     vil_image_view<float> inten1, hue1, sat1;
03465     vil_image_view<vil_rgb<vxl_byte> > cimage0 = img0->get_view();
03466     vil_image_view<vil_rgb<vxl_byte> > cimage1 = img1->get_view();
03467     brip_vil_float_ops::convert_to_IHS(cimage0, inten0, hue0, sat0);
03468     brip_vil_float_ops::convert_to_IHS(cimage1, inten1, hue1, sat1);
03469 
03470     for (unsigned j0 = j_radius; j0<(nj0-j_radius); j0+=step)
03471       for (unsigned i0 = i_radius; i0<(ni0-i_radius); i0+=step)
03472         for (unsigned j1 = j_radius; j1<(nj1-j_radius); j1+=step)
03473           for (unsigned i1 = i_radius; i1<(ni1-i_radius); i1+=step)
03474           {
03475             float minfo = brip_vil_float_ops::minfo_hs(i0, j0,i1, j1,
03476                                                        i_radius, j_radius,
03477                                                        hue0, sat0,
03478                                                        hue1, sat1);
03479             MI0(i0/step,j0/step) += minfo;
03480             MI1(i1/step,j1/step) += minfo;
03481           }
03482   }
03483   return true;
03484 }
03485 
03486 
03487 float brip_vil_float_ops::
03488 average_in_box(vil_image_view<float> const& v, vgl_box_2d<double> const&  box)
03489 {
03490   vgl_point_2d<double> p0 = box.min_point();
03491   unsigned i0 = static_cast<unsigned>(p0.x()), j0 = static_cast<unsigned>(p0.y());
03492   vgl_point_2d<double> p1 = box.max_point();
03493   unsigned i1 = static_cast<unsigned>(p1.x()), j1 = static_cast<unsigned>(p1.y());
03494   float n = 0.0f;
03495   float sum = 0.0f;
03496   for (unsigned i = i0; i<=i1; ++i)
03497     for (unsigned j = j0; j<=j1; ++j, ++n)
03498       sum += v(i,j);
03499   if (n>0)
03500     sum /= n;
03501   return sum;
03502 }
03503 
03504 #if 0 // For now remove dependency on vimt. Save for illustration
03505 bool brip_vil_float_ops::vimt_homography(vil_image_view<float> const& curr_view,
03506                                          vgl_h_matrix_2d<double>const& H,
03507                                          vil_image_view<float>& output)
03508 {
03509   int bimg_ni;
03510   int bimg_nj;
03511 
03512   int offset_i;
03513   int offset_j;
03514 
03515   vbl_bounding_box<double,2> box;
03516 
03517   unsigned ni =  curr_view.ni(), nj =  curr_view.nj();
03518   vimt_transform_2d p;
03519   vnl_double_3x3 Mh = H.get_matrix();
03520   vnl_double_2x3 M;
03521   for (unsigned c = 0; c<3; ++c)
03522     for (unsigned r = 0; r<2; ++r)
03523       M[r][c] = Mh[r][c]/Mh[2][2];
03524   p.set_affine(M);
03525   box.update(p(0,0).x(),p(0,0).y());
03526   box.update(p(0,nj).x(),p(0,nj).y());
03527   box.update(p(ni,0).x(),p(ni,0).y());
03528   box.update(p(ni,nj).x(),p(ni,nj).y());
03529 
03530   bimg_ni=(int)vcl_ceil(box.max()[0]-box.min()[0]);
03531   bimg_nj=(int)vcl_ceil(box.max()[1]-box.min()[1]);
03532 
03533   offset_i=(int)vcl_ceil(0-box.min()[0]);
03534   offset_j=(int)vcl_ceil(0-box.min()[1]);
03535 
03536   vimt_image_2d_of<float> sample_im;
03537   vgl_point_2d<double> q(-offset_i,-offset_j);
03538   vgl_vector_2d<double> u(1,0);
03539   vgl_vector_2d<double> v(0,1);
03540 
03541   vimt_image_2d_of<float> curr_img(curr_view,p);
03542   vimt_resample_bilin(curr_img,sample_im,q,u,v,bimg_ni,bimg_nj);
03543   output = sample_im.image();
03544   return true;
03545 }
03546 
03547 #endif // 0
03548 
03549 vcl_vector<float> brip_vil_float_ops::scan_region(vil_image_resource_sptr img,
03550                                                   vgl_polygon<double> poly,
03551                                                   float& min,
03552                                                   float& max)
03553 {
03554   vcl_vector<float> pixels;
03555   min = vnl_numeric_traits<float>::maxval;
03556   max = 0;
03557   unsigned np = img->nplanes();
03558   vgl_polygon_scan_iterator<double> si(poly, false);
03559   if (img->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
03560   {
03561     if (np==1) 
03562     {
03563       for (si.reset(); si.next();)
03564       {
03565         unsigned j = static_cast<unsigned>(si.scany());
03566         for (int x = si.startx(); x<=si.endx(); ++x)
03567         {
03568           unsigned i = static_cast<unsigned>(x);
03569           vil_image_view<unsigned char> v = img->get_view(i, 1,j, 1);
03570           float fv = static_cast<float>(v(0,0));
03571           if (fv<min) min = fv;
03572           if (fv>max) max = fv;
03573           pixels.push_back(fv);
03574         }
03575       }
03576       return pixels;
03577     }
03578     else
03579     {
03580       for (si.reset(); si.next();)
03581       {
03582         unsigned j = static_cast<unsigned>(si.scany());
03583         for (int x = si.startx(); x<=si.endx(); ++x)
03584         {
03585           unsigned i = static_cast<unsigned>(x);
03586           vil_image_view<unsigned char> v = img->get_view(i, 1,j, 1);
03587           float fv = 0;
03588           for (unsigned p = 0; p<np; ++p)
03589             fv += v(0,0,p);
03590           fv/=3;
03591           if (fv<min) min = fv;
03592           if (fv>max) max = fv;
03593           pixels.push_back(fv);
03594         }
03595       }
03596     }
03597     return pixels;
03598   }
03599   else if (img->pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
03600   {
03601     if (np) 
03602     {
03603       for (si.reset(); si.next();)
03604       {
03605         unsigned j = static_cast<unsigned>(si.scany());
03606         for (int x = si.startx(); x<=si.endx(); ++x)
03607         {
03608           unsigned i = static_cast<unsigned>(x);
03609           vil_image_view<unsigned short> v = img->get_view(i, 1,j, 1);
03610           float fv = static_cast<float>(v(0,0));
03611           if (fv<min) min = fv;
03612           if (fv>max) max = fv;
03613           pixels.push_back(fv);
03614         }
03615       }
03616       return pixels;
03617     }
03618     else
03619     {
03620       for (si.reset(); si.next();)
03621       {
03622         unsigned j = static_cast<unsigned>(si.scany());
03623         for (int x = si.startx(); x<=si.endx(); ++x)
03624         {
03625           unsigned i = static_cast<unsigned>(x);
03626           vil_image_view<unsigned short> v = img->get_view(i, 1,j, 1);
03627           float fv = 0;
03628           for (unsigned p = 0; p<np; ++p)
03629             fv += v(0,0,p);
03630           fv/=3;
03631           if (fv<min) min = fv;
03632           if (fv>max) max = fv;
03633           pixels.push_back(fv);
03634         }
03635       }
03636       return pixels;
03637     }
03638   }
03639   vcl_cerr << "In brip_vil_float_ops::scan_region() - unknown format\n";
03640   return pixels;
03641 }
03642 
03643 
03644 
03645 
03646 
03647 
03648 
03649 
03650 
03651 
03652 
03653 
03654 
03655 
03656 
03657 
03658 
03659 
03660 
03661 
03662 
03663 
03664 vil_image_view<vxl_byte> brip_vil_float_ops::
03665 color_order(vil_image_view<float> const& color_image, float eq_tol)
03666 {
03667   unsigned ni = color_image.ni(), nj = color_image.nj();
03668   unsigned np = color_image.nplanes();
03669   vil_image_view<vxl_byte> temp;
03670   if (np!=3)
03671     return temp; 
03672   temp.set_size(ni, nj);
03673   vxl_byte rg_eq=192, rg_lt=128, rg_gt=64;
03674   vxl_byte rb_eq=48, rb_lt=32, rb_gt=16;
03675   vxl_byte gb_eq=12, gb_lt=8, gb_gt=4;
03676   for (unsigned j = 0; j<nj; ++j)
03677     for (unsigned i = 0; i<ni; ++i) {
03678       float r=color_image(i,j,0), g=color_image(i,j,1), b=color_image(i,j,2);
03679       vxl_byte rg, rb, gb;
03680       
03681       if (vcl_fabs(r-g)<eq_tol)
03682         rg = rg_eq;
03683       else if (r<g)
03684         rg = rg_lt;
03685       else rg = rg_gt;
03686       
03687       if (vcl_fabs(r-b)<eq_tol)
03688         rb = rb_eq;
03689       else if (r<b)
03690         rb = rb_lt;
03691       else rb = rb_gt;
03692       
03693       if (vcl_fabs(g-b)<eq_tol)
03694         gb = gb_eq;
03695       else if (g<b)
03696         gb = gb_lt;
03697       else gb = gb_gt;
03698       vxl_byte v = static_cast<vxl_byte>(rg|rb|gb); 
03699       temp(i,j) = v;
03700     }
03701   return temp;
03702 }
03703 
03704 #if 0 // only used in commented-out part of brip_vil_float_ops::extrema()
03705 static double zs(double x)
03706 { if (x < 0.0001 && x > -0.0001) return 0; else return x; }
03707 #endif // 0
03708 
03709 static double brip_vil_rot_gauss(double x, double y,
03710                                  double sigma_x, double sigma_y, double theta)
03711 {
03712   double theta_rad = theta*vnl_math::pi_over_180;
03713   double s = vcl_sin(theta_rad), c = vcl_cos(theta_rad);
03714   double sxr = 1.0/sigma_x, syr = 1.0/sigma_y;
03715   double ax = (c*x + s*y)*sxr, ay = (-s*x + c*y)*syr;
03716   double ret = vcl_exp(-0.5*(ax*ax + ay*ay));
03717   return ret*sxr*syr/(2.0*vnl_math::pi);
03718 }
03719 
03720 
03721 float brip_vil_float_ops::extrema_revert_angle(float angle)
03722 {
03723   if (angle>=0.0f) {
03724     if (angle>90.0f&&angle<=270.0f)
03725       angle -= 180.0f;
03726     else if (angle>270.0f&&angle<=360.0f)
03727       angle -= 360.0f;
03728   }
03729   if (angle<0.0f) {
03730     if (angle<-90.0f&&angle>=-270.0f)
03731       angle += 180.0f;
03732     else if (angle<-270.0f&&angle>=-360.0f)
03733       angle += 360.0f;
03734   }
03735   return angle;
03736 }
03737 
03738 
03739 void brip_vil_float_ops::extrema_kernel_mask(float lambda0, float lambda1,
03740                                              float theta,
03741                                              vbl_array_2d<float>& kernel,
03742                                              vbl_array_2d<bool>& mask, float cutoff_percentage, bool scale_invariant)
03743 {
03744   theta = extrema_revert_angle(theta); 
03745   
03746   double theta_rad = theta*vnl_math::pi_over_180;
03747   double s = vcl_sin(theta_rad), c = vcl_cos(theta_rad);
03748   double s0 = lambda0, s1 = lambda1;
03749   double s1sq = 1.0/(s1*s1);
03750   
03751   double max_v = brip_vil_rot_gauss(0, 0, s0, s1, 0);
03752   double cutoff = max_v*cutoff_percentage; 
03753   unsigned ru = 0;
03754   while (brip_vil_rot_gauss(ru, 0, s0, s1, 0) >= cutoff)
03755     ++ru;
03756   unsigned rv = 0;
03757   while (brip_vil_rot_gauss(0, rv, s0, s1, 0) >= cutoff)
03758     ++rv;
03759 
03760   
03761   int ri = static_cast<int>(vcl_fabs(ru*c+rv*s) +0.5);
03762   int rj = static_cast<int>(vcl_fabs(ru*s+rv*c) +0.5);
03763   if (s<0) {
03764     ri = static_cast<int>(vcl_fabs(ru*c-rv*s) +0.5);
03765     rj = static_cast<int>(vcl_fabs(ru*s-rv*c) +0.5);
03766   }
03767 
03768   unsigned ncols = 2*ri +1, nrows = 2*rj+1;
03769   vbl_array_2d<double> coef(nrows, ncols);
03770   mask.resize(nrows,ncols);
03771   double residual = 0.0, total  = 0.0;
03772   for (int ry = -rj; ry<=rj; ++ry)
03773     for (int rx = -ri; rx<=ri; ++rx)
03774     {
03775       double g = brip_vil_rot_gauss(rx, ry, s0, s1, theta);
03776       mask[ry+rj][rx+ri] = g>=cutoff;
03777       double temp = (-s*rx + c*ry);
03778       temp = temp*temp*s1sq;
03779       double v = (temp -1)*g*(scale_invariant?1.0:s1sq);
03780       if (g<cutoff) v = 0.0;
03781       coef[ry+rj][rx+ri] = v;
03782       residual+=v;
03783       total += vcl_fabs(v);
03784     }
03785   double cor = 0.0;
03786   if (total)
03787     cor = -residual/total;
03788   kernel.resize(nrows, ncols);
03789   
03790   
03791   for (unsigned j = 0; j<nrows; ++j)
03792     for (unsigned i = 0; i<ncols; ++i)
03793     {
03794       double v = vcl_fabs(coef[j][i]);
03795       coef[j][i]+=v*cor;
03796       kernel[j][i]=static_cast<float>(coef[j][i]);
03797     }
03798 }
03799 
03800 
03801 
03802 vil_image_view<float> brip_vil_float_ops::
03803 std_dev_operator(vil_image_view<float> const& sd_image,
03804                  vbl_array_2d<float> const& kernel)
03805 {
03806   unsigned ni = sd_image.ni(), nj = sd_image.nj();
03807   unsigned nrows = kernel.rows(), ncols = kernel.cols();
03808   int rrad = (nrows-1)/2, crad = (ncols-1)/2;
03809   float sd_min, sd_max;
03810   vil_math_value_range(sd_image, sd_min, sd_max);
03811 
03812   vil_image_view<float> res(ni, nj);
03813   res.fill(sd_max);
03814 
03815   vbl_array_2d<float>ksq(nrows, ncols);
03816   for (unsigned r = 0; r<nrows; ++r)
03817     for (unsigned c = 0; c<ncols; ++c)
03818       ksq[r][c] = kernel[r][c]*kernel[r][c];
03819 
03820   for (int j = rrad; j<static_cast<int>(nj-rrad); ++j)
03821     for (int i = crad; i<static_cast<int>(ni-crad); ++i)
03822     {
03823       float sum = 0;
03824       for (int jj = -rrad; jj<=rrad; ++jj)
03825         for (int ii = -crad; ii<=crad; ++ii) {
03826           float sd_sq = sd_image(i+ii, j+jj);
03827           sd_sq *= sd_sq;
03828           sum += sd_sq*ksq[jj+rrad][ii+crad];
03829         }
03830       res(i,j) = vcl_sqrt(sum);
03831     }
03832   return res;
03833 }
03834 
03835 
03836 
03837 
03838 vil_image_view<float> brip_vil_float_ops::
03839 std_dev_operator_method2(vil_image_view<float> const& sd_image,
03840                          vbl_array_2d<float> const& kernel)
03841 {
03842   unsigned ni = sd_image.ni(), nj = sd_image.nj();
03843   unsigned nrows = kernel.rows(), ncols = kernel.cols();
03844   int rrad = (nrows-1)/2, crad = (ncols-1)/2;
03845   float sd_min, sd_max;
03846   vil_math_value_range(sd_image, sd_min, sd_max);
03847 
03848   vil_image_view<float> res(ni, nj);
03849   res.fill(sd_max);
03850 
03851   for (int j = rrad; j<static_cast<int>(nj-rrad); ++j)
03852     for (int i = crad; i<static_cast<int>(ni-crad); ++i)
03853     {
03854       float sum = 0;
03855       for (int jj = -rrad; jj<=rrad; ++jj)
03856         for (int ii = -crad; ii<=crad; ++ii) {
03857           float sd = sd_image(i+ii, j+jj);
03858           sum += (float)(sd*vcl_abs(kernel[jj+rrad][ii+crad]));
03859         }
03860       res(i,j) = sum;
03861     }
03862   return res;
03863 }
03864 
03865 vil_image_view<float>
03866 brip_vil_float_ops::extrema(vil_image_view<float> const& input,
03867                             float lambda0, float lambda1, float theta,
03868                             bool bright, bool mag_only,
03869                             bool output_response_mask,
03870                             bool signed_response, bool scale_invariant,
03871                             bool non_max_suppress, float cutoff_per)
03872 {
03873   assert(!(mag_only&&signed_response));
03874   vbl_array_2d<float> fa;
03875   vbl_array_2d<bool> mask;
03876   brip_vil_float_ops::extrema_kernel_mask(lambda0, lambda1, theta,
03877                                           fa, mask, cutoff_per,
03878                                           scale_invariant);
03879   unsigned nrows = fa.rows(), ncols = fa.cols();
03880   int rj = (nrows-1)/2, ri = (ncols-1)/2;
03881   vbl_array_2d<double> coef(nrows,ncols);
03882   for (unsigned r = 0; r<nrows; ++r)
03883     for (unsigned c = 0; c<ncols; ++c)
03884       coef[r][c]=fa[r][c];
03885 
03886 #if 0
03887   
03888   
03889   vcl_cout << "\ngauss ={";
03890   for (unsigned j = 0; j<nrows; ++j) {
03891     vcl_cout << '{';
03892     for (unsigned i = 0; i<ncols-1; ++i)
03893       vcl_cout << zs(coef[j][i]) << ',';
03894     if (j != nrows-1)
03895       vcl_cout << zs(coef[j][ncols-1]) << "},";
03896     else
03897       vcl_cout << zs(coef[j][ncols-1]) << '}';
03898   }
03899 
03900   vcl_cout << "};\n\nmask ={";
03901   for (unsigned j = 0; j<nrows; ++j) {
03902     vcl_cout << '{';
03903     for (unsigned i = 0; i<ncols-1; ++i)
03904       vcl_cout << mask[j][i] << ',';
03905     if (j != nrows-1)
03906       vcl_cout << mask[j][ncols-1] << "},";
03907     else
03908       vcl_cout << mask[j][ncols-1] << '}';
03909   }
03910   vcl_cout << "};" << vcl_flush;
03911 #endif
03912   
03913   unsigned ni = input.ni(), nj = input.nj();
03914   vil_image_view<float> temp(ni, nj);
03915   vil_image_view<float> temp2(ni, nj);
03916   temp.fill(0.0f); temp2.fill(0.0f);
03917   for (unsigned j = rj; j<(nj-rj); j++)
03918     for (unsigned i = ri; i<(ni-ri); i++) {
03919       double sum = 0;
03920       for (int jj=-rj; jj<=rj; ++jj)
03921         for (int ii=-ri; ii<=ri; ++ii)
03922           if (mask[jj+rj][ii+ri])
03923             sum += coef[jj+rj][ii+ri]*input(i+ii, j+jj);
03924       temp2(i,j) = static_cast<float>(sum);
03925       if (mag_only) {
03926         temp(i,j) = static_cast<float>(vcl_fabs(sum));
03927       }
03928       else if (bright) { 
03929         if (sum<0) temp(i,j) = static_cast<float>(-sum);
03930       }
03931       else {
03932         if (sum>0) temp(i,j) = static_cast<float>(sum);
03933       }
03934     }
03935   
03936   vil_image_view<float> res(temp);
03937   if (non_max_suppress)
03938     for (unsigned j = rj; j<(nj-rj); j++)
03939       for (unsigned i = ri; i<(ni-ri); i++)
03940       {
03941         float cv = temp(i,j);
03942         for (int jj=-rj; jj<=rj; ++jj)
03943           for (int ii=-ri; ii<=ri; ++ii)
03944             if ((ii!=0||jj!=0) && mask[jj+rj][ii+ri] && temp(i+ii, j+jj)>cv)
03945               res(i,j)=0.0f;
03946       }
03947   if (!output_response_mask&&!signed_response)
03948     return res;
03949   unsigned np = 2;
03950   if (output_response_mask&&signed_response)
03951     np = 3;
03952   
03953   vil_image_view<float> res_mask(ni, nj, np);
03954   res_mask.fill(0.0f);
03955   
03956   for (unsigned j = rj; j<(nj-rj); j++)
03957     for (unsigned i = ri; i<(ni-ri); i++)
03958     {
03959       float rv = res(i,j);
03960       res_mask(i,j,0)=rv;
03961     }
03962   
03963   if (output_response_mask) {
03964     for (unsigned j = rj; j<(nj-rj); j++)
03965       for (unsigned i = ri; i<(ni-ri); i++)
03966       {
03967         float rv = res(i,j);
03968         if (!rv)
03969           continue;
03970         for (int jj=-rj; jj<=rj; ++jj)
03971           for (int ii=-ri; ii<=ri; ++ii)
03972             if (mask[jj+rj][ii+ri])
03973               if (rv>res_mask(i+ii,j+jj,1))
03974                 res_mask(i+ii,j+jj,1) = rv;
03975       }
03976   }
03977   
03978   if (signed_response) {
03979     unsigned p = np-1;
03980     for (unsigned j = rj; j<(nj-rj); j++)
03981       for (unsigned i = ri; i<(ni-ri); i++)
03982         res_mask(i,j,p) = temp2(i,j);
03983   }
03984   return res_mask;
03985 }
03986 
03987 
03988 
03989 
03990 vil_image_view<float> brip_vil_float_ops::
03991 extrema_rotational(vil_image_view<float> const& input, float lambda0,
03992                    float lambda1, float theta_interval, bool bright,
03993                    bool mag_only, bool signed_response,
03994                    bool scale_invariant, bool non_max_suppress,
03995                    float cutoff_per)
03996 {
03997   
03998   assert(!(mag_only&&signed_response));
03999 
04000   unsigned ni = input.ni();
04001   unsigned nj = input.nj();
04002 
04003   vil_image_view<float> output(ni, nj, 3); 
04004   output.fill(0.0f);
04005 
04006   if (lambda0 == lambda1) {  
04007     vil_image_view<float> res_mask_current =
04008       extrema(input, lambda0, lambda1, 0.0f, bright, mag_only,
04009               true, signed_response, scale_invariant,
04010               non_max_suppress, cutoff_per);
04011     unsigned np = res_mask_current.nplanes();
04012     for (unsigned j = 0; j<nj; j++)
04013       for (unsigned i = 0; i<ni; i++) {
04014         if (!signed_response)
04015           output(i,j,0) = res_mask_current(i,j,0);  
04016         else
04017           output(i,j,0) = res_mask_current(i,j,np-1);
04018         output(i,j,1) = 0.0f;
04019         output(i,j,2) = res_mask_current(i,j,1);
04020       }
04021     return output;
04022   }
04023 
04024   
04025   
04026   if (lambda0 < lambda1) {
04027     vcl_cout << "In brip_vil_float_ops::extrema_rotational() - ERROR! rotational extrema operator requires lambda0 to be larger than lambda1! switch the lambdas and use the output angle map accordingly!\n";
04028     throw 0;
04029   }
04030   if (theta_interval < vcl_numeric_limits<float>::epsilon()) {
04031     vcl_cout << "In brip_vil_float_ops::extrema_rotational() - ERROR! theta_interval needs to be larger than 0!\n";
04032     throw 0;
04033   }
04034 
04035   vil_image_view<float> res_img(ni, nj);
04036   vil_image_view<int> res_angle(ni, nj);
04037   res_img.fill(0.0f); res_angle.fill(0);
04038 
04039   vcl_vector<float> angles;
04040   angles.push_back(-1.0f);
04041   for (float theta = 0.0f; theta < 180.0f; theta += theta_interval) { angles.push_back(theta); }
04042 
04043   vcl_vector<vbl_array_2d<bool> > mask_vect(angles.size(), vbl_array_2d<bool>());
04044   int max_rji = 0;
04045   
04046   float theta = 0.0f; unsigned theta_i = 1;
04047   for ( ; theta < 180; theta += theta_interval, theta_i++)
04048   {
04049     
04050     vbl_array_2d<float> fa; vbl_array_2d<bool> mask;
04051     brip_vil_float_ops::extrema_kernel_mask(lambda0, lambda1, theta,
04052                                             fa, mask, cutoff_per, scale_invariant);
04053     mask_vect[theta_i] = mask;
04054     unsigned nrows = fa.rows(), ncols = fa.cols();
04055     int rj = (nrows-1)/2, ri = (ncols-1)/2;
04056     if (rj > max_rji) max_rji = rj;
04057     if (ri > max_rji) max_rji = ri;
04058     for (unsigned j = rj; j<(nj-rj); j++) {
04059       for (unsigned i = ri; i<(ni-ri); i++) {
04060         float res = 0.0f;
04061         double sum = 0;
04062         for (int jj=-rj; jj<=rj; ++jj)
04063           for (int ii=-ri; ii<=ri; ++ii)
04064             if (mask[jj+rj][ii+ri]) {
04065               sum += double(fa[jj+rj][ii+ri])*input(i+ii, j+jj);
04066             }
04067         if (mag_only) {
04068           res = static_cast<float>(vcl_fabs(sum));
04069         }
04070         else if (signed_response) {
04071           res = static_cast<float>(sum);
04072         }
04073         else if (bright) { 
04074           if (sum<0) res = static_cast<float>(-sum);
04075         }
04076         else {
04077           if (sum>0) res = static_cast<float>(sum);
04078         }
04079         
04080         if (vcl_fabs(res_img(i,j)) < vcl_fabs(res)) {
04081           res_img(i,j) = res;
04082           res_angle(i,j) = theta_i;
04083         }
04084       }
04085     }
04086     vcl_cout << '.';
04087   }
04088   vcl_cout << '\n';
04089   if (!non_max_suppress) return res_img;
04090   
04091   vil_image_view<float> res(res_img);
04092 
04093   for (unsigned j = max_rji; j<(nj-max_rji); j++)
04094     for (unsigned i = max_rji; i<(ni-max_rji); i++)
04095     {
04096       float cv = res_img(i,j);
04097       if (!cv)
04098         continue;
04099       int theta_i = res_angle(i,j);
04100       vbl_array_2d<bool> mask = mask_vect[theta_i];
04101       unsigned nrows = mask.rows(), ncols = mask.cols();
04102       int rj = (nrows-1)/2, ri = (ncols-1)/2;
04103 
04104       bool max = true;
04105       for (int jj=-rj; jj<=rj; ++jj) {
04106         for (int ii=-ri; ii<=ri; ++ii) {
04107           if ((ii!=0||jj!=0) && mask[jj+rj][ii+ri] && res_img(i+ii, j+jj)>cv) {
04108             max = false;
04109             break;
04110           }
04111         }
04112         if (!max)
04113           break;
04114       }
04115       if (!max) {
04116         res(i,j) = 0.0f;
04117         res_angle(i, j) = 0; 
04118       }
04119     }
04120 
04121   vil_image_view<float> res_mask(ni, nj);
04122   res_mask.fill(0.0f);
04123   
04124   for (unsigned j = max_rji; j<(nj-max_rji); j++)
04125     for (unsigned i = max_rji; i<(ni-max_rji); i++)
04126     {
04127       float rv = res(i,j);
04128       if (!rv)
04129         continue;
04130       int theta_i = res_angle(i,j);
04131       
04132       vbl_array_2d<bool> mask = mask_vect[theta_i];
04133       unsigned nrows = mask.rows(), ncols = mask.cols();
04134       int rj = (nrows-1)/2, ri = (ncols-1)/2;
04135 
04136       for (int jj=-rj; jj<=rj; ++jj)
04137         for (int ii=-ri; ii<=ri; ++ii)
04138           if (mask[jj+rj][ii+ri])
04139             if (rv>res_mask(i+ii,j+jj))
04140               res_mask(i+ii,j+jj) = rv;
04141     }
04142 
04143   
04144   for (unsigned j = max_rji; j<(nj-max_rji); j++)
04145     for (unsigned i = max_rji; i<(ni-max_rji); i++)
04146     {
04147       output(i,j,0) = res(i,j);
04148       output(i,j,1) = angles[res_angle(i,j)];
04149       output(i,j,2) = res_mask(i,j);
04150     }
04151   return output;
04152 }
04153 
04154 
04155 
04156 float brip_vil_float_ops::elu(float phi, float lamda0,
04157                               float lambda1, float theta)
04158 {
04159   double sp = vcl_sin(phi), cp = vcl_cos(phi);
04160   double st = vcl_sin(theta), ct = vcl_cos(theta);
04161   double temp = 3.0*lamda0*cp*ct-3.0*lambda1*sp*st;
04162   return static_cast<float>(temp);
04163 }
04164 
04165 
04166 float brip_vil_float_ops::elv(float phi, float lamda0,
04167                               float lambda1, float theta)
04168 {
04169   double sp = vcl_sin(phi), cp = vcl_cos(phi);
04170   double st = vcl_sin(theta), ct = vcl_cos(theta);
04171   double temp = 3.0*lamda0*st*cp + 3.0*lambda1*sp*ct;
04172   return static_cast<float>(temp);
04173 }
04174 
04175 
04176 void brip_vil_float_ops::
04177 max_inscribed_rect(float lambda0, float lambda1, float theta,
04178                    float& u_rect, float& v_rect)
04179 {
04180   float sign = -1.0f;
04181   if (theta<0) sign = 1.0f;
04182   float th_rad = static_cast<float>(theta*vnl_math::pi_over_180);
04183   float maxa = 0.0f, max_phi = 0.0f;
04184   for (float phi = -float(vnl_math::pi); phi<=float(vnl_math::pi); phi+=0.01f)
04185   {
04186     float a = (1.0f+brip_vil_float_ops::elu(phi, lambda0, lambda1, th_rad));
04187     a *= (1.0f+ sign*brip_vil_float_ops::elv(phi, lambda0, lambda1, th_rad));
04188     if (a>maxa)
04189     {
04190       maxa = a;
04191       max_phi = phi;
04192     }
04193   }
04194   u_rect = brip_vil_float_ops::elu(max_phi, lambda0, lambda1, th_rad);
04195   v_rect = brip_vil_float_ops::elv(max_phi, lambda0, lambda1, th_rad);
04196   v_rect = vcl_fabs(v_rect);
04197 }
04198 
04199 static void eu(float lambda0, float cutoff_per, vcl_vector<float>& kernel)
04200 {
04201   kernel.clear();
04202   double l_sqi = 1/(lambda0*lambda0);
04203   double norm = 1/vcl_sqrt(2.0*vnl_math::pi);
04204   norm /= lambda0;
04205   int r = static_cast<int>(vcl_sqrt((-2.0*vcl_log(cutoff_per))/l_sqi)+0.5);
04206   for (int i = -r; i<=r; ++i)
04207   {
04208     double k = vcl_exp(-0.5*i*i*l_sqi);
04209     k*=norm;
04210     kernel.push_back(static_cast<float>(k));
04211   }
04212 }
04213 
04214 static void ev(float lambda1, float cutoff_per, bool scale_invariant,
04215                vcl_vector<float>& kernel)
04216 {
04217   kernel.clear();
04218   double l1_sqi = 1/(lambda1*lambda1);
04219   int r = static_cast<int>(vcl_sqrt((-2.0*vcl_log(cutoff_per))/l1_sqi)+0.5);
04220   double norm = scale_invariant ? 1/lambda1 : l1_sqi/lambda1;
04221   norm /= vcl_sqrt(2.0*vnl_math::pi);
04222   for (int i = -r; i<=r; ++i)
04223   {
04224     double s = i*i*l1_sqi;
04225     double k = vcl_exp(-0.5*s);
04226     k *= norm*(s-1.0);
04227     kernel.push_back(static_cast<float>(k));
04228   }
04229 }
04230 
04231 static vil_image_view<float> convolve_u(vil_image_view<float> const& image,
04232                                         vcl_vector<float> const& kernel,
04233                                         bool initialize = true)
04234 {
04235   int nk = kernel.size();
04236   if (nk<3)
04237     return image;
04238   int ni = image.ni(), nj = image.nj();
04239   int ru = (nk-1)/2;
04240   vil_image_view<float> Iu(ni, nj);
04241   if (initialize) Iu.fill(0.0f);
04242   for (int j = 0; j<nj; ++j)
04243     for (int i = ru; i<ni-ru; ++i) {
04244       float sum = 0.0f;
04245       for (int k = -ru; k<=ru; ++k)
04246       {
04247         float v = image(i+k, j);
04248         sum += kernel[k+ru]*v;
04249       }
04250       Iu(i,j) = sum;
04251     }
04252   return Iu;
04253 }
04254 
04255 static vil_image_view<float> convolve_v(vil_image_view<float> const& image,
04256                                         vcl_vector<float> const& kernel,
04257                                         bool initialize = true)
04258 {
04259   int nk = kernel.size();
04260   if (nk<3)
04261     return image;
04262   int ni = image.ni(), nj = image.nj();
04263   int rv = (nk-1)/2;
04264   vil_image_view<float> Iv(ni, nj);
04265   if (initialize) Iv.fill(0.0f);
04266   for (int j = rv; j<nj-rv; ++j)
04267     for (int i = 0; i<ni; ++i) {
04268       float sum = 0.0f;
04269       for (int k = -rv; k<=rv; ++k)
04270       {
04271         float v = image(i, j+k);
04272         sum += kernel[k+rv]*v;
04273       }
04274       Iv(i,j) = sum;
04275     }
04276   return Iv;
04277 }
04278 
04279 
04280 
04281 static void rotation_offset(int ni, int nj, float theta_deg,
04282                             int i, int j, int& ti, int& tj)
04283 {
04284   ti= 0; tj = 0;
04285   double deg_to_rad = vnl_math::pi_over_180;
04286   double rang = deg_to_rad*theta_deg;
04287   vgl_h_matrix_2d<double> H;
04288   H.set_identity().set_rotation(rang);
04289   vsol_box_2d_sptr input_roi;
04290   vsol_polygon_2d_sptr input_poly, output_poly;
04291   input_roi = new vsol_box_2d();
04292   input_roi->add_point(0, 0);
04293   input_roi->add_point(ni, nj);
04294   input_poly = bsol_algs::poly_from_box(input_roi);
04295   if (!bsol_algs::homography(input_poly, H, output_poly))
04296     return;
04297   vsol_box_2d_sptr temp = output_poly->get_bounding_box();
04298   vgl_h_matrix_2d<double> t; t.set_identity().set_translation(-temp->get_min_x(),-temp->get_min_y());
04299   vgl_homg_point_2d<double> torg = (t*H)*vgl_homg_point_2d<double>(double(i),double(j));
04300   ti = static_cast<int>(torg.x());
04301   tj = static_cast<int>(torg.y());
04302 }
04303 
04304 vil_image_view<float> brip_vil_float_ops::
04305 fast_extrema(vil_image_view<float> const& input, float lambda0, float lambda1,
04306              float theta, bool bright, bool mag_only,bool output_response_mask,
04307              bool signed_response, bool scale_invariant, bool non_max_suppress,
04308              float cutoff)
04309 {
04310   
04311   assert(!(mag_only&&signed_response));
04312   
04313   vcl_vector<float> euk, evk;
04314   eu(lambda0, cutoff, euk);
04315   ev(lambda1, cutoff, scale_invariant, evk);
04316   vil_image_view<float> pre_res;
04317   int tuf=0, tvf=0, tui=0, tvi=0;
04318   vil_image_view<float> rot = input;
04319   bool ang90 = theta==90.0f||theta == 270.0f||
04320     theta ==-90.0f||theta == -270.0f;
04321   
04322   if (theta!=0&&!ang90)
04323     rot = brip_vil_float_ops::rotate(input, -theta);
04324   if (!ang90) {
04325     
04326     vil_image_view<float> rotu = convolve_u(rot, euk);
04327     
04328     vil_image_view<float> rotuv = convolve_v(rotu, evk);
04329     
04330     if (theta!=0)
04331     {
04332       pre_res = brip_vil_float_ops::rotate(rotuv, +theta);
04333       
04334       
04335       rotation_offset(input.ni(), input.nj(), -theta, 0, 0, tuf, tvf);
04336       rotation_offset(rotuv.ni(), rotuv.nj(), +theta, tuf, tvf, tui, tvi);
04337     }
04338     else pre_res = rotuv;
04339   }
04340   else {
04341     
04342     vil_image_view<float> rotv = convolve_v(rot, euk);
04343     
04344     vil_image_view<float> rotvu = convolve_u(rotv, evk);
04345     pre_res = rotvu;
04346   }
04347   int ni = input.ni(), nj = input.nj();
04348   vil_image_view<float> res(ni, nj);
04349   res.fill(0.0f);
04350   vil_image_view<float> temp2(ni, nj);
04351   temp2.fill(0.0f);
04352   for (int j = 0; j<nj; ++j)
04353     for (int i = 0; i<ni; ++i)
04354     {
04355       float v = pre_res(i + tui, j+ tvi);
04356       if (mag_only) {
04357         res(i,j) = vcl_fabs(v);
04358       }
04359       else if (bright) { 
04360         if (v<0) res(i,j) = -v;
04361       }
04362       else {
04363         if (v>0) res(i,j) = v;
04364       }
04365       temp2(i,j) = v;
04366     }
04367   if (!non_max_suppress && !output_response_mask) {
04368     return signed_response ? temp2 : res;
04369   }
04370   
04371   
04372   
04373   
04374   
04375   
04376   float u_rect, v_rect;
04377   brip_vil_float_ops::max_inscribed_rect(lambda0,lambda1,theta,u_rect,v_rect);
04378   int ni_rect = static_cast<int>(u_rect);
04379   int nj_rect = static_cast<int>(v_rect);
04380   vil_image_view<float> res_sup(ni, nj);
04381   res_sup.fill(0.0f);
04382   for ( int i= ni_rect; i< ni-ni_rect; i+= ni_rect+1 )
04383     for ( int j = nj_rect; j < nj-nj_rect; j += nj_rect+1 ) {
04384       int ci= i, cj = j;
04385       bool find_response = false;
04386       for ( int di= 0; di<= ni_rect; di++ )
04387         for ( int dj = 0; dj <= nj_rect; dj++ )
04388         {
04389           float v = res(ci,cj);
04390           float dv = res(i+di,j+dj);
04391           if (v==0.0f&&dv==0.0f) continue;
04392           find_response = true;
04393           if ( v < dv )
04394           {
04395             ci= i+di;
04396             cj = j+dj;
04397           }
04398         }
04399       if (!find_response)
04400         continue;
04401       res_sup(ci,cj) = res(ci,cj);
04402     }
04403 
04404   
04405   vbl_array_2d<float> kern;
04406   vbl_array_2d<bool> mask;
04407   brip_vil_float_ops::extrema_kernel_mask(lambda0, lambda1, theta, kern, mask);
04408   int ri = (kern.cols()-1)/2, rj = (kern.rows()-1)/2;
04409   
04410   
04411   
04412   for (int j = rj; j<(nj-rj); j++)
04413     for (int i = ri; i<(ni-ri); i++)
04414     {
04415       float v = res_sup(i,j);
04416       if (v==0.0f) continue;
04417       for (int jj=-rj; jj<=rj; ++jj)
04418         for (int ii=-ri; ii<=ri; ++ii)
04419           if (mask[rj+jj][ri+ii] && res_sup(i+ii, j+jj)<v)
04420             res_sup(i+ii,j+jj)=0.0f;
04421     }
04422 
04423   if (!output_response_mask&&!signed_response)
04424     return res_sup;
04425   unsigned np = 2;
04426   if (output_response_mask&&signed_response)
04427     np = 3;
04428   
04429 
04430   vil_image_view<float> res_mask(ni, nj, np);
04431   res_mask.fill(0.0f);
04432   
04433   for (int j = rj; j<(nj-rj); j++)
04434     for (int i = ri; i<(ni-ri); i++)
04435     {
04436       float rv = res_sup(i,j);
04437       res_mask(i,j,0)=rv;
04438     }
04439   
04440   if (output_response_mask) {
04441     for (int j = rj; j<(nj-rj); j++)
04442       for (int i = ri; i<(ni-ri); i++)
04443       {
04444         float rv = res_sup(i,j);
04445         if (!rv)
04446           continue;
04447         for (int jj=-rj; jj<=rj; ++jj)
04448           for (int ii=-ri; ii<=ri; ++ii)
04449             if (mask[jj+rj][ii+ri])
04450               if (rv>res_mask(i+ii,j+jj,1))
04451                 res_mask(i+ii,j+jj,1) = rv;
04452       }
04453   }
04454   
04455   if (signed_response) {
04456     unsigned p = np-1;
04457     for (int j = rj; j<(nj-rj); j++)
04458       for (int i = ri; i<(ni-ri); i++)
04459         res_mask(i,j,p) = temp2(i,j);
04460   }
04461   return res_mask;
04462 }
04463 
04464 vil_image_view<float> brip_vil_float_ops::
04465 fast_extrema_rotational(vil_image_view<float> const& input,
04466                         float lambda0, float lambda1,
04467                         float theta_interval,
04468                         bool bright, bool mag_only,
04469                         bool signed_response, bool scale_invariant,
04470                         bool non_max_suppress,
04471                         float cutoff) {
04472   unsigned ni = input.ni(), nj = input.nj();
04473   vil_image_view<float> resp(ni, nj);
04474   resp.fill(0.0f);
04475 
04476     
04477   float theta = 0; unsigned theta_i = 1;
04478   for (; theta < 180; theta += theta_interval, theta_i++)
04479   {
04480    vil_image_view<float> temp =
04481      fast_extrema(input, lambda0, lambda1, theta, bright,
04482                   mag_only, false, signed_response,
04483                   scale_invariant, false, cutoff);
04484     for (unsigned j = 0; j<nj; ++j)
04485       for (unsigned i = 0; i<ni; ++i) {
04486         float v = temp(i,j);
04487         if (vcl_fabs(v)>vcl_fabs(resp(i,j)))
04488           resp(i,j) = v;
04489       }
04490   }
04491   return resp;
04492 }