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