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