2 ///////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify //
4 // it under the terms of the version 3 of the GNU General Public License //
5 // as published by the Free Software Foundation. //
7 // This program is distributed in the hope that it will be useful, but //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
10 // General Public License for more details. //
12 // You should have received a copy of the GNU General Public License //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
15 // Written by Francois Fleuret //
16 // (C) Idiap Research Institute //
18 // Contact <francois.fleuret@idiap.ch> for comments & bug reports //
19 ///////////////////////////////////////////////////////////////////////////
21 #include "pi_feature.h"
24 #include "rectangle.h"
26 int PiFeature::random_registration_mode(int level) {
28 switch(int(6 * drand48())) {
31 return PiReferential::RM_HEAD;
36 return PiReferential::RM_BELLY;
41 return PiReferential::RM_HEAD_BELLY;
46 return PiReferential::RM_HEAD_BELLY_EDGES;
59 void PiFeature::randomize_window(int registration_mode, Rectangle *window) {
60 scalar_t xc, yc, w, h;
63 xc = 2 * drand48() - 1.0;
64 yc = 2 * drand48() - 1.0;
68 // If we are in a non-rotating frame, allow rectangular window,
69 // otherwise force it to be squared
71 if(registration_mode == PiReferential::RM_HEAD ||
72 registration_mode == PiReferential::RM_BELLY ||
73 registration_mode == PiReferential::RM_HEAD_NO_POLARITY ||
74 registration_mode == PiReferential::RM_BELLY_NO_POLARITY) {
79 } while(w < global.pi_feature_window_min_size ||
80 h < global.pi_feature_window_min_size ||
81 xc - w/2 < -1.0 || xc + w/2 > 1.0 ||
82 yc - h/2 < -1.0 || yc + h/2 > 1.0);
84 window->xmin = xc - w/2;
85 window->ymin = yc - h/2;
86 window->xmax = xc + w/2;
87 window->ymax = yc + h/2;
90 //////////////////////////////////////////////////////////////////////
91 // PF_EDGE_THRESHOLDING
93 scalar_t PiFeature::response_edge_thresholding(RichImage *image,
94 PiReferential *referential) {
95 Rectangle registered_window_a;
97 referential->register_rectangle(_registration_a,
99 ®istered_window_a);
101 int tag = referential->register_edge(_registration_a, _tag);
103 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
104 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
105 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
106 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
108 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
112 ASSERT((tag >= RichImage::first_edge_tag &&
113 tag < RichImage::first_edge_tag + RichImage::nb_edge_tags) ||
114 tag == RichImage::variance_tag);
116 if(tag != RichImage::variance_tag) {
117 ne = scalar_t(image->nb_tags_in_window(scale, tag,
118 xmin_a, ymin_a, xmax_a, ymax_a));
119 nt = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
120 xmin_a, ymin_a, xmax_a, ymax_a) + 1);
122 ne = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
123 xmin_a, ymin_a, xmax_a, ymax_a));
124 nt = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a)) + 1;
130 void PiFeature::draw_edge_thresholding(RGBImage *image,
132 PiReferential *referential) {
134 (*global.log_stream) << "draw_edge_thresholding" << endl;
136 Rectangle registered_window_a;
138 referential->register_rectangle(_registration_a,
140 ®istered_window_a);
142 referential->draw_window(image, _registration_a, ®istered_window_a, 0);
145 void PiFeature::print_edge_thresholding(ostream *os) {
146 (*os) << "_tag " << _tag << endl;
147 (*os) << "_edge_scale " << _edge_scale << endl;
148 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
149 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
150 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
151 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
154 //////////////////////////////////////////////////////////////////////
155 // PF_EDGE_HISTOGRAM_COMPARISON
157 scalar_t PiFeature::response_edge_histogram_comparison(RichImage *image,
158 PiReferential *referential) {
160 Rectangle registered_window_a;
162 referential->register_rectangle(_registration_a,
164 ®istered_window_a);
166 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
167 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
168 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
169 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
171 Rectangle registered_window_b;
173 referential->register_rectangle(_registration_b,
175 ®istered_window_b);
177 int xmin_b = int(registered_window_b.xmin) >> _edge_scale;
178 int ymin_b = int(registered_window_b.ymin) >> _edge_scale;
179 int xmax_b = int(registered_window_b.xmax) >> _edge_scale;
180 int ymax_b = int(registered_window_b.ymax) >> _edge_scale;
182 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
184 scalar_t result = 0.0;
186 scalar_t ne_a = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
188 xmax_a, ymax_a) + 1);
190 scalar_t ne_b = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
192 xmax_b, ymax_b) + 1);
194 for(int t = RichImage::first_edge_tag; t < RichImage::first_edge_tag + RichImage::nb_edge_tags; t++)
195 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
197 xmax_a, ymax_a)) / ne_a
199 scalar_t(image->nb_tags_in_window(scale, t,
201 xmax_b, ymax_b)) / ne_b);
203 ASSERT(!isnan(result));
208 void PiFeature::draw_edge_histogram_comparison(RGBImage *image,
210 PiReferential *referential) {
212 (*global.log_stream) << "draw_edge_histogram_comparison" << endl;
214 Rectangle registered_window;
217 referential->register_rectangle(_registration_a,
220 referential->draw_window(image, _registration_a, ®istered_window, 0);
224 referential->register_rectangle(_registration_b,
228 referential->draw_window(image, _registration_b, ®istered_window, 0);
232 void PiFeature::print_edge_histogram_comparison(ostream *os) {
233 (*os) << "_edge_scale " << _edge_scale << endl;
234 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
235 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
236 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
237 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
238 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
239 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
240 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
241 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
244 //////////////////////////////////////////////////////////////////////
245 // PF_GRAYSCALE_HISTOGRAM_COMPARISON
247 scalar_t PiFeature::response_grayscale_histogram_comparison(RichImage *image,
248 PiReferential *referential) {
249 Rectangle registered_window_a;
251 referential->register_rectangle(_registration_a,
253 ®istered_window_a);
255 int xmin_a = int(registered_window_a.xmin);
256 int ymin_a = int(registered_window_a.ymin);
257 int xmax_a = int(registered_window_a.xmax);
258 int ymax_a = int(registered_window_a.ymax);
260 Rectangle registered_window_b;
262 referential->register_rectangle(_registration_b,
264 ®istered_window_b);
266 int xmin_b = int(registered_window_b.xmin);
267 int ymin_b = int(registered_window_b.ymin);
268 int xmax_b = int(registered_window_b.xmax);
269 int ymax_b = int(registered_window_b.ymax);
271 int scale = referential->common_scale();
273 scalar_t result = 0.0;
275 scalar_t ne_a = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a));
276 scalar_t ne_b = scalar_t((xmax_b - xmin_b) * (ymax_b - ymin_b));
278 for(int t = RichImage::first_gray_tag; t < RichImage::first_gray_tag + RichImage::nb_gray_tags; t++)
279 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
281 xmax_a, ymax_a))/ne_a
283 scalar_t(image->nb_tags_in_window(scale, t,
285 xmax_b, ymax_b))/ne_b);
286 ASSERT(!isnan(result));
291 void PiFeature::draw_grayscale_histogram_comparison(RGBImage *image,
293 PiReferential *referential) {
295 (*global.log_stream) << "draw_grayscale_histogram_comparison" << endl;
297 Rectangle registered_window;
300 referential->register_rectangle(_registration_a,
304 referential->draw_window(image, _registration_a, ®istered_window, 0);
308 referential->register_rectangle(_registration_b,
312 referential->draw_window(image, _registration_b, ®istered_window, 0);
316 void PiFeature::print_grayscale_histogram_comparison(ostream *os) {
317 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
318 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
319 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
320 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
321 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
322 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
323 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
324 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
327 //////////////////////////////////////////////////////////////////////
328 //////////////////////////////////////////////////////////////////////
329 //////////////////////////////////////////////////////////////////////
331 void PiFeature::randomize(int level) {
333 // We randomize all parameters, even those which will not be used
334 // due to the feature type
336 _tag = int(drand48() * (RichImage::nb_edge_tags + 1));
338 if(_tag < RichImage::nb_edge_tags)
339 _tag += RichImage::first_edge_tag;
341 _tag = RichImage::variance_tag;
343 _edge_scale = int(drand48() * 3);
345 // Windows can not be defined in different frames unless we allow
346 // head-belly registration
348 if(global.force_head_belly_independence) {
350 _registration_a = PiReferential::RM_HEAD_NO_POLARITY;
351 _registration_b = PiReferential::RM_HEAD_NO_POLARITY;
352 } else if(level == 1) {
353 _registration_a = PiReferential::RM_BELLY_NO_POLARITY;
354 _registration_b = PiReferential::RM_BELLY_NO_POLARITY;
359 _registration_a = random_registration_mode(level);
360 _registration_b = random_registration_mode(level);
363 randomize_window(_registration_a, &_window_a);
364 randomize_window(_registration_b, &_window_b);
366 switch(int(drand48() * 3)) {
369 _type = PF_EDGE_THRESHOLDING;
373 _type = PF_EDGE_HISTOGRAM_COMPARISON;
377 _type = PF_GRAYSCALE_HISTOGRAM_COMPARISON;
385 scalar_t PiFeature::response(RichImage *image, PiReferential *referential) {
390 case PF_EDGE_THRESHOLDING:
391 r = response_edge_thresholding(image, referential);
394 case PF_EDGE_HISTOGRAM_COMPARISON:
395 r = response_edge_histogram_comparison(image, referential);
398 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
399 r = response_grayscale_histogram_comparison(image, referential);
411 void PiFeature::draw(RGBImage *image,
412 int r, int g, int b, PiReferential *referential) {
416 case PF_EDGE_THRESHOLDING:
417 draw_edge_thresholding(image, r, g, b, referential);
420 case PF_EDGE_HISTOGRAM_COMPARISON:
421 draw_edge_histogram_comparison(image, r, g, b, referential);
424 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
425 draw_grayscale_histogram_comparison(image, r, g, b, referential);
433 void PiFeature::print(ostream *os) {
435 (*os) << "registration_a ";
436 PiReferential::print_registration_mode(os, _registration_a);
439 (*os) << "registration_b ";
440 PiReferential::print_registration_mode(os, _registration_b);
445 case PF_EDGE_THRESHOLDING:
446 print_edge_thresholding(os);
449 case PF_EDGE_HISTOGRAM_COMPARISON:
450 print_edge_histogram_comparison(os);
453 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
454 print_grayscale_histogram_comparison(os);