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/>.
30 memset(this, 0, sizeof(*this));
33 void Pose::horizontal_flip(scalar_t scene_width) {
34 _head_xc = scene_width - 1 - _head_xc;
35 _belly_xc = scene_width - 1 - _belly_xc;
38 const scalar_t tolerance_scale_ratio_for_hit = 1.5;
39 const scalar_t tolerance_distance_factor_for_hit = 1.0;
41 bool Pose::hit(int level, Pose *pose) {
45 if(_head_radius/pose->_head_radius > tolerance_scale_ratio_for_hit ||
46 pose->_head_radius/_head_radius > tolerance_scale_ratio_for_hit)
49 scalar_t sq_delta = _head_radius * pose->_head_radius * sq(tolerance_distance_factor_for_hit);
53 if(sq(_head_xc - pose->_head_xc) + sq(_head_yc - pose->_head_yc) > sq_delta)
56 if(level == 0) return true;
60 if(sq(_belly_xc - pose->_belly_xc) + sq(_belly_yc - pose->_belly_yc) > 4 * sq_delta)
63 if(level == 1) return true;
65 cerr << "Hit criterion is undefined for level " << level << endl;
70 const scalar_t tolerance_scale_ratio_for_collide = 1.2;
71 const scalar_t tolerance_distance_factor_for_collide = 0.25;
73 bool Pose::collide(int level, Pose *pose) {
77 if(_head_radius/pose->_head_radius > tolerance_scale_ratio_for_collide ||
78 pose->_head_radius/_head_radius > tolerance_scale_ratio_for_collide)
81 scalar_t sq_delta = _head_radius * pose->_head_radius * sq(tolerance_distance_factor_for_collide);
85 if(sq(_head_xc - pose->_head_xc) + sq(_head_yc - pose->_head_yc) <= sq_delta)
88 if(level == 0) return false;
92 if(sq(_belly_xc - pose->_belly_xc) + sq(_belly_yc - pose->_belly_yc) <= sq_delta)
95 if(level == 1) return false;
97 cerr << "Colliding criterion is undefined for level " << level << endl;
102 void Pose::draw(int thickness, int r, int g, int b, int level, RGBImage *image) {
104 // Draw the head circle
106 image->draw_ellipse(thickness, r, g, b,
107 _head_xc, _head_yc, _head_radius, _head_radius, 0);
111 scalar_t vx = _belly_xc - _head_xc, vy = _belly_yc - _head_yc;
112 scalar_t l = sqrt(vx * vx + vy * vy);
116 scalar_t belly_radius = 12 + thickness / 2;
118 if(l > _head_radius + thickness + belly_radius) {
119 image->draw_line(thickness, r, g, b,
120 _head_xc + vx * (_head_radius + thickness/2),
121 _head_yc + vy * (_head_radius + thickness/2),
122 _belly_xc - vx * (belly_radius - thickness/2),
123 _belly_yc - vy * (belly_radius - thickness/2));
126 // An ugly way to make a filled disc
128 for(scalar_t u = 0; u < belly_radius; u += thickness / 2) {
129 image->draw_ellipse(thickness, r, g, b, _belly_xc, _belly_yc, u, u, 0);
135 void Pose::print(ostream *out) {
136 (*out) << " _head_xc " << _head_xc << endl;
137 (*out) << " _head_yc " << _head_yc << endl;
138 (*out) << " _head_radius " << _head_radius << endl;
139 (*out) << " _belly_xc " << _belly_xc << endl;
140 (*out) << " _belly_yc " << _belly_yc << endl;
143 void Pose::write(ostream *out) {
144 write_var(out, &_bounding_box_xmin);
145 write_var(out, &_bounding_box_ymin);
146 write_var(out, &_bounding_box_xmax);
147 write_var(out, &_bounding_box_ymax);
148 write_var(out, &_head_xc); write_var(out, &_head_yc);
149 write_var(out, &_head_radius);
150 write_var(out, &_belly_xc);
151 write_var(out, &_belly_yc);
154 void Pose::read(istream *in) {
155 read_var(in, &_bounding_box_xmin);
156 read_var(in, &_bounding_box_ymin);
157 read_var(in, &_bounding_box_xmax);
158 read_var(in, &_bounding_box_ymax);
159 read_var(in, &_head_xc); read_var(in, &_head_yc);
160 read_var(in, &_head_radius);
161 read_var(in, &_belly_xc);
162 read_var(in, &_belly_yc);