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 as published
13 * by the Free Software Foundation, either version 3 of the License,
14 * or (at your option) any later version.
16 * folded-ctf is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with folded-ctf. If not, see <http://www.gnu.org/licenses/>.
26 #include "pi_feature.h"
29 #include "rectangle.h"
31 int PiFeature::random_registration_mode(int level) {
33 switch(int(6 * drand48())) {
36 return PiReferential::RM_HEAD;
41 return PiReferential::RM_BELLY;
46 return PiReferential::RM_HEAD_BELLY;
51 return PiReferential::RM_HEAD_BELLY_EDGES;
64 void PiFeature::randomize_window(int registration_mode, Rectangle *window) {
65 scalar_t xc, yc, w, h;
68 xc = 2 * drand48() - 1.0;
69 yc = 2 * drand48() - 1.0;
73 // If we are in a non-rotating frame, allow rectangular window,
74 // otherwise force it to be squared
76 if(registration_mode == PiReferential::RM_HEAD ||
77 registration_mode == PiReferential::RM_BELLY ||
78 registration_mode == PiReferential::RM_HEAD_NO_POLARITY ||
79 registration_mode == PiReferential::RM_BELLY_NO_POLARITY) {
84 } while(w < global.pi_feature_window_min_size ||
85 h < global.pi_feature_window_min_size ||
86 xc - w/2 < -1.0 || xc + w/2 > 1.0 ||
87 yc - h/2 < -1.0 || yc + h/2 > 1.0);
89 window->xmin = xc - w/2;
90 window->ymin = yc - h/2;
91 window->xmax = xc + w/2;
92 window->ymax = yc + h/2;
95 //////////////////////////////////////////////////////////////////////
96 // PF_EDGE_THRESHOLDING
98 scalar_t PiFeature::response_edge_thresholding(RichImage *image,
99 PiReferential *referential) {
100 Rectangle registered_window_a;
102 referential->register_rectangle(_registration_a,
104 ®istered_window_a);
106 int tag = referential->register_edge(_registration_a, _tag);
108 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
109 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
110 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
111 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
113 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
117 ASSERT((tag >= RichImage::first_edge_tag &&
118 tag < RichImage::first_edge_tag + RichImage::nb_edge_tags) ||
119 tag == RichImage::variance_tag);
121 if(tag != RichImage::variance_tag) {
122 ne = scalar_t(image->nb_tags_in_window(scale, tag,
123 xmin_a, ymin_a, xmax_a, ymax_a));
124 nt = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
125 xmin_a, ymin_a, xmax_a, ymax_a) + 1);
127 ne = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
128 xmin_a, ymin_a, xmax_a, ymax_a));
129 nt = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a)) + 1;
135 void PiFeature::draw_edge_thresholding(RGBImage *image,
137 PiReferential *referential) {
139 (*global.log_stream) << "draw_edge_thresholding" << endl;
141 Rectangle registered_window_a;
143 referential->register_rectangle(_registration_a,
145 ®istered_window_a);
147 referential->draw_window(image, _registration_a, ®istered_window_a, 0);
150 void PiFeature::print_edge_thresholding(ostream *os) {
151 (*os) << "_tag " << _tag << endl;
152 (*os) << "_edge_scale " << _edge_scale << endl;
153 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
154 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
155 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
156 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
159 //////////////////////////////////////////////////////////////////////
160 // PF_EDGE_HISTOGRAM_COMPARISON
162 scalar_t PiFeature::response_edge_histogram_comparison(RichImage *image,
163 PiReferential *referential) {
165 Rectangle registered_window_a;
167 referential->register_rectangle(_registration_a,
169 ®istered_window_a);
171 int xmin_a = int(registered_window_a.xmin) >> _edge_scale;
172 int ymin_a = int(registered_window_a.ymin) >> _edge_scale;
173 int xmax_a = int(registered_window_a.xmax) >> _edge_scale;
174 int ymax_a = int(registered_window_a.ymax) >> _edge_scale;
176 Rectangle registered_window_b;
178 referential->register_rectangle(_registration_b,
180 ®istered_window_b);
182 int xmin_b = int(registered_window_b.xmin) >> _edge_scale;
183 int ymin_b = int(registered_window_b.ymin) >> _edge_scale;
184 int xmax_b = int(registered_window_b.xmax) >> _edge_scale;
185 int ymax_b = int(registered_window_b.ymax) >> _edge_scale;
187 int scale = referential->common_scale() + _edge_scale * global.nb_scales_per_power_of_two;
189 scalar_t result = 0.0;
191 scalar_t ne_a = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
193 xmax_a, ymax_a) + 1);
195 scalar_t ne_b = scalar_t(image->nb_tags_in_window(scale, RichImage::variance_tag,
197 xmax_b, ymax_b) + 1);
199 for(int t = RichImage::first_edge_tag; t < RichImage::first_edge_tag + RichImage::nb_edge_tags; t++)
200 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
202 xmax_a, ymax_a)) / ne_a
204 scalar_t(image->nb_tags_in_window(scale, t,
206 xmax_b, ymax_b)) / ne_b);
208 ASSERT(!isnan(result));
213 void PiFeature::draw_edge_histogram_comparison(RGBImage *image,
215 PiReferential *referential) {
217 (*global.log_stream) << "draw_edge_histogram_comparison" << endl;
219 Rectangle registered_window;
222 referential->register_rectangle(_registration_a,
225 referential->draw_window(image, _registration_a, ®istered_window, 0);
229 referential->register_rectangle(_registration_b,
233 referential->draw_window(image, _registration_b, ®istered_window, 0);
237 void PiFeature::print_edge_histogram_comparison(ostream *os) {
238 (*os) << "_edge_scale " << _edge_scale << endl;
239 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
240 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
241 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
242 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
243 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
244 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
245 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
246 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
249 //////////////////////////////////////////////////////////////////////
250 // PF_GRAYSCALE_HISTOGRAM_COMPARISON
252 scalar_t PiFeature::response_grayscale_histogram_comparison(RichImage *image,
253 PiReferential *referential) {
254 Rectangle registered_window_a;
256 referential->register_rectangle(_registration_a,
258 ®istered_window_a);
260 int xmin_a = int(registered_window_a.xmin);
261 int ymin_a = int(registered_window_a.ymin);
262 int xmax_a = int(registered_window_a.xmax);
263 int ymax_a = int(registered_window_a.ymax);
265 Rectangle registered_window_b;
267 referential->register_rectangle(_registration_b,
269 ®istered_window_b);
271 int xmin_b = int(registered_window_b.xmin);
272 int ymin_b = int(registered_window_b.ymin);
273 int xmax_b = int(registered_window_b.xmax);
274 int ymax_b = int(registered_window_b.ymax);
276 int scale = referential->common_scale();
278 scalar_t result = 0.0;
280 scalar_t ne_a = scalar_t((xmax_a - xmin_a) * (ymax_a - ymin_a));
281 scalar_t ne_b = scalar_t((xmax_b - xmin_b) * (ymax_b - ymin_b));
283 for(int t = RichImage::first_gray_tag; t < RichImage::first_gray_tag + RichImage::nb_gray_tags; t++)
284 result += sq(scalar_t(image->nb_tags_in_window(scale, t,
286 xmax_a, ymax_a))/ne_a
288 scalar_t(image->nb_tags_in_window(scale, t,
290 xmax_b, ymax_b))/ne_b);
291 ASSERT(!isnan(result));
296 void PiFeature::draw_grayscale_histogram_comparison(RGBImage *image,
298 PiReferential *referential) {
300 (*global.log_stream) << "draw_grayscale_histogram_comparison" << endl;
302 Rectangle registered_window;
305 referential->register_rectangle(_registration_a,
309 referential->draw_window(image, _registration_a, ®istered_window, 0);
313 referential->register_rectangle(_registration_b,
317 referential->draw_window(image, _registration_b, ®istered_window, 0);
321 void PiFeature::print_grayscale_histogram_comparison(ostream *os) {
322 (*os) << "_window_a.xmin " << _window_a.xmin << endl;
323 (*os) << "_window_a.ymin " << _window_a.ymin << endl;
324 (*os) << "_window_a.xmax " << _window_a.xmax << endl;
325 (*os) << "_window_a.ymax " << _window_a.ymax << endl;
326 (*os) << "_window_b.xmin " << _window_a.xmin << endl;
327 (*os) << "_window_b.ymin " << _window_a.ymin << endl;
328 (*os) << "_window_b.xmax " << _window_a.xmax << endl;
329 (*os) << "_window_b.ymax " << _window_a.ymax << endl;
332 //////////////////////////////////////////////////////////////////////
333 //////////////////////////////////////////////////////////////////////
334 //////////////////////////////////////////////////////////////////////
336 void PiFeature::randomize(int level) {
338 // We randomize all parameters, even those which will not be used
339 // due to the feature type
341 _tag = int(drand48() * (RichImage::nb_edge_tags + 1));
343 if(_tag < RichImage::nb_edge_tags)
344 _tag += RichImage::first_edge_tag;
346 _tag = RichImage::variance_tag;
348 _edge_scale = int(drand48() * 3);
350 // Windows can not be defined in different frames unless we allow
351 // head-belly registration
353 if(global.force_head_belly_independence) {
355 _registration_a = PiReferential::RM_HEAD_NO_POLARITY;
356 _registration_b = PiReferential::RM_HEAD_NO_POLARITY;
357 } else if(level == 1) {
358 _registration_a = PiReferential::RM_BELLY_NO_POLARITY;
359 _registration_b = PiReferential::RM_BELLY_NO_POLARITY;
364 _registration_a = random_registration_mode(level);
365 _registration_b = random_registration_mode(level);
368 randomize_window(_registration_a, &_window_a);
369 randomize_window(_registration_b, &_window_b);
371 switch(int(drand48() * 3)) {
374 _type = PF_EDGE_THRESHOLDING;
378 _type = PF_EDGE_HISTOGRAM_COMPARISON;
382 _type = PF_GRAYSCALE_HISTOGRAM_COMPARISON;
390 scalar_t PiFeature::response(RichImage *image, PiReferential *referential) {
395 case PF_EDGE_THRESHOLDING:
396 r = response_edge_thresholding(image, referential);
399 case PF_EDGE_HISTOGRAM_COMPARISON:
400 r = response_edge_histogram_comparison(image, referential);
403 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
404 r = response_grayscale_histogram_comparison(image, referential);
416 void PiFeature::draw(RGBImage *image,
417 int r, int g, int b, PiReferential *referential) {
421 case PF_EDGE_THRESHOLDING:
422 draw_edge_thresholding(image, r, g, b, referential);
425 case PF_EDGE_HISTOGRAM_COMPARISON:
426 draw_edge_histogram_comparison(image, r, g, b, referential);
429 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
430 draw_grayscale_histogram_comparison(image, r, g, b, referential);
438 void PiFeature::print(ostream *os) {
440 (*os) << "registration_a ";
441 PiReferential::print_registration_mode(os, _registration_a);
444 (*os) << "registration_b ";
445 PiReferential::print_registration_mode(os, _registration_b);
450 case PF_EDGE_THRESHOLDING:
451 print_edge_thresholding(os);
454 case PF_EDGE_HISTOGRAM_COMPARISON:
455 print_edge_histogram_comparison(os);
458 case PF_GRAYSCALE_HISTOGRAM_COMPARISON:
459 print_grayscale_histogram_comparison(os);