2 * folded-ctf is an implementation of the folded hierarchy of
3 * classifiers for object detection, developed by Francois Fleuret
6 * Copyright (c) 2008 Idiap Research Institute, http://www.idiap.ch/
7 * Written by Francois Fleuret <francois.fleuret@idiap.ch>
9 * This file is part of folded-ctf.
11 * folded-ctf is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 3 as
13 * published by the Free Software Foundation.
15 * folded-ctf is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with folded-ctf. If not, see <http://www.gnu.org/licenses/>.
25 #include "pi_feature.h"
28 #include "rectangle.h"
30 int PiFeature::random_registration_mode(int level) {
32 switch(int(6 * drand48())) {
35 return PiReferential::RM_HEAD;
40 return PiReferential::RM_BELLY;
45 return PiReferential::RM_HEAD_BELLY;
50 return PiReferential::RM_HEAD_BELLY_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);
149 void PiFeature::print_edge_thresholding(ostream *os) {
150 (*os) << "_tag " << _tag << endl;
151 (*os) << "_edge_scale " << _edge_scale << endl;
152 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
153 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
154 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
155 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
158 //////////////////////////////////////////////////////////////////////
159 // PF_EDGE_HISTOGRAM_COMPARISON
161 scalar_t PiFeature::response_edge_histogram_comparison(RichImage *image,
162 PiReferential *referential) {
164 Rectangle registered_window_a;
166 referential->register_rectangle(_registration_a,
168 ®istered_window_a);
170 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
171 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
172 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
173 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
175 Rectangle registered_window_b;
177 referential->register_rectangle(_registration_b,
179 ®istered_window_b);
181 int xmin_b = int(registered_window_b.xmin) >> _edge_scale;
182 int ymin_b = int(registered_window_b.ymin) >> _edge_scale;
183 int xmax_b = int(registered_window_b.xmax) >> _edge_scale;
184 int ymax_b = int(registered_window_b.ymax) >> _edge_scale;
186 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
188 scalar_t result = 0.0;
190 scalar_t ne_a = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
192 xmax_a, ymax_a) + 1);
194 scalar_t ne_b = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
196 xmax_b, ymax_b) + 1);
198 for(int t = RichImage::first_edge_tag; t < RichImage::first_edge_tag + RichImage::nb_edge_tags; t++)
199 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
201 xmax_a, ymax_a)) / ne_a
203 scalar_t(image->nb_tags_in_window(scale, t,
205 xmax_b, ymax_b)) / ne_b);
207 ASSERT(!isnan(result));
212 void PiFeature::draw_edge_histogram_comparison(RGBImage *image,
214 PiReferential *referential) {
216 (*global.log_stream) << "draw_edge_histogram_comparison" << endl;
218 Rectangle registered_window;
221 referential->register_rectangle(_registration_a,
224 referential->draw_window(image, _registration_a, ®istered_window, 0);
228 referential->register_rectangle(_registration_b,
232 referential->draw_window(image, _registration_b, ®istered_window, 0);
236 void PiFeature::print_edge_histogram_comparison(ostream *os) {
237 (*os) << "_edge_scale " << _edge_scale << endl;
238 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
239 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
240 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
241 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
242 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
243 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
244 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
245 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
248 //////////////////////////////////////////////////////////////////////
249 // PF_GRAYSCALE_HISTOGRAM_COMPARISON
251 scalar_t PiFeature::response_grayscale_histogram_comparison(RichImage *image,
252 PiReferential *referential) {
253 Rectangle registered_window_a;
255 referential->register_rectangle(_registration_a,
257 ®istered_window_a);
259 int xmin_a = int(registered_window_a.xmin);
260 int ymin_a = int(registered_window_a.ymin);
261 int xmax_a = int(registered_window_a.xmax);
262 int ymax_a = int(registered_window_a.ymax);
264 Rectangle registered_window_b;
266 referential->register_rectangle(_registration_b,
268 ®istered_window_b);
270 int xmin_b = int(registered_window_b.xmin);
271 int ymin_b = int(registered_window_b.ymin);
272 int xmax_b = int(registered_window_b.xmax);
273 int ymax_b = int(registered_window_b.ymax);
275 int scale = referential->common_scale();
277 scalar_t result = 0.0;
279 scalar_t ne_a = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a));
280 scalar_t ne_b = scalar_t((xmax_b - xmin_b) * (ymax_b - ymin_b));
282 for(int t = RichImage::first_gray_tag; t < RichImage::first_gray_tag + RichImage::nb_gray_tags; t++)
283 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
285 xmax_a, ymax_a))/ne_a
287 scalar_t(image->nb_tags_in_window(scale, t,
289 xmax_b, ymax_b))/ne_b);
290 ASSERT(!isnan(result));
295 void PiFeature::draw_grayscale_histogram_comparison(RGBImage *image,
297 PiReferential *referential) {
299 (*global.log_stream) << "draw_grayscale_histogram_comparison" << endl;
301 Rectangle registered_window;
304 referential->register_rectangle(_registration_a,
308 referential->draw_window(image, _registration_a, ®istered_window, 0);
312 referential->register_rectangle(_registration_b,
316 referential->draw_window(image, _registration_b, ®istered_window, 0);
320 void PiFeature::print_grayscale_histogram_comparison(ostream *os) {
321 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
322 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
323 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
324 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
325 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
326 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
327 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
328 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
331 //////////////////////////////////////////////////////////////////////
332 //////////////////////////////////////////////////////////////////////
333 //////////////////////////////////////////////////////////////////////
335 void PiFeature::randomize(int level) {
337 // We randomize all parameters, even those which will not be used
338 // due to the feature type
340 _tag = int(drand48() * (RichImage::nb_edge_tags + 1));
342 if(_tag < RichImage::nb_edge_tags)
343 _tag += RichImage::first_edge_tag;
345 _tag = RichImage::variance_tag;
347 _edge_scale = int(drand48() * 3);
349 // Windows can not be defined in different frames unless we allow
350 // head-belly registration
352 if(global.force_head_belly_independence) {
354 _registration_a = PiReferential::RM_HEAD_NO_POLARITY;
355 _registration_b = PiReferential::RM_HEAD_NO_POLARITY;
356 } else if(level == 1) {
357 _registration_a = PiReferential::RM_BELLY_NO_POLARITY;
358 _registration_b = PiReferential::RM_BELLY_NO_POLARITY;
363 _registration_a = random_registration_mode(level);
364 _registration_b = random_registration_mode(level);
367 randomize_window(_registration_a, &_window_a);
368 randomize_window(_registration_b, &_window_b);
370 switch(int(drand48() * 3)) {
373 _type = PF_EDGE_THRESHOLDING;
377 _type = PF_EDGE_HISTOGRAM_COMPARISON;
381 _type = PF_GRAYSCALE_HISTOGRAM_COMPARISON;
389 scalar_t PiFeature::response(RichImage *image, PiReferential *referential) {
394 case PF_EDGE_THRESHOLDING:
395 r = response_edge_thresholding(image, referential);
398 case PF_EDGE_HISTOGRAM_COMPARISON:
399 r = response_edge_histogram_comparison(image, referential);
402 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
403 r = response_grayscale_histogram_comparison(image, referential);
415 void PiFeature::draw(RGBImage *image,
416 int r, int g, int b, PiReferential *referential) {
420 case PF_EDGE_THRESHOLDING:
421 draw_edge_thresholding(image, r, g, b, referential);
424 case PF_EDGE_HISTOGRAM_COMPARISON:
425 draw_edge_histogram_comparison(image, r, g, b, referential);
428 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
429 draw_grayscale_histogram_comparison(image, r, g, b, referential);
437 void PiFeature::print(ostream *os) {
439 (*os) << "registration_a ";
440 PiReferential::print_registration_mode(os, _registration_a);
443 (*os) << "registration_b ";
444 PiReferential::print_registration_mode(os, _registration_b);
449 case PF_EDGE_THRESHOLDING:
450 print_edge_thresholding(os);
453 case PF_EDGE_HISTOGRAM_COMPARISON:
454 print_edge_histogram_comparison(os);
457 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
458 print_grayscale_histogram_comparison(os);