Go to the documentation of this file.00001
00002 #include "vifa_parallel.h"
00003
00004
00005 #include <vnl/vnl_math.h>
00006 #include <vdgl/vdgl_digital_curve.h>
00007 #include <vsol/vsol_curve_2d.h>
00008 #include <vtol/vtol_edge_2d.h>
00009 #include <vtol/vtol_vertex_2d.h>
00010 #include <vtol/vtol_intensity_face.h>
00011 #include "vifa_gaussian.h"
00012
00013 #ifdef DUMP
00014 #include <vul/vul_sprintf.h>
00015 #include <vcl_fstream.h>
00016
00017 static int pass = 0;
00018 #endif
00019
00020 const float n_sigma = 2.0;
00021
00022
00023 vifa_parallel::
00024 vifa_parallel(iface_list& faces,
00025 bool contrast_weighted,
00026 vifa_parallel_params* params) :
00027 vifa_parallel_params(params)
00028 {
00029 raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00030 float range = max_angle - min_angle;
00031
00032 for (iface_iterator ifi = faces.begin(); ifi != faces.end(); ++ifi)
00033 {
00034 edge_list edges; (*ifi)->edges(edges);
00035
00036 for (edge_iterator ei = edges.begin(); ei != edges.end(); ei++)
00037 {
00038 vtol_edge_2d* e = (*ei)->cast_to_edge_2d();
00039
00040 if (e)
00041 {
00042 #ifdef OLD_LINE_APPROX
00043 const vtol_vertex_2d* v1 = e->v1()->cast_to_vertex_2d();
00044 const vtol_vertex_2d* v2 = e->v2()->cast_to_vertex_2d();
00045 double dy = v1->y() - v2->y();
00046 double dx = v1->x() - v2->x();
00047 double length = 0.0;
00048
00049 if (contrast_weighted)
00050 {
00051 vtol_intensity_face_sptr other_f = get_adjacent_iface(*ifi, e);
00052
00053 if (other_f)
00054 length = vcl_sqrt((dx * dx) + (dy * dy))
00055 * vcl_fabs((*ifi)->Io() - other_f->Io());
00056 }
00057
00058 double orientation = vcl_atan2(dy, dx) * vnl_math::deg_per_rad;
00059 if (orientation < 0)
00060 orientation += 180.0;
00061
00062 float theta = map_x(float(orientation));
00063 raw_h_->SetCount(theta, raw_h_->GetCount(theta) + float(length));
00064 #else
00065 vsol_curve_2d_sptr c = e->curve();
00066
00067 if (c)
00068 {
00069 vdgl_digital_curve* dc = c->cast_to_vdgl_digital_curve();
00070
00071 if (dc)
00072 {
00073 double l = dc->length();
00074
00075 for (int i = 0; i < l; i++)
00076 {
00077
00078 double theta = dc->get_theta(i / l);
00079 #ifdef DEBUG
00080 vcl_cout << "raw theta: " << theta;
00081 #endif
00082 while (theta < min_angle)
00083 theta += range;
00084
00085 while (theta > max_angle)
00086 theta -= range;
00087 #ifdef DEBUG
00088 vcl_cout << " to " << theta << vcl_endl;
00089 #endif
00090 raw_h_->UpCount(float(theta));
00091 }
00092 }
00093 }
00094 #endif // OLD_LINE_APPROX
00095 }
00096 }
00097 }
00098
00099 norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00100 }
00101
00102
00103 vifa_parallel::
00104 vifa_parallel(vcl_vector<float>& pixel_orientations,
00105 vifa_parallel_params* params) :
00106 vifa_parallel_params(params)
00107 {
00108 raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00109 float range = max_angle - min_angle;
00110
00111 for (vcl_vector<float>::iterator p = pixel_orientations.begin();
00112 p != pixel_orientations.end(); ++p)
00113 {
00114 float theta = (*p);
00115
00116 while (theta < min_angle)
00117 {
00118 theta += range;
00119 }
00120 while (theta > max_angle)
00121 {
00122 theta -= range;
00123 }
00124
00125 raw_h_->UpCount(theta);
00126 }
00127
00128 norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00129 }
00130
00131 vifa_parallel::
00132 vifa_parallel(float center_angle,
00133 float std_dev)
00134 {
00135 raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00136
00137 #ifdef DEBUG
00138 vcl_cout << "vifa_parallel(): 0.5 is "<< raw_h_->GetValIndex(0.5) << vcl_endl;
00139 #endif
00140
00141 vifa_gaussian g(center_angle, std_dev);
00142 for (float i = min_angle; i < 2 * max_angle; i++)
00143 {
00144 float v = g.pdf(i);
00145 float vx = map_x(i);
00146
00147 raw_h_->SetCount(vx, raw_h_->GetCount(vx) + v);
00148 }
00149
00150 norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00151 }
00152
00153 vifa_parallel::~vifa_parallel()
00154 {
00155 delete raw_h_;
00156 delete norm_h_;
00157 }
00158
00159 void vifa_parallel::reset(void)
00160 {
00161 delete norm_h_;
00162 norm_h_ = normalize_histogram(raw_h_);
00163 }
00164
00165 vifa_histogram* vifa_parallel::
00166 get_raw_hist(void)
00167 {
00168 return raw_h_;
00169 }
00170
00171 vifa_histogram* vifa_parallel::
00172 get_norm_hist(void)
00173 {
00174 return norm_h_;
00175 }
00176
00177 void vifa_parallel::
00178 map_gaussian(float& max_angle,
00179 float& std_dev,
00180 float& scale)
00181 {
00182 bool set_min_res_flag = true;
00183
00184 const float incr = 3.0;
00185 float max_value;
00186 float local_max_angle = find_peak(max_value);
00187 max_angle = 0.0;
00188 std_dev = 0.0;
00189 scale = 0.0;
00190
00191
00192 if (local_max_angle != -1.0)
00193 {
00194 float min_residual = 0.f;
00195
00196 for (float j=-(n_sigma+1); j<=(n_sigma+1); j++)
00197 {
00198 float new_center = map_x(local_max_angle + (j * incr));
00199 float local_std_dev = 0.0;
00200
00201 for (int i = 0; i < 5; i++)
00202 {
00203 local_std_dev += incr;
00204 vifa_gaussian g(new_center, local_std_dev);
00205 float g_max = g.pdf(new_center);
00206 float local_scale = norm_h_->GetCount(new_center) /
00207 g_max;
00208
00209
00210 #ifdef DUMP
00211 char buf[25];
00212 vul_sprintf(buf, "gauss-%d-%d-%d.dat", pass, (int)j, i);
00213 vcl_ofstream gdump(buf);
00214 #endif
00215
00216 float sample_sum = 0.0;
00217
00218 for (float dx = (-n_sigma * local_std_dev);
00219 dx <= (n_sigma * local_std_dev);
00220 dx += norm_h_->GetBucketSize())
00221 {
00222 float vx = new_center + dx;
00223 float e = g.pdf(vx) * local_scale;
00224
00225 float x = map_x(vx);
00226 float f = norm_h_->GetCount(x);
00227 if (f < 0)
00228 {
00229 f = 0;
00230 }
00231
00232 float diff = vcl_fabs(f - e);
00233
00234 #ifdef DUMP
00235 gdump << x << ' ' << e << ' ' << diff << ' ' << vx << ' ' << f << vcl_endl;
00236 #endif
00237 if (e != 0.0)
00238 {
00239 sample_sum += ((diff * diff) / e);
00240
00241 }
00242 }
00243
00244
00245 if ((set_min_res_flag || sample_sum < min_residual) && sample_sum != 0)
00246 {
00247 set_min_res_flag = false;
00248 min_residual = sample_sum;
00249 std_dev = local_std_dev;
00250 max_angle = new_center;
00251 scale = local_scale;
00252
00253 #ifdef DEBUG
00254 vcl_cout << "*** ";
00255 #endif
00256 }
00257
00258 #ifdef DEBUG
00259 vcl_cout << j << " gaussian " << i << " residual "
00260 << sample_sum << " sample count " << sample_count << vcl_endl;
00261 #endif
00262 }
00263 }
00264
00265 #ifdef DEBUG
00266 vcl_cout << "best is at " << max_angle << " sd of " << std_dev
00267 << " scale " << scale << vcl_endl;
00268 #endif
00269
00270 #ifdef DUMP
00271 pass++;
00272 #endif
00273 }
00274 }
00275
00276 void vifa_parallel::
00277 remove_gaussian(float max_angle,
00278 float std_dev,
00279 float scale)
00280 {
00281
00282 if (norm_h_->GetMaxCount() != 0.0)
00283 {
00284 vifa_gaussian g(max_angle, std_dev);
00285 for (float dx = (-n_sigma * std_dev);
00286 dx <= (n_sigma * std_dev);
00287 dx += norm_h_->GetBucketSize())
00288 {
00289 float vx = max_angle + dx;
00290 float e = g.pdf(vx) * scale;
00291 float x = map_x(vx);
00292 float f = norm_h_->GetCount(x);
00293
00294 if (f >= 0)
00295 {
00296 float new_val = ((f - e) < 0) ? 0 : (f - e);
00297
00298 #ifdef DEBUG
00299 vcl_cout << " --- " << x << ": " << f <<" to " << new_val << vcl_endl;
00300 #endif
00301
00302 norm_h_->SetCount(x, new_val);
00303 }
00304 else
00305 {
00306 vcl_cerr << " --- " << x << ": bad " <<
00307 norm_h_->GetValIndex(x) << vcl_endl;
00308 }
00309 }
00310 }
00311 }
00312
00313 void vifa_parallel::
00314 snapshot(char* fname)
00315 {
00316 norm_h_->WritePlot(fname);
00317 }
00318
00319 float vifa_parallel::
00320 area(void)
00321 {
00322 if (norm_h_->GetMaxCount() == 0.0)
00323 {
00324
00325 return 0.0;
00326 }
00327 else
00328 {
00329 return norm_h_->ComputeArea();
00330 }
00331 }
00332
00333 float vifa_parallel::
00334 bin_variance(void)
00335 {
00336 float* counts = norm_h_->GetCounts();
00337 int res = norm_h_->GetRes();
00338 float sum = 0;
00339 float sum2 = 0;
00340
00341 for (int i = 0; i < res; i++)
00342 {
00343 sum += counts[i];
00344 sum2 += (counts[i] * counts[i]);
00345 }
00346
00347 float mean = sum / res;
00348 float var = (sum2 / res) - (mean * mean);
00349
00350 return var;
00351 }
00352
00353 float vifa_parallel::
00354 map_x(float raw_x)
00355 {
00356 float range = max_angle - min_angle + 1;
00357
00358 while (raw_x < min_angle)
00359 {
00360 raw_x += range;
00361 }
00362 while (raw_x > max_angle)
00363 {
00364 raw_x -= range;
00365 }
00366
00367 return raw_x;
00368 }
00369
00370 vifa_histogram* vifa_parallel::
00371 normalize_histogram(vifa_histogram* h)
00372 {
00373 vifa_histogram* norm = new vifa_histogram(nbuckets, min_angle, max_angle);
00374 int nbuckets = h->GetRes();
00375 float area = h->ComputeArea();
00376 float* x_vals = h->GetVals();
00377 float* y_vals = h->GetCounts();
00378
00379 for (int i = 0; i < nbuckets; i++)
00380 {
00381 float new_area = y_vals[i] / area;
00382 norm->SetCount(x_vals[i], new_area);
00383 }
00384
00385 return norm;
00386 }
00387
00388 float vifa_parallel::
00389 find_peak(float& max_value)
00390 {
00391 int nbuckets = norm_h_->GetRes();
00392 float* x_vals = norm_h_->GetVals();
00393 float* y_vals = norm_h_->GetCounts();
00394 int max_index = -1;
00395 max_value = -1;
00396
00397 for (int i = 0; i < nbuckets; i++)
00398 {
00399 if (y_vals[i] > max_value)
00400 {
00401 max_index = i;
00402 max_value = y_vals[i];
00403 }
00404 }
00405
00406 if (max_index == -1)
00407 {
00408 return -1;
00409 }
00410
00411 max_value = y_vals[max_index];
00412 return x_vals[max_index];
00413 }
00414
00415 vtol_intensity_face_sptr vifa_parallel::
00416 get_adjacent_iface(vtol_intensity_face_sptr known_face,
00417 vtol_edge_2d* e)
00418 {
00419 vtol_intensity_face_sptr adj_face = 0;
00420 face_list faces; e->faces(faces);
00421
00422
00423 if (faces.size() == 2)
00424 {
00425 vtol_intensity_face* f1 = faces[0]->cast_to_intensity_face();
00426 vtol_intensity_face* f2 = faces[1]->cast_to_intensity_face();
00427
00428 if (f1 && f2)
00429 {
00430 if (*known_face == *f1)
00431 {
00432 adj_face = f2;
00433 }
00434 else if (*known_face == *f2)
00435 {
00436 adj_face = f1;
00437 }
00438 else
00439 {
00440
00441
00442 }
00443 }
00444 }
00445 return adj_face;
00446 }