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, (C) IDIAP //
16 // Contact <francois.fleuret@idiap.ch> for comments & bug reports //
17 ///////////////////////////////////////////////////////////////////////////
19 #include "pi_feature.h"
22 #include "rectangle.h"
24 int PiFeature::random_registration_mode(int level) {
26 switch(int(6 * drand48())) {
29 return PiReferential::RM_HEAD;
34 return PiReferential::RM_BELLY;
39 return PiReferential::RM_HEAD_BELLY;
44 return PiReferential::RM_HEAD_BELLY_EDGES;
49 return PiReferential::RM_BODY;
54 return PiReferential::RM_BODY_EDGES;
63 void PiFeature::randomize_window(int registration_mode, Rectangle *window) {
64 scalar_t xc, yc, w, h;
67 xc = 2 * drand48() - 1.0;
68 yc = 2 * drand48() - 1.0;
72 // If we are in a non-rotating frame, allow rectangular window,
73 // otherwise force it to be squared
75 if(registration_mode == PiReferential::RM_HEAD ||
76 registration_mode == PiReferential::RM_BELLY ||
77 registration_mode == PiReferential::RM_HEAD_NO_POLARITY ||
78 registration_mode == PiReferential::RM_BELLY_NO_POLARITY) {
83 } while(w < global.pi_feature_window_min_size ||
84 h < global.pi_feature_window_min_size ||
85 xc - w/2 < -1.0 || xc + w/2 > 1.0 ||
86 yc - h/2 < -1.0 || yc + h/2 > 1.0);
88 window->xmin = xc - w/2;
89 window->ymin = yc - h/2;
90 window->xmax = xc + w/2;
91 window->ymax = yc + h/2;
94 //////////////////////////////////////////////////////////////////////
95 // PF_EDGE_THRESHOLDING
97 scalar_t PiFeature::response_edge_thresholding(RichImage *image,
98 PiReferential *referential) {
99 Rectangle registered_window_a;
101 referential->register_rectangle(_registration_a,
103 ®istered_window_a);
105 int tag = referential->register_edge(_registration_a, _tag);
107 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
108 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
109 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
110 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
112 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
116 ASSERT((tag >= RichImage::first_edge_tag &&
117 tag < RichImage::first_edge_tag + RichImage::nb_edge_tags) ||
118 tag == RichImage::variance_tag);
120 if(tag != RichImage::variance_tag) {
121 ne = scalar_t(image->nb_tags_in_window(scale, tag,
122 xmin_a, ymin_a, xmax_a, ymax_a));
123 nt = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
124 xmin_a, ymin_a, xmax_a, ymax_a) + 1);
126 ne = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
127 xmin_a, ymin_a, xmax_a, ymax_a));
128 nt = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a)) + 1;
134 void PiFeature::draw_edge_thresholding(RGBImage *image,
136 PiReferential *referential) {
138 (*global.log_stream) << "draw_edge_thresholding" << endl;
140 Rectangle registered_window_a;
142 referential->register_rectangle(_registration_a,
144 ®istered_window_a);
146 referential->draw_window(image, _registration_a, ®istered_window_a, 0);
148 // if(!global.pictures_for_article) {
149 // int tag = referential->register_edge(_registration_a, _tag);
151 // referential->draw_edge_and_scale(image, _registration_a, ®istered_window_a,
152 // tag, _edge_scale);
156 void PiFeature::print_edge_thresholding(ostream *os) {
157 (*os) << "_tag " << _tag << endl;
158 (*os) << "_edge_scale " << _edge_scale << endl;
159 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
160 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
161 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
162 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
165 //////////////////////////////////////////////////////////////////////
166 // PF_EDGE_HISTOGRAM_COMPARISON
168 scalar_t PiFeature::response_edge_histogram_comparison(RichImage *image,
169 PiReferential *referential) {
171 Rectangle registered_window_a;
173 referential->register_rectangle(_registration_a,
175 ®istered_window_a);
177 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
178 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
179 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
180 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
182 Rectangle registered_window_b;
184 referential->register_rectangle(_registration_b,
186 ®istered_window_b);
188 int xmin_b = int(registered_window_b.xmin) >> _edge_scale;
189 int ymin_b = int(registered_window_b.ymin) >> _edge_scale;
190 int xmax_b = int(registered_window_b.xmax) >> _edge_scale;
191 int ymax_b = int(registered_window_b.ymax) >> _edge_scale;
193 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
195 scalar_t result = 0.0;
197 scalar_t ne_a = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
199 xmax_a, ymax_a) + 1);
201 scalar_t ne_b = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
203 xmax_b, ymax_b) + 1);
205 for(int t = RichImage::first_edge_tag; t < RichImage::first_edge_tag + RichImage::nb_edge_tags; t++)
206 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
208 xmax_a, ymax_a)) / ne_a
210 scalar_t(image->nb_tags_in_window(scale, t,
212 xmax_b, ymax_b)) / ne_b);
214 ASSERT(!isnan(result));
219 void PiFeature::draw_edge_histogram_comparison(RGBImage *image,
221 PiReferential *referential) {
223 (*global.log_stream) << "draw_edge_histogram_comparison" << endl;
225 Rectangle registered_window;
228 referential->register_rectangle(_registration_a,
231 referential->draw_window(image, _registration_a, ®istered_window, 0);
235 referential->register_rectangle(_registration_b,
239 referential->draw_window(image, _registration_b, ®istered_window, 0);
243 void PiFeature::print_edge_histogram_comparison(ostream *os) {
244 (*os) << "_edge_scale " << _edge_scale << endl;
245 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
246 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
247 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
248 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
249 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
250 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
251 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
252 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
255 //////////////////////////////////////////////////////////////////////
256 // PF_GRAYSCALE_HISTOGRAM_COMPARISON
258 scalar_t PiFeature::response_grayscale_histogram_comparison(RichImage *image,
259 PiReferential *referential) {
260 Rectangle registered_window_a;
262 referential->register_rectangle(_registration_a,
264 ®istered_window_a);
266 int xmin_a = int(registered_window_a.xmin);
267 int ymin_a = int(registered_window_a.ymin);
268 int xmax_a = int(registered_window_a.xmax);
269 int ymax_a = int(registered_window_a.ymax);
271 Rectangle registered_window_b;
273 referential->register_rectangle(_registration_b,
275 ®istered_window_b);
277 int xmin_b = int(registered_window_b.xmin);
278 int ymin_b = int(registered_window_b.ymin);
279 int xmax_b = int(registered_window_b.xmax);
280 int ymax_b = int(registered_window_b.ymax);
282 int scale = referential->common_scale();
284 scalar_t result = 0.0;
286 scalar_t ne_a = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a));
287 scalar_t ne_b = scalar_t((xmax_b - xmin_b) * (ymax_b - ymin_b));
289 for(int t = RichImage::first_gray_tag; t < RichImage::first_gray_tag + RichImage::nb_gray_tags; t++)
290 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
292 xmax_a, ymax_a))/ne_a
294 scalar_t(image->nb_tags_in_window(scale, t,
296 xmax_b, ymax_b))/ne_b);
297 ASSERT(!isnan(result));
302 void PiFeature::draw_grayscale_histogram_comparison(RGBImage *image,
304 PiReferential *referential) {
306 (*global.log_stream) << "draw_grayscale_histogram_comparison" << endl;
308 Rectangle registered_window;
311 referential->register_rectangle(_registration_a,
315 referential->draw_window(image, _registration_a, ®istered_window, 0);
319 referential->register_rectangle(_registration_b,
323 referential->draw_window(image, _registration_b, ®istered_window, 0);
327 void PiFeature::print_grayscale_histogram_comparison(ostream *os) {
328 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
329 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
330 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
331 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
332 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
333 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
334 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
335 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
338 //////////////////////////////////////////////////////////////////////
339 //////////////////////////////////////////////////////////////////////
340 //////////////////////////////////////////////////////////////////////
342 void PiFeature::randomize(int level) {
344 // We randomize all parameters, even those which will not be used
345 // due to the feature type
347 _tag = int(drand48() * (RichImage::nb_edge_tags + 1));
349 if(_tag < RichImage::nb_edge_tags)
350 _tag += RichImage::first_edge_tag;
352 _tag = RichImage::variance_tag;
354 _edge_scale = int(drand48() * 3);
356 // Windows can not be defined in different frames unless we allow
357 // head-belly registration
359 if(global.force_head_belly_independence) {
361 _registration_a = PiReferential::RM_HEAD_NO_POLARITY;
362 _registration_b = PiReferential::RM_HEAD_NO_POLARITY;
363 } else if(level == 1) {
364 _registration_a = PiReferential::RM_BELLY_NO_POLARITY;
365 _registration_b = PiReferential::RM_BELLY_NO_POLARITY;
370 _registration_a = random_registration_mode(level);
371 _registration_b = random_registration_mode(level);
374 randomize_window(_registration_a, &_window_a);
375 randomize_window(_registration_b, &_window_b);
377 switch(int(drand48() * 3)) {
380 _type = PF_EDGE_THRESHOLDING;
384 _type = PF_EDGE_HISTOGRAM_COMPARISON;
388 _type = PF_GRAYSCALE_HISTOGRAM_COMPARISON;
396 scalar_t PiFeature::response(RichImage *image, PiReferential *referential) {
401 case PF_EDGE_THRESHOLDING:
402 r = response_edge_thresholding(image, referential);
405 case PF_EDGE_HISTOGRAM_COMPARISON:
406 r = response_edge_histogram_comparison(image, referential);
409 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
410 r = response_grayscale_histogram_comparison(image, referential);
422 void PiFeature::draw(RGBImage *image,
423 int r, int g, int b, PiReferential *referential) {
427 case PF_EDGE_THRESHOLDING:
428 draw_edge_thresholding(image, r, g, b, referential);
431 case PF_EDGE_HISTOGRAM_COMPARISON:
432 draw_edge_histogram_comparison(image, r, g, b, referential);
435 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
436 draw_grayscale_histogram_comparison(image, r, g, b, referential);
444 void PiFeature::print(ostream *os) {
446 (*os) << "registration_a ";
447 PiReferential::print_registration_mode(os, _registration_a);
450 (*os) << "registration_b ";
451 PiReferential::print_registration_mode(os, _registration_b);
456 case PF_EDGE_THRESHOLDING:
457 print_edge_thresholding(os);
460 case PF_EDGE_HISTOGRAM_COMPARISON:
461 print_edge_histogram_comparison(os);
464 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
465 print_grayscale_histogram_comparison(os);