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 }