2 * svrt is the ``Synthetic Visual Reasoning Test'', an image
3 * generator for evaluating classification performance of machine
4 * learning systems, humans and primates.
6 * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
7 * Written by Francois Fleuret <francois.fleuret@idiap.ch>
9 * This file is part of svrt.
11 * svrt is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 3 as
13 * published by the Free Software Foundation.
15 * svrt 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 svrt. If not, see <http://www.gnu.org/licenses/>.
27 int Shape::generate_part_part(scalar_t *xp, scalar_t *yp, int *nb_pixels,
28 scalar_t radius, scalar_t hole_radius,
29 scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2) {
30 if(abs(x1 - x2) > gap_max || abs(y1 - y2) > gap_max) {
32 scalar_t d = sqrt(scalar_t(sq(x1 - x2) + sq(y1 - y2)))/5;
33 scalar_t x3, y3, dx, dy;
38 dx = (2 * random_uniform_0_1() - 1) * d;
39 dy = (2 * random_uniform_0_1() - 1) * d;
40 } while(sq(dx) + sq(dy) > sq(d));
41 x3 = (x1 + x2) / 2 + dx;
42 y3 = (y1 + y2) / 2 + dy;
43 } while(sq(x3) + sq(y3) > sq(radius));
45 if(generate_part_part(xp, yp, nb_pixels,
46 radius, hole_radius, x1, y1, x3, y3)) {
50 if(generate_part_part(xp, yp, nb_pixels,
51 radius, hole_radius, x3, y3, x2, y2)) {
57 if(sq(x1) + sq(y1) >= sq(radius) || sq(x1) + sq(y1) < sq(hole_radius)) {
70 void Shape::generate_part(scalar_t *xp, scalar_t *yp, int *nb_pixels,
71 scalar_t radius, scalar_t hole_radius) {
72 scalar_t x1, y1, x2, y2, x3, y3, x4, y4;
73 int err1, err2, err3, err4;
79 x1 = random_uniform_0_1() * radius;
80 y1 = random_uniform_0_1() * radius;
81 } while(sq(x1) + sq(y1) > sq(radius) || sq(x1) + sq(y1) < sq(hole_radius));
84 x2 = -random_uniform_0_1() * radius;
85 y2 = random_uniform_0_1() * radius;
86 } while(sq(x2) + sq(y2) > sq(radius) || sq(x2) + sq(y2) < sq(hole_radius));
89 x3 = -random_uniform_0_1() * radius;
90 y3 = -random_uniform_0_1() * radius;
91 } while(sq(x3) + sq(y3) > sq(radius) || sq(x3) + sq(y3) < sq(hole_radius));
94 x4 = random_uniform_0_1() * radius;
95 y4 = -random_uniform_0_1() * radius;
96 } while(sq(x4) + sq(y4) > sq(radius) || sq(x4) + sq(y4) < sq(hole_radius));
98 n_pixels1 = *nb_pixels;
99 err1 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x1, y1, x2, y2);
100 n_pixels2 = *nb_pixels;
101 err2 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x2, y2, x3, y3);
102 n_pixels3 = *nb_pixels;
103 err3 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x3, y3, x4, y4);
104 n_pixels4 = *nb_pixels;
105 err4 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x4, y4, x1, y1);
107 } while(err1 || err2 || err3 || err4);
121 void Shape::randomize(scalar_t radius, scalar_t hole_radius) {
125 scalar_t tmp_x_pixels[nb_max_pixels], tmp_y_pixels[nb_max_pixels];
126 generate_part(tmp_x_pixels, tmp_y_pixels, &nb_pixels, radius, hole_radius);
127 x_pixels = new scalar_t[nb_pixels];
128 y_pixels = new scalar_t[nb_pixels];
129 for(int p = 0; p < nb_pixels; p++) {
130 x_pixels[p] = tmp_x_pixels[p];
131 y_pixels[p] = tmp_y_pixels[p];
134 rotate(random_uniform_0_1() * M_PI * 2);
136 // { // ******************************* START ***************************
137 // #warning Test code added on 2009 Sep 09 18:15:25
138 // for(int p = 0; p < nb_pixels; p++) {
139 // cout << x_pixels[p] << " " << y_pixels[p] << endl;
141 // } // ******************************** END ****************************
145 void Shape::copy(Shape *shape) {
148 nb_pixels = shape->nb_pixels;
149 n_pixels1 = shape->n_pixels1;
150 n_pixels2 = shape->n_pixels2;
151 n_pixels3 = shape->n_pixels3;
152 n_pixels4 = shape->n_pixels4;
153 x_pixels = new scalar_t[nb_pixels];
154 y_pixels = new scalar_t[nb_pixels];
155 for(int p = 0; p < nb_pixels; p++) {
156 x_pixels[p] = shape->x_pixels[p];
157 y_pixels[p] = shape->y_pixels[p];
161 void Shape::scale(scalar_t s) {
162 for(int p = 0; p < nb_pixels; p++) {
168 void Shape::rotate(scalar_t alpha) {
169 scalar_t ux = cos(alpha), uy = -sin(alpha);
170 scalar_t vx = sin(alpha), vy = cos(alpha);
172 for(int p = 0; p < nb_pixels; p++) {
173 x = x_pixels[p] * ux + y_pixels[p] * uy;
174 y = x_pixels[p] * vx + y_pixels[p] * vy;
180 void Shape::symmetrize(scalar_t axis_x, scalar_t axis_y) {
181 scalar_t sql = sq(axis_x) + sq(axis_y);
183 for(int p = 0; p < nb_pixels; p++) {
184 u = x_pixels[p] * axis_y - y_pixels[p] * axis_x;
185 v = x_pixels[p] * axis_x + y_pixels[p] * axis_y;
187 x_pixels[p] = ( u * axis_y + v * axis_x) / sql;
188 y_pixels[p] = (- u * axis_x + v * axis_y) / sql;
193 int Shape::overwrites(Vignette *vignette, scalar_t xc, scalar_t yc, int n1, int n2) {
194 int x1 = int(x_pixels[n1 % nb_pixels] + xc);
195 int y1 = int(y_pixels[n1 % nb_pixels] + yc);
196 int x2 = int(x_pixels[n2 % nb_pixels] + xc);
197 int y2 = int(y_pixels[n2 % nb_pixels] + yc);
198 int n3 = (n1 + n2) / 2;
200 if(n1 + 1 < n2 && (abs(x1 - x2) > 1 || abs(y1 - y2) > 1)) {
202 overwrites(vignette, xc, yc, n1, n3) ||
203 overwrites(vignette, xc, yc, n3, n2);
206 if(x1 >= margin && x1 < Vignette::width - margin &&
207 y1 >= margin && y1 < Vignette::height - margin) {
210 for(int xx = x1 - margin; xx <= x1 + margin; xx++) {
211 for(int yy = y1 - margin; yy <= y1 + margin; yy++) {
212 if(vignette->content[xx + Vignette::width * yy] != 255) {
226 int Shape::overwrites(Vignette *vignette, scalar_t xc, scalar_t yc) {
228 overwrites(vignette, xc, yc, n_pixels1, n_pixels2) ||
229 overwrites(vignette, xc, yc, n_pixels2, n_pixels3) ||
230 overwrites(vignette, xc, yc, n_pixels3, n_pixels4) ||
231 overwrites(vignette, xc, yc, n_pixels4, nb_pixels);
234 void Shape::draw(int part_number, Vignette *vignette, scalar_t xc, scalar_t yc, int n1, int n2) {
235 int x1 = int(x_pixels[n1 % nb_pixels] + xc);
236 int y1 = int(y_pixels[n1 % nb_pixels] + yc);
237 int x2 = int(x_pixels[n2 % nb_pixels] + xc);
238 int y2 = int(y_pixels[n2 % nb_pixels] + yc);
239 int n3 = (n1 + n2) / 2;
241 if(n1 + 1 < n2 && (abs(x1 - x2) > 1 || abs(y1 - y2) > 1)) {
242 draw(part_number, vignette, xc, yc, n1, n3);
243 draw(part_number, vignette, xc, yc, n3, n2);
245 if(x1 >= margin && x1 < Vignette::width-margin &&
246 y1 >= margin && y1 < Vignette::height-margin) {
247 vignette->content[x1 + Vignette::width * y1] = 0;
248 #ifdef KEEP_PART_PRESENCE
249 vignette->part_presence[x1 + Vignette::width * y1] |= (1 << part_number);
257 void Shape::draw(int part_number, Vignette *vignette, scalar_t xc, scalar_t yc) {
258 draw(part_number, vignette, xc, yc, n_pixels1, n_pixels2);
259 draw(part_number, vignette, xc, yc, n_pixels2, n_pixels3);
260 draw(part_number, vignette, xc, yc, n_pixels3, n_pixels4);
261 draw(part_number, vignette, xc, yc, n_pixels4, nb_pixels);