--- /dev/null
+
+# svrt is the ``Synthetic Visual Reasoning Test'', an image generator
+# for evaluating classification performance of machine learning
+# systems, humans and primates.
+#
+# Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+# Written by Francois Fleuret <francois.fleuret@idiap.ch>
+#
+# This file is part of svrt.
+#
+# svrt is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation.
+#
+# svrt is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with selector. If not, see <http://www.gnu.org/licenses/>.
+
+LDFLAGS=-lm -ljpeg -lpng
+
+ifeq ($(DEBUG),yes)
+ OPTIMIZE_FLAG = -ggdb3 -DDEBUG -fno-omit-frame-pointer
+else
+ OPTIMIZE_FLAG = -ggdb3 -O3
+endif
+
+ifeq ($(PROFILE),yes)
+ PROFILE_FLAG = -pg
+endif
+
+CXXFLAGS = -Wall $(OPTIMIZE_FLAG) $(PROFILE_FLAG) $(CXXGLPK)
+
+all: vision_test TAGS
+
+TAGS: *.cc *.h
+ etags --members -l c++ *.cc *.h
+
+vision_test: misc.o rgb_image.o jpeg_misc.o fusion_sort.o global.o param_parser.o progress_bar.o \
+ discrete_density.o \
+ tools.o \
+ vignette.o \
+ shape.o \
+ vignette_generator.o \
+ vision_problem_tools.o \
+ vision_problem_1.o \
+ vision_problem_2.o \
+ vision_problem_3.o \
+ vision_problem_5.o \
+ vision_problem_6.o \
+ vision_problem_8.o \
+ vision_problem_11.o \
+ vision_problem_12.o \
+ vision_problem_13.o \
+ vision_problem_17.o \
+ vision_problem_18.o \
+ vision_problem_20.o \
+ vision_problem_21.o \
+ classifier_reader.o \
+ classifier.o naive_bayesian_classifier.o \
+ stump.o boosted_classifier.o \
+ error_rates.o \
+ vision_test.o
+ $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
+
+Makefile.depend: *.h *.cc Makefile
+ $(CC) -M *.cc > Makefile.depend
+
+clean:
+ \rm -f vision_test *.o Makefile.depend TAGS
+
+-include Makefile.depend
--- /dev/null
+This software should compile on any standard GNU/Linux machine, and
+UNIX machine in general. It only requires the jpeg and png library.
+
+To test it on a list of problems, just run the script doit.sh with the
+problem numbers as arguments. For instance:
+
+ ./doit.sh 1 2 3
+
+It will compile the source and run the executable on the specified
+problems to generate sample images and test a Boosted classifier. If
+no argument is given, it will run on all the problems by default.
+
+--
+Francois Fleuret, Nov 2009.
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "boosted_classifier.h"
+#include "classifier_reader.h"
+#include "fusion_sort.h"
+#include "tools.h"
+
+inline scalar_t loss_derivative(int label, scalar_t response) {
+ return - scalar_t(label * 2 - 1) * exp( - scalar_t(label * 2 - 1) * response );
+}
+
+BoostedClassifier::BoostedClassifier() {
+ _nb_stumps = 0;
+ _stumps = 0;
+}
+
+BoostedClassifier::BoostedClassifier(int nb_weak_learners) {
+ _nb_stumps = nb_weak_learners;
+ _stumps = new Stump[_nb_stumps];
+}
+
+BoostedClassifier::~BoostedClassifier() {
+ delete[] _stumps;
+}
+
+const char *BoostedClassifier::name() {
+ return "ADABOOST";
+}
+
+void BoostedClassifier::chose_stump_from_sampling(int t, int **integral_images, scalar_t *derivatives, int nb_samples) {
+ int *indexes = new int[nb_samples];
+ int *sorted_indexes = new int[nb_samples];
+ scalar_t *stump_counts = new scalar_t[nb_samples];
+
+ scalar_t max_loss_derivative = 0;
+ Stump tmp;
+ tmp.weight0 = -1;
+ tmp.weight1 = 1;
+ tmp.threshold = 0;
+
+ for(int k = 0; k < global.nb_optimization_weak_learners; k++) {
+ tmp.randomize();
+ scalar_t s = 0;
+
+ for(int n = 0; n < nb_samples; n++) {
+ stump_counts[n] = tmp.count(integral_images[n]);
+ indexes[n] = n;
+ s += derivatives[n];
+ }
+
+ indexed_fusion_sort(nb_samples, indexes, sorted_indexes, stump_counts);
+
+ for(int n = 0; n < nb_samples - 1; n++) {
+ int i = sorted_indexes[n];
+ int j = sorted_indexes[n + 1];
+ s -= 2 * derivatives[i];
+ if(stump_counts[j] > stump_counts[i]) {
+ if(abs(s) > abs(max_loss_derivative)) {
+ max_loss_derivative = s;
+ _stumps[t] = tmp;
+ _stumps[t].threshold = (stump_counts[i] + stump_counts[j])/2;
+ }
+ }
+ }
+ }
+
+ delete[] stump_counts;
+ delete[] indexes;
+ delete[] sorted_indexes;
+}
+
+void BoostedClassifier::chose_stump(int t, int **integral_images, scalar_t *derivatives, int nb_samples) {
+ if(global.nb_sampled_samples <= 0) {
+ chose_stump_from_sampling(t, integral_images, derivatives, nb_samples);
+ } else {
+ int *sampled_indexes = new int[global.nb_sampled_samples];
+ scalar_t *weights = new scalar_t[nb_samples];
+ for(int s = 0; s < nb_samples; s++) {
+ weights[s] = abs(derivatives[s]);
+ }
+ robust_sampling(nb_samples, weights, global.nb_sampled_samples, sampled_indexes);
+ delete[] weights;
+
+ int **sampled_integral_images = new int *[global.nb_sampled_samples];
+ scalar_t *sampled_derivatives = new scalar_t[global.nb_sampled_samples];
+
+ for(int s = 0; s < global.nb_sampled_samples; s++) {
+ sampled_integral_images[s] = integral_images[sampled_indexes[s]];
+ if(derivatives[sampled_indexes[s]] > 0) {
+ sampled_derivatives[s] = 1.0;
+ } else {
+ sampled_derivatives[s] = -1.0;
+ }
+ }
+
+ chose_stump_from_sampling(t, sampled_integral_images, sampled_derivatives, global.nb_sampled_samples);
+
+ delete[] sampled_derivatives;
+ delete[] sampled_integral_images;
+ delete[] sampled_indexes;
+ }
+}
+
+void BoostedClassifier::train(int nb_vignettes, Vignette *vignettes, int *labels) {
+ int **integral_images = new int *[nb_vignettes];
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ integral_images[n] = new int[(Vignette::width + 1) * (Vignette::height + 1)];
+ compute_integral_image(&vignettes[n], integral_images[n]);
+ }
+
+ scalar_t *responses = new scalar_t[nb_vignettes];
+ scalar_t *derivatives = new scalar_t[nb_vignettes];
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ responses[n] = 0.0;
+ }
+
+ global.bar.init(&cout, _nb_stumps);
+ for(int t = 0; t < _nb_stumps; t++) {
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ derivatives[n] = loss_derivative(labels[n], responses[n]);
+ }
+
+ chose_stump(t, integral_images, derivatives, nb_vignettes);
+
+ scalar_t num0 = 0, den0 = 0, num1 = 0, den1 = 0;
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ if(_stumps[t].response(integral_images[n]) > 0) {
+ if(labels[n] == 1) {
+ num1 += exp( - responses[n] );
+ } else {
+ den1 += exp( responses[n] );
+ }
+ } else {
+ if(labels[n] == 1) {
+ num0 += exp( - responses[n] );
+ } else {
+ den0 += exp( responses[n] );
+ }
+ }
+ }
+
+ scalar_t weight_max = 5.0;
+
+ _stumps[t].weight0 = 0.5 * log(num0 / den0);
+
+ if(_stumps[t].weight0 < -weight_max)
+ _stumps[t].weight0 = -weight_max;
+ else if(_stumps[t].weight0 > weight_max)
+ _stumps[t].weight0 = weight_max;
+
+ _stumps[t].weight1 = 0.5 * log(num1 / den1);
+ if(_stumps[t].weight1 < -weight_max)
+ _stumps[t].weight1 = -weight_max;
+ else if(_stumps[t].weight1 > weight_max)
+ _stumps[t].weight1 = weight_max;
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ responses[n] += _stumps[t].response(integral_images[n]);
+ }
+
+ // cout << "ADABOOST_STEP " << t + 1 << " " << loss << endl;
+ global.bar.refresh(&cout, t);
+ }
+ global.bar.finish(&cout);
+
+ scalar_t loss = 0;
+ for(int n = 0; n < nb_vignettes; n++) {
+ loss += exp( - scalar_t(labels[n] * 2 - 1) * responses[n]);
+ }
+
+ cout << "Final loss is " << loss << endl;
+
+ delete[] derivatives;
+ delete[] responses;
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ delete[] integral_images[n];
+ }
+
+ delete[] integral_images;
+}
+
+scalar_t BoostedClassifier::classify(Vignette *vignette) {
+ int integral_image[(Vignette::width + 1) * (Vignette::height + 1)];
+ compute_integral_image(vignette, integral_image);
+ scalar_t result = 0;
+ for(int n = 0; n < _nb_stumps; n++) {
+ result += _stumps[n].response(integral_image);
+ }
+ return result;
+}
+
+void BoostedClassifier::read(istream *in) {
+ delete[] _stumps;
+ read_var(in, &_nb_stumps);
+ cout << "Reading " << _nb_stumps << " stumps." << endl;
+ _stumps = new Stump[_nb_stumps];
+ in->read((char *) _stumps, sizeof(Stump) * _nb_stumps);
+}
+
+void BoostedClassifier::write(ostream *out) {
+ int t;
+ t = CT_BOOSTED;
+ write_var(out, &t);
+ write_var(out, &_nb_stumps);
+ out->write((char *) _stumps, sizeof(Stump) * _nb_stumps);
+}
+
+scalar_t BoostedClassifier::partial_sum(int first, int nb, Vignette *vignette) {
+ int integral_image[(Vignette::width + 1) * (Vignette::height + 1)];
+ compute_integral_image(vignette, integral_image);
+ scalar_t result = 0;
+ for(int n = first; n < first + nb; n++) {
+ result += _stumps[n].response(integral_image);
+ }
+ return result;
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BOOSTED_CLASSIFIER_H
+#define BOOSTED_CLASSIFIER_H
+
+#include "classifier.h"
+#include "stump.h"
+
+class BoostedClassifier : public Classifier {
+ Stump *_stumps;
+ int _nb_stumps;
+ void chose_stump_from_sampling(int t, int **integral_images, scalar_t *derivatives, int nb_samples);
+ void chose_stump(int t, int **integral_images, scalar_t *derivatives, int nb_samples);
+public:
+ BoostedClassifier();
+ BoostedClassifier(int nb_weak_learners);
+ ~BoostedClassifier();
+ inline int nb_stumps() { return _nb_stumps; }
+ virtual const char *name();
+ virtual void train(int nb_vignettes, Vignette *vignettes, int *labels);
+ virtual scalar_t classify(Vignette *vignette);
+ virtual void read(istream *in);
+ virtual void write(ostream *out);
+ scalar_t partial_sum(int first, int nb, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "classifier.h"
+
+Classifier::~Classifier() { }
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CLASSIFIER_H
+#define CLASSIFIER_H
+
+#include "misc.h"
+#include "vignette.h"
+
+class Classifier {
+public:
+
+ // We need a virtual destructor since there are virtual methods
+ virtual ~Classifier();
+
+ // This method returns an upper-caps string to identify the classifier
+ virtual const char *name() = 0;
+
+ // Train the classifier from a set of vignettes. The labels are in the
+ // vignettes.
+ virtual void train(int nb_vignettes, Vignette *vignettes, int *labels) = 0;
+
+ // Compute a scalar value which should be strictly positive on
+ // positive vignettes and strictly negative on negative ones.
+ virtual scalar_t classify(Vignette *vignette) = 0;
+
+ // Read or write the classifier from or to a stream
+ virtual void read(istream *in) = 0;
+ virtual void write(ostream *out) = 0;
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "misc.h"
+#include "classifier_reader.h"
+#include "naive_bayesian_classifier.h"
+#include "boosted_classifier.h"
+
+Classifier *read_classifier(istream *in) {
+ Classifier *result = 0;
+
+ unsigned int t;
+ read_var(in, &t);
+
+ switch(t) {
+ case CT_NAIVE_BAYESIAN:
+ cout << "Reading a CT_NAIVE_BAYESIAN." << endl;
+ result = new NaiveBayesianClassifier();
+ result->read(in);
+ break;
+ case CT_BOOSTED:
+ cout << "Reading a CT_BOOSTED." << endl;
+ result = new BoostedClassifier();
+ result->read(in);
+ break;
+ default:
+ cerr << "Unknown classifier type for reading." << endl;
+ abort();
+ }
+
+ return result;
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CLASSIFIER_READER_H
+#define CLASSIFIER_READER_H
+
+#include "classifier.h"
+
+enum {
+ CT_NAIVE_BAYESIAN,
+ CT_BOOSTED
+};
+
+Classifier *read_classifier(istream *in);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "discrete_density.h"
+
+DiscreteDensityTree::DiscreteDensityTree(scalar_t *proba, int first_value, int nb_values) {
+ if(nb_values > 1) {
+ _proba_tree0 = 0;
+ for(int n = 0; n < nb_values/2; n++) _proba_tree0 += proba[first_value + n];
+ scalar_t s = 0;
+ for(int n = 0; n < nb_values; n++) s += proba[first_value + n];
+ _proba_tree0 /= s;
+ _tree0 = new DiscreteDensityTree(proba, first_value, nb_values/2);
+ _tree1 = new DiscreteDensityTree(proba, first_value + nb_values/2, nb_values - (nb_values/2));
+ } else {
+ _tree0 = 0;
+ _tree1 = 0;
+ _value = first_value;
+ }
+}
+
+DiscreteDensityTree::~DiscreteDensityTree() {
+ if(_tree0) delete _tree0;
+ if(_tree1) delete _tree1;
+}
+
+int DiscreteDensityTree::sample() {
+ if(_tree0) {
+ if(drand48() < _proba_tree0)
+ return _tree0->sample();
+ else
+ return _tree1->sample();
+ } else return _value;
+}
+
+DiscreteDensity::DiscreteDensity(int nb_values) {
+ _nb_values = nb_values;
+ _probas = new scalar_t[_nb_values];
+ _log_probas = new scalar_t[_nb_values];
+ _sampling_tree = 0;
+}
+
+DiscreteDensity::~DiscreteDensity() {
+ delete[] _probas;
+ delete[] _log_probas;
+ delete _sampling_tree;
+}
+
+void DiscreteDensity::set_non_normalized_proba(int n, scalar_t p) {
+ _probas[n] = p;
+}
+
+void DiscreteDensity::normalize() {
+ scalar_t s = 0;
+ for(int k = 0; k < _nb_values; k++) {
+ s += _probas[k];
+ }
+ for(int k = 0; k < _nb_values; k++) {
+ _probas[k] /= s;
+ _log_probas[k] = log(_probas[k]);
+ }
+ delete _sampling_tree;
+ _sampling_tree = new DiscreteDensityTree(_probas, 0, _nb_values);
+}
+
+scalar_t DiscreteDensity::entropy() {
+ scalar_t h = 0;
+ for(int k = 0; k < _nb_values; k++) {
+ if(_probas[k] > 0) h += - _probas[k] * _log_probas[k]/log(2.0);
+ }
+ return h;
+}
+
+scalar_t DiscreteDensity::proba(int n) {
+ return _probas[n];
+}
+
+scalar_t DiscreteDensity::log_proba(int n) {
+ return _log_probas[n];
+}
+
+int DiscreteDensity::sample() {
+ return _sampling_tree->sample();
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DISCRETE_DENSITY_H
+#define DISCRETE_DENSITY_H
+
+#include "misc.h"
+
+class DiscreteDensityTree {
+ scalar_t _proba_tree0;
+ DiscreteDensityTree *_tree0, *_tree1;
+ int _value;
+public:
+ DiscreteDensityTree(scalar_t *proba, int first_value, int nb_values);
+ ~DiscreteDensityTree();
+ int sample();
+};
+
+class DiscreteDensity {
+ DiscreteDensityTree *_sampling_tree;
+ int _nb_values;
+ scalar_t *_probas, *_log_probas;
+public:
+ DiscreteDensity(int nb_values);
+ ~DiscreteDensity();
+
+ void set_non_normalized_proba(int n, scalar_t p);
+ void normalize();
+ scalar_t entropy();
+
+ scalar_t proba(int n);
+ scalar_t log_proba(int n);
+ int sample();
+};
+
+#endif
--- /dev/null
+#!/bin/bash
+
+# svrt is the ``Synthetic Visual Reasoning Test'', an image generator
+# for evaluating classification performance of machine learning
+# systems, humans and primates.
+#
+# Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+# Written by Francois Fleuret <francois.fleuret@idiap.ch>
+#
+# This file is part of svrt.
+#
+# svrt is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation.
+#
+# svrt is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with selector. If not, see <http://www.gnu.org/licenses/>.
+
+nb_samples_to_save=100
+nb_samples_for_training=1000
+
+problem_list=$*
+
+[[ ${problem_list} ]] || problem_list="1 2 3 5 6 8 11 12 13 17 18 20 21"
+
+set -e
+
+make -j -k vision_test
+
+for problem_number in ${problem_list}; do
+
+ result_dir=./results_problem_${problem_number}/
+
+ mkdir -p ${result_dir}
+
+ ./vision_test \
+ --problem_number=${problem_number} \
+ --nb_train_samples=${nb_samples_to_save} \
+ --result_path=${result_dir} \
+ write-samples
+
+ ./vision_test \
+ --problem_number=${problem_number} \
+ --nb_train_samples=${nb_samples_for_training} \
+ --result_path=${result_dir} \
+ randomize-train adaboost compute-train-error compute-test-error
+
+done
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "error_rates.h"
+#include "rgb_image.h"
+
+scalar_t error_rate(Classifier *classifier, int nb_vignettes, Vignette *vignettes, int *labels) {
+ int e = 0;
+
+ for(int n = 0; n < nb_vignettes; n++) {
+ if(classifier->classify(&vignettes[n]) >= 0) {
+ if(labels[n] == 0) e++;
+ } else {
+ if(labels[n] == 1) e++;
+ }
+ }
+
+ return scalar_t(e)/scalar_t(nb_vignettes);
+}
+
+scalar_t test_error_rate(VignetteGenerator *generator, Classifier *classifier, long int nb_to_try) {
+ scalar_t e = 0;
+ Vignette vignette;
+ int label;
+
+ global.bar.init(&cout, nb_to_try);
+
+ for(long int k = 0; k < nb_to_try; k++) {
+ label = int(drand48() * 2);
+ generator->generate(label, &vignette);
+ if(classifier->classify(&vignette) >= 0) {
+ if(label == 0) e++;
+ } else {
+ if(label == 1) e++;
+ }
+ global.bar.refresh(&cout, k);
+ }
+ global.bar.finish(&cout);
+
+ return scalar_t(e)/scalar_t(nb_to_try);
+}
+
+
+void compute_response_mu_and_sigma(int nb_samples, Vignette *vignette, Classifier *classifier,
+ scalar_t *mu, scalar_t *sigma) {
+ scalar_t sum = 0, sum_sq = 0;
+ const int nb_pixels_to_switch = 1;
+ int changed_pixels[nb_pixels_to_switch];
+
+ for(int n = 0; n < nb_samples; n++) {
+ for(int p = 0; p < nb_pixels_to_switch; p++) {
+ changed_pixels[p] = int(drand48() * Vignette::width * Vignette::height);
+ vignette->content[changed_pixels[p]] = 255 - vignette->content[changed_pixels[p]];
+ }
+
+ scalar_t r = classifier->classify(vignette);
+ sum += r;
+ sum_sq += sq(r);
+
+ for(int p = 0; p < nb_pixels_to_switch; p++) {
+ vignette->content[changed_pixels[p]] = 255 - vignette->content[changed_pixels[p]];
+ }
+ }
+
+ *mu = sum_sq/scalar_t(nb_samples);
+ *sigma = *mu - sq(sum/scalar_t(nb_samples));
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ERROR_RATES_H
+#define ERROR_RATES_H
+
+#include "classifier.h"
+#include "vignette_generator.h"
+
+scalar_t error_rate(Classifier *classifier, int nb_vignettes, Vignette *vignettes, int *labels);
+
+scalar_t test_error_rate(VignetteGenerator *generator, Classifier *classifier, long int nb_to_try);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "fusion_sort.h"
+#include <string.h>
+
+inline void indexed_fusion(int na, int *ia, int nb, int *ib, int *ic, scalar_t *values) {
+ int *ma = ia + na, *mb = ib + nb;
+ while(ia < ma && ib < mb)
+ if(values[*ia] <= values[*ib]) *(ic++) = *(ia++);
+ else *(ic++) = *(ib++);
+ while(ia < ma) *(ic++) = *(ia++);
+ while(ib < mb) *(ic++) = *(ib++);
+}
+
+void indexed_fusion_sort(int n, int *from, int *result, scalar_t *values) {
+ ASSERT(n > 0);
+ if(n == 1) result[0] = from[0];
+ else {
+ int k = n/2;
+ indexed_fusion_sort(k, from, result, values);
+ indexed_fusion_sort(n - k, from + k, result + k, values);
+ memcpy((void *) from, (void *) result, n * sizeof(int));
+ indexed_fusion(k, from, n - k, from + k, result, values);
+ }
+}
+
+// Sorting in decreasing order
+
+inline void indexed_fusion_dec(int na, int *ia,
+ int nb, int *ib,
+ int *ic, scalar_t *values) {
+ int *ma = ia + na, *mb = ib + nb;
+ while(ia < ma && ib < mb)
+ if(values[*ia] > values[*ib]) *(ic++) = *(ia++);
+ else *(ic++) = *(ib++);
+ while(ia < ma) *(ic++) = *(ia++);
+ while(ib < mb) *(ic++) = *(ib++);
+}
+
+void indexed_fusion_dec_sort(int n, int *from, int *result, scalar_t *values) {
+ ASSERT(n > 0);
+ if(n == 1) result[0] = from[0];
+ else {
+ int k = n/2;
+ indexed_fusion_dec_sort(k, from, result, values);
+ indexed_fusion_dec_sort(n - k, from + k, result + k, values);
+ memcpy((void *) from, (void *) result, n * sizeof(int));
+ indexed_fusion_dec(k, from, n - k, from + k, result, values);
+ }
+}
+
+void fusion_two_cells(int n1, scalar_t *cell1, int n2, scalar_t *cell2, scalar_t *result) {
+ scalar_t *max1 = cell1 + n1, *max2 = cell2 + n2;
+ while(cell1 < max1 && cell2 < max2) {
+ if(*(cell1) <= *(cell2)) *(result++) = *(cell1++);
+ else *(result++) = *(cell2++);
+ }
+ while(cell1 < max1) *(result++) = *(cell1++);
+ while(cell2 < max2) *(result++) = *(cell2++);
+}
+
+void fusion_sort(int n, scalar_t *from, scalar_t *result) {
+ if(n > 1) {
+ fusion_sort(n/2, from, result);
+ fusion_sort(n - n/2, from + n/2, result + n/2);
+ memcpy(from, result, sizeof(scalar_t) * n);
+ fusion_two_cells(n/2, from, n - n/2, from + n/2, result);
+ } else result[0] = from[0];
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FUSION_SORT_H
+#define FUSION_SORT_H
+
+#include "misc.h"
+
+void indexed_fusion_sort(int n, int *from, int *result, scalar_t *values);
+void indexed_fusion_dec_sort(int n, int *from, int *result, scalar_t *values);
+void fusion_sort(int n, scalar_t *from, scalar_t *result);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <string.h>
+
+#include "global.h"
+
+Global global;
+
+Global::Global() { }
+
+Global::~Global() { }
+
+void Global::init_parser(ParamParser *parser) {
+ // The nice level of the process
+ parser->add_association("niceness", "15", false);
+ // Seed to initialize the random generator
+ parser->add_association("random_seed", "0", false);
+
+ // Where to put the generated files
+ parser->add_association("result_path", "/tmp/", false);
+ // The classifier filename
+ parser->add_association("classifier_name", "default.clf", false);
+
+ // Should we display a progress bar for lengthy operations
+ parser->add_association("progress_bar", "yes", false);
+
+ // The problem number
+ parser->add_association("problem_number", "0", false);
+
+ // The number of samples for training and testing
+ parser->add_association("nb_train_samples", "1000", false);
+ parser->add_association("nb_test_samples", "1000", false);
+ parser->add_association("nb_weak_learners", "1000", false);
+ parser->add_association("nb_optimization_weak_learners", "100", false);
+ parser->add_association("nb_sampled_samples", "-1", false);
+}
+
+void Global::read_parser(ParamParser *parser) {
+ niceness = parser->get_association_int("niceness");
+ random_seed = parser->get_association_int("random_seed");
+
+ strncpy(result_path, parser->get_association("result_path"), buffer_size);
+ strncpy(classifier_name, parser->get_association("classifier_name"), buffer_size);
+ if(!classifier_name[0]) {
+ sprintf(classifier_name, "%s/default.clf", result_path);
+ }
+
+ bar.set_visible(parser->get_association_bool("progress_bar"));
+
+ problem_number = parser->get_association_int("problem_number");
+
+ nb_train_samples = parser->get_association_int("nb_train_samples");
+ nb_test_samples = parser->get_association_int("nb_test_samples");
+ nb_weak_learners = parser->get_association_int("nb_weak_learners");
+ nb_optimization_weak_learners = parser->get_association_int("nb_optimization_weak_learners");
+ nb_sampled_samples = parser->get_association_int("nb_sampled_samples");
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#include <iostream>
+
+using namespace std;
+
+#include "misc.h"
+#include "param_parser.h"
+#include "progress_bar.h"
+
+class Global {
+public:
+ int niceness;
+ int random_seed;
+ char result_path[buffer_size];
+ char classifier_name[buffer_size];
+ ProgressBar bar;
+
+ int problem_number;
+
+ int nb_train_samples;
+ int nb_test_samples;
+ int nb_weak_learners;
+ int nb_optimization_weak_learners;
+ int nb_sampled_samples;
+
+ Global();
+ ~Global();
+
+ void init_parser(ParamParser *parser);
+ void read_parser(ParamParser *parser);
+};
+
+extern Global global;
+
+#endif
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "jpeg_misc.h"
+
+void my_error_exit (j_common_ptr cinfo) {
+ my_error_ptr myerr = (my_error_ptr) cinfo->err;
+ (*cinfo->err->output_message) (cinfo);
+ longjmp (myerr->setjmp_buffer, 1);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef JPEG_MISC_H
+#define JPEG_MISC_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <jpeglib.h>
+
+struct my_error_mgr {
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+typedef struct my_error_mgr *my_error_ptr;
+
+void my_error_exit (j_common_ptr cinfo);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <fstream>
+
+using namespace std;
+
+#include "misc.h"
+
+char *basename(char *name) {
+ char *result = name;
+ while(*name) {
+ if(*name == '/') result = name + 1;
+ name++;
+ }
+ return result;
+}
+
+char *next_word(char *buffer, char *r, int buffer_size) {
+ char *s;
+ s = buffer;
+
+ if(r != 0) {
+ while((*r == ' ') || (*r == '\t') || (*r == ',')) r++;
+ if(*r == '"') {
+ r++;
+ while((*r != '"') && (*r != '\0') &&
+ (s<buffer+buffer_size-1))
+ *s++ = *r++;
+ if(*r == '"') r++;
+ } else {
+ while((*r != '\r') && (*r != '\n') && (*r != '\0') &&
+ (*r != '\t') && (*r != ' ') && (*r != ',')) {
+ if(s == buffer + buffer_size) {
+ cerr << "Buffer overflow in next_word." << endl;
+ exit(1);
+ }
+ *s++ = *r++;
+ }
+ }
+
+ while((*r == ' ') || (*r == '\t') || (*r == ',')) r++;
+ if((*r == '\0') || (*r=='\r') || (*r=='\n')) r = 0;
+ }
+ *s = '\0';
+
+ return r;
+}
+
+scalar_t discrete_entropy(int *n, int nb) {
+ scalar_t s = 0, t = 0;
+ for(int k = 0; k < nb; k++) if(n[k] > 0) {
+ s += n[k] * log(scalar_t(n[k]));
+ t += n[k];
+ }
+ return (log(t) - s/scalar_t(t))/log(2.0);
+}
+
+void random_permutation(int *val, int nb) {
+ for(int k = 0; k < nb; k++) val[k] = k;
+ int i, t;
+ for(int k = 0; k < nb - 1; k++) {
+ i = int(drand48() * (nb - k)) + k;
+ t = val[i];
+ val[i] = val[k];
+ val[k] = t;
+ }
+}
+
+void tag_subset(bool *val, int nb_total, int nb_to_tag) {
+ ASSERT(nb_to_tag <= nb_total);
+ int index[nb_total];
+ random_permutation(index, nb_total);
+ for(int n = 0; n < nb_total; n++) val[n] = false;
+ for(int n = 0; n < nb_to_tag; n++) val[index[n]] = true;
+}
+
+int compare_couple(const void *a, const void *b) {
+ if(((Couple *) a)->value < ((Couple *) b)->value) return -1;
+ else if(((Couple *) a)->value > ((Couple *) b)->value) return 1;
+ else return 0;
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MISC_H
+#define MISC_H
+
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <cfloat>
+#include <stdlib.h>
+#include <string.h>
+
+using namespace std;
+
+typedef double scalar_t;
+// typedef float scalar_t;
+
+const int buffer_size = 1024;
+
+using namespace std;
+
+#ifdef DEBUG
+#define ASSERT(x) if(!(x)) { \
+ std::cerr << "ASSERT FAILED IN " << __FILE__ << ":" << __LINE__ << endl; \
+ abort(); \
+}
+#else
+#define ASSERT(x)
+#endif
+
+template<class T>
+T **allocate_array(int a, int b) {
+ T *tmp = new T[a * b];
+ T **array = new T *[a];
+ for(int k = 0; k < a; k++) {
+ array[k] = tmp;
+ tmp += b;
+ }
+ return array;
+}
+
+template<class T>
+void deallocate_array(T **array) {
+ delete[] array[0];
+ delete[] array;
+}
+
+template<class T>
+T smooth_min(T x, T y) {
+ T z = exp(x - y);
+ return 0.5 * (x + y - (x - y)/(1 + 1/z) - (y - x)/(1 + z));
+}
+
+template <class T>
+void write_var(ostream *os, const T *x) { os->write((char *) x, sizeof(T)); }
+
+template <class T>
+void read_var(istream *is, T *x) { is->read((char *) x, sizeof(T)); }
+
+template <class T>
+void grow(int *nb_max, int nb, T** current, int factor) {
+ ASSERT(*nb_max > 0);
+ if(nb == *nb_max) {
+ T *tmp = new T[*nb_max * factor];
+ memcpy(tmp, *current, *nb_max * sizeof(T));
+ delete[] *current;
+ *current = tmp;
+ *nb_max *= factor;
+ }
+}
+
+template <class T>
+inline T sq(T x) {
+ return x * x;
+}
+
+inline scalar_t log2(scalar_t x) {
+ return log(x)/log(2.0);
+}
+
+inline scalar_t xi(scalar_t x) {
+ if(x <= 0.0) return 0.0;
+ else return - x * log(x)/log(2.0);
+}
+
+scalar_t discrete_entropy(int *n, int nb);
+
+char *basename(char *name);
+
+char *next_word(char *buffer, char *r, int buffer_size);
+
+void random_permutation(int *val, int nb);
+void tag_subset(bool *val, int nb_total, int nb_to_tag);
+
+struct Couple {
+ int index;
+ scalar_t value;
+};
+
+int compare_couple(const void *a, const void *b);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "naive_bayesian_classifier.h"
+#include "classifier_reader.h"
+
+NaiveBayesianClassifier::NaiveBayesianClassifier() { }
+
+NaiveBayesianClassifier::~NaiveBayesianClassifier() { }
+
+const char *NaiveBayesianClassifier::name() {
+ return "NAIVE_BAYESIAN";
+}
+
+void NaiveBayesianClassifier::train(int nb_vignettes, Vignette *vignettes, int *labels) {
+ for(int k = 0; k < Vignette::width * Vignette::height * Vignette::nb_grayscales; k++) {
+ proba_given_0[k] = 0;
+ proba_given_1[k] = 0;
+ }
+
+ int nb_0 = 0, nb_1 = 0;
+
+ global.bar.init(&cout, nb_vignettes);
+ for(int n = 0; n < nb_vignettes; n++) {
+ if(labels[n] == 1) {
+ nb_1++;
+ for(int k = 0; k < Vignette::width * Vignette::height; k++) {
+ proba_given_1[k * Vignette::nb_grayscales + vignettes[n].content[k]] += 1.0;
+ }
+ } else {
+ nb_0++;
+ for(int k = 0; k < Vignette::width * Vignette::height; k++) {
+ proba_given_0[k * Vignette::nb_grayscales + vignettes[n].content[k]] += 1.0;
+ }
+ }
+ global.bar.refresh(&cout, n);
+ }
+ global.bar.finish(&cout);
+
+ for(int k = 0; k < Vignette::width * Vignette::height * Vignette::nb_grayscales; k++) {
+ proba_given_0[k] /= scalar_t(nb_0);
+ proba_given_1[k] /= scalar_t(nb_1);
+ }
+}
+
+scalar_t NaiveBayesianClassifier::classify(Vignette *vignette) {
+ scalar_t result = 0.0;
+
+ for(int k = 0; k < Vignette::width * Vignette::height; k++) {
+ result += log(proba_given_1[k * Vignette::nb_grayscales + vignette->content[k]])
+ - log(proba_given_0[k * Vignette::nb_grayscales + vignette->content[k]]);
+ }
+
+ return result;
+}
+
+void NaiveBayesianClassifier::read(istream *in) {
+ in->read((char *) proba_given_0, sizeof(scalar_t) * Vignette::width * Vignette::height * Vignette::nb_grayscales);
+ in->read((char *) proba_given_1, sizeof(scalar_t) * Vignette::width * Vignette::height * Vignette::nb_grayscales);
+}
+
+void NaiveBayesianClassifier::write(ostream *out) {
+ int t;
+ t = CT_NAIVE_BAYESIAN;
+ write_var(out, &t);
+ out->write((char *) proba_given_0, sizeof(scalar_t) * Vignette::width * Vignette::height * Vignette::nb_grayscales);
+ out->write((char *) proba_given_1, sizeof(scalar_t) * Vignette::width * Vignette::height * Vignette::nb_grayscales);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NAIVE_BAYESIAN_CLASSIFIER_H
+#define NAIVE_BAYESIAN_CLASSIFIER_H
+
+#include "classifier.h"
+#include "vignette.h"
+
+class NaiveBayesianClassifier : public Classifier {
+ scalar_t proba_given_0[Vignette::width * Vignette::height * Vignette::nb_grayscales];
+ scalar_t proba_given_1[Vignette::width * Vignette::height * Vignette::nb_grayscales];
+public:
+ NaiveBayesianClassifier();
+ ~NaiveBayesianClassifier();
+ virtual const char *name();
+ virtual void train(int nb_vignettes, Vignette *vignettes, int *labels);
+ virtual scalar_t classify(Vignette *vignette);
+ virtual void read(istream *in);
+ virtual void write(ostream *out);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// All this is clearly non-optimal, loaded with news and deletes and
+// should be rewritten.
+
+#include <string.h>
+
+#include "param_parser.h"
+
+ParamParser::ParamParser() : _nb_max(10),
+ _nb(0),
+ _names(new char *[_nb_max]),
+ _values(new char *[_nb_max]),
+ _changed(new bool[_nb_max]) { }
+
+ParamParser::~ParamParser() {
+ for(int k = 0; k < _nb; k++) {
+ delete[] _names[k];
+ delete[] _values[k];
+ }
+ delete[] _names;
+ delete[] _values;
+ delete[] _changed;
+}
+
+void ParamParser::add_association(const char *variable_name, const char *variable_value, bool change) {
+ int n;
+
+ for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
+
+ if(n < _nb) {
+ delete[] _values[n];
+ _values[n] = new char[strlen(variable_value) + 1];
+ strcpy(_values[n], variable_value);
+ _changed[n] = change;
+ } else {
+ int nm;
+ nm = _nb_max; grow(&nm, _nb, &_names, 2);
+ nm = _nb_max; grow(&nm, _nb, &_values, 2);
+ grow(&_nb_max, _nb, &_changed, 2);
+
+ _names[_nb] = new char[strlen(variable_name) + 1];
+ strcpy(_names[_nb], variable_name);
+ _values[_nb] = new char[strlen(variable_value) + 1];
+ strcpy(_values[_nb], variable_value);
+ _changed[_nb] = change;
+ _nb++;
+ }
+}
+
+char *ParamParser::get_association(const char *variable_name) {
+ int n;
+ for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
+ if(n < _nb) return _values[n];
+ else {
+ cerr << "Unknown parameter \"" << variable_name << "\", existing ones are" << endl;
+ for(int n = 0; n < _nb; n++)
+ cerr << " \"" << _names[n] << "\"" << endl;
+ exit(1);
+ }
+}
+
+int ParamParser::get_association_int(const char *variable_name) {
+ char *u = get_association(variable_name);
+ char *s = u;
+ while(*s)
+ if((*s < '0' || *s > '9') && *s != '-') {
+ cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
+ exit(1);
+ } else s++;
+ return atoi(u);
+}
+
+long int ParamParser::get_association_long_int(const char *variable_name) {
+ char *u = get_association(variable_name);
+ char *s = u;
+ while(*s)
+ if((*s < '0' || *s > '9') && *s != '-') {
+ cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
+ exit(1);
+ } else s++;
+ return atol(u);
+}
+
+scalar_t ParamParser::get_association_scalar(const char *variable_name) {
+ char *u = get_association(variable_name);
+ char *s = u;
+ while(*s)
+ if((*s < '0' || *s > '9') && *s != '.' && *s != 'e' && *s != '-') {
+ cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
+ exit(1);
+ } else s++;
+ return atof(u);
+}
+
+bool ParamParser::get_association_bool(const char *variable_name) {
+ char *value = get_association(variable_name);
+ if(strcasecmp(value, "") == 0 || strcasecmp(value, "y") == 0 || strcasecmp(value, "yes") == 0) return true;
+ if(strcasecmp(value, "n") == 0 || strcasecmp(value, "no") == 0) return false;
+ cerr << "Expects nothing (for yes), or y[es] or n[o] for a boolean argument and got '" << value << "'" << endl;
+ exit(1);
+}
+
+void ParamParser::parse_options(int argc, char **argv,
+ bool allow_undefined,
+ int *new_argc, char **new_argv) {
+
+ int i = 1;
+
+ if(new_argc && new_argv)
+ new_argv[(*new_argc)++] = argv[0];
+
+ while(i < argc) {
+ if(strncmp(argv[i], "--", 2) == 0) {
+ // This is so 70s! I luuuuv it!
+ char variable_name[buffer_size] = "", variable_value[buffer_size] = "";
+ char *o = argv[i] + 2, *s = variable_name, *u = variable_value;
+ while(*o && *o != '=') *s++ = *o++;
+ *s = '\0';
+ if(*o) { o++; while(*o) *u++ = *o++; }
+ *u = '\0';
+ if(!allow_undefined) get_association(variable_name);
+ add_association(variable_name, variable_value, true);
+ } else {
+ if(new_argc && new_argv)
+ new_argv[(*new_argc)++] = argv[i];
+ else {
+ cerr << "Can not parse " << argv[i] << endl;
+ exit(1);
+ }
+ }
+ i++;
+ }
+}
+
+void ParamParser::print_all(ostream *os) {
+ for(int n = 0; n < _nb; n++) {
+ (*os) << (_changed[n] ? " * " : " ") << "\"" << _names[n] << "\" \"" << _values[n] << "\"" << endl;
+ }
+}
+
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+
+ A class to parse the arguments from the command line.
+
+ */
+
+#ifndef PARAM_PARSER_H
+#define PARAM_PARSER_H
+
+#include <iostream>
+#include "misc.h"
+
+using namespace std;
+
+class ParamParser {
+ int _nb_max, _nb;
+ char **_names, **_values;
+ bool *_changed;
+public:
+ ParamParser();
+ ~ParamParser();
+ void add_association(const char *variable_name, const char *variable_value, bool change);
+ char *get_association(const char *variable_name);
+ int get_association_int(const char *variable_name);
+ long int get_association_long_int(const char *variable_name);
+ scalar_t get_association_scalar(const char *variable_name);
+ bool get_association_bool(const char *variable_name);
+
+ void parse_options(int argc, char **argv, bool allow_undefined, int *new_argc, char **new_argv);
+ void print_all(ostream *os);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <time.h>
+#include "progress_bar.h"
+
+ProgressBar::ProgressBar() : _visible(false), _value_max(-1) { }
+
+void ProgressBar::set_visible(bool visible) {
+ _visible = visible;
+}
+
+void ProgressBar::init(ostream *out, scalar_t value_max) {
+ _value_max = value_max;
+ _last_step = -1;
+ time(&_initial_time);
+ refresh(out, 0);
+}
+
+void ProgressBar::refresh(ostream *out, scalar_t value) {
+ if(_visible && _value_max > 0) {
+ int step = int((value * 40) / _value_max);
+
+ if(step > _last_step) {
+ char buffer[width + 1], date_buffer[buffer_size];
+ int i, j;
+ j = sprintf(buffer, "Timer: ");
+
+ for(i = 0; i < step; i++) buffer[j + i] = 'X';
+ for(; i < 40; i++) buffer[j + i] = (i%4 == 0) ? '+' : '-';
+ j += i;
+
+ time_t current_time; time(¤t_time);
+ int rt = int(((current_time - _initial_time)/scalar_t(value)) * scalar_t(_value_max - value));
+
+ if(rt > 0) {
+ if(rt > 3600 * 24) {
+ time_t current;
+ time(¤t);
+ current += rt;
+ strftime(date_buffer, buffer_size, "%a %b %e %H:%M", localtime(¤t));
+ j += snprintf(buffer + j, width - j - 1, " (end ~ %s)", date_buffer);
+ } else {
+ int hours = rt/3600, min = (rt%3600)/60, sec = rt%60;
+ if(hours > 0)
+ j += snprintf(buffer + j, width - j - 1, " (~%dh%dmin left)", hours, min);
+ else if(min > 0)
+ j += snprintf(buffer + j, width - j - 1, " (~%dmin%ds left)", min, sec);
+ else
+ j += snprintf(buffer + j, width - j - 1, " (~%ds left)", sec);
+ }
+ }
+
+ for(; j < width; j++) buffer[j] = ' ';
+ buffer[j] = '\0';
+ (*out) << buffer << "\r";
+ out->flush();
+ _last_step = step;
+ }
+ }
+}
+
+void ProgressBar::finish(ostream *out) {
+ if(_visible) {
+ char buffer[width + 1];
+ int j;
+ time_t current_time; time(¤t_time);
+ int rt = int(current_time - _initial_time);
+ int min = rt/60, sec = rt%60;
+ j = sprintf(buffer, "Timer: Total %dmin%ds", min, sec);
+ for(; j < width; j++) buffer[j] = ' ';
+ buffer[j] = '\0';
+ (*out) << buffer << endl;
+ out->flush();
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+
+ This class displays a progress bar in text mode and computes a rough
+ estimate of the remaining processing time.
+
+*/
+
+#ifndef PROGRESS_BAR_H
+#define PROGRESS_BAR_H
+
+#include <iostream>
+
+using namespace std;
+
+#include "misc.h"
+
+class ProgressBar {
+ const static int width = 80;
+ bool _visible;
+ scalar_t _value_max, _last_step;
+ time_t _initial_time;
+public:
+ ProgressBar();
+ void set_visible(bool visible);
+ void init(ostream *out, scalar_t value_max);
+ void refresh(ostream *out, scalar_t value);
+ void finish(ostream *out);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <iostream>
+#include <stdio.h>
+
+#include <libpng/png.h>
+#include "jpeg_misc.h"
+
+#include "rgb_image.h"
+
+void RGBImage::allocate() {
+ _bit_plans = new unsigned char **[RGB_DEPTH];
+ _bit_lines = new unsigned char *[RGB_DEPTH * _height];
+ _bit_map = new unsigned char [_width * _height * RGB_DEPTH];
+ for(int k = 0; k < RGB_DEPTH; k++) _bit_plans[k] = _bit_lines + k * _height;
+ for(int k = 0; k < RGB_DEPTH * _height; k++) _bit_lines[k] = _bit_map + k * _width;
+}
+
+void RGBImage::deallocate() {
+ delete[] _bit_plans;
+ delete[] _bit_lines;
+ delete[] _bit_map;
+}
+
+RGBImage::RGBImage() : _bit_plans(0), _bit_lines(0), _bit_map(0) { }
+
+RGBImage::RGBImage(int width, int height) : _width(width), _height(height) {
+ allocate();
+ memset(_bit_map, 0, _width * _height * RGB_DEPTH * sizeof(unsigned char));
+}
+
+RGBImage::RGBImage(RGBImage *image, scalar_t scale) {
+ _width = int(scale * image->_width);
+ _height = int(scale * image->_height);
+
+ allocate();
+
+ for(int y = 0; y < _height; y++) {
+ for(int x = 0; x < _width; x++) {
+
+ const int delta = 10;
+ int sr = 0, sg = 0, sb = 0, t = 0;
+ int xo, yo;
+
+ for(int yy = y * delta; yy < (y + 1) * delta; yy++) {
+ for(int xx = x * delta; xx < (x + 1) * delta; xx++) {
+ xo = (image->_width * xx)/(_width * delta);
+ yo = (image->_height * yy)/(_height * delta);
+ if(xo >= 0 && xo < image->_width && yo >= 0 && yo < image->_height) {
+ sr += image->_bit_plans[RED][yo][xo];
+ sg += image->_bit_plans[GREEN][yo][xo];
+ sb += image->_bit_plans[BLUE][yo][xo];
+ t++;
+ }
+ }
+ }
+
+ if(t > 0) {
+ _bit_plans[RED][y][x] = sr / t;
+ _bit_plans[GREEN][y][x] = sg / t;
+ _bit_plans[BLUE][y][x] = sb / t;
+ } else {
+ _bit_plans[RED][y][x] = 0;
+ _bit_plans[GREEN][y][x] = 0;
+ _bit_plans[BLUE][y][x] = 0;
+ }
+
+ }
+ }
+}
+
+RGBImage::~RGBImage() {
+ deallocate();
+}
+
+void RGBImage::read_png(const char *name) {
+ // This is the number of bytes the read_png routine will read to
+ // decide if the file is a PNG or not. According to the png
+ // documentation, it can be 1 to 8 bytes, 8 being the max and the
+ // best.
+
+ const int header_size = 8;
+
+ png_byte header[header_size];
+ png_bytep *row_pointers;
+
+ deallocate();
+
+ // open file
+ FILE *fp = fopen(name, "rb");
+ if (!fp) {
+ cerr << "Unable to open file " << name << " for reading.\n";
+ exit(1);
+ }
+
+ // read header
+ fread(header, 1, header_size, fp);
+ if (png_sig_cmp(header, 0, header_size)) {
+ cerr << "File " << name << " does not look like PNG.\n";
+ fclose(fp);
+ exit(1);
+ }
+
+ // create png pointer
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ if (!png_ptr) {
+ cerr << "png_create_read_struct failed\n";
+ fclose(fp);
+ exit(1);
+ }
+
+ // create png info struct
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) 0, (png_infopp) 0);
+ cerr << "png_create_info_struct failed\n";
+ fclose(fp);
+ exit(1);
+ }
+
+ // get image info
+ png_init_io(png_ptr, fp);
+ png_set_sig_bytes(png_ptr, header_size);
+ png_read_info(png_ptr, info_ptr);
+
+ _width = info_ptr->width;
+ _height = info_ptr->height;
+
+ png_byte bit_depth, color_type, channels;
+ color_type = info_ptr->color_type;
+ bit_depth = info_ptr->bit_depth;
+ channels = info_ptr->channels;
+
+ if(bit_depth != 8) {
+ cerr << "Can only read 8-bits PNG images." << endl;
+ exit(1);
+ }
+
+ // allocate image pointer
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * _height);
+ for (int y = 0; y < _height; y++)
+ row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
+
+ allocate();
+
+ // read image
+ png_read_image(png_ptr, row_pointers);
+
+ // send image to red, green and blue buffers
+ switch (color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ {
+ unsigned char pixel = 0;
+ for (int y = 0; y < _height; y++) for (int x = 0; x < _width; x++) {
+ pixel = row_pointers[y][x];
+ _bit_plans[RED][y][x] = pixel;
+ _bit_plans[GREEN][y][x] = pixel;
+ _bit_plans[BLUE][y][x] = pixel;
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ cerr << "PNG type GRAY_ALPHA not supported.\n";
+ exit(1);
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ cerr << "PNG type PALETTE not supported.\n";
+ exit(1);
+ break;
+
+ case PNG_COLOR_TYPE_RGB:
+ {
+ if(channels != RGB_DEPTH) {
+ cerr << "Unsupported number of channels for RGB type\n";
+ break;
+ }
+ int k;
+ for (int y = 0; y < _height; y++) {
+ k = 0;
+ for (int x = 0; x < _width; x++) {
+ _bit_plans[RED][y][x] = row_pointers[y][k++];
+ _bit_plans[GREEN][y][x] = row_pointers[y][k++];
+ _bit_plans[BLUE][y][x] = row_pointers[y][k++];
+ }
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ cerr << "PNG type RGB_ALPHA not supported.\n";
+ exit(1);
+ break;
+
+ default:
+ cerr << "Unknown PNG type\n";
+ exit(1);
+ }
+
+ // release memory
+ png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+
+ for (int y = 0; y < _height; y++) free(row_pointers[y]);
+ free(row_pointers);
+
+ fclose(fp);
+}
+
+void RGBImage::write_png(const char *name) {
+ png_bytep *row_pointers;
+
+ // create file
+ FILE *fp = fopen(name, "wb");
+
+ if (!fp) {
+ cerr << "Unable to create image '" << name << "'\n";
+ exit(1);
+ }
+
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+
+ if (!png_ptr) {
+ cerr << "png_create_write_struct failed\n";
+ fclose(fp);
+ exit(1);
+ }
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ cerr << "png_create_info_struct failed\n";
+ fclose(fp);
+ exit(1);
+ }
+
+ png_init_io(png_ptr, fp);
+
+ png_set_IHDR(png_ptr, info_ptr, _width, _height,
+ 8, 2, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+
+ // allocate memory
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * _height);
+ for (int y = 0; y < _height; y++)
+ row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
+
+ int k;
+ for (int y = 0; y < _height; y++) {
+ k = 0;
+ for (int x = 0; x < _width; x++) {
+ row_pointers[y][k++] = _bit_map[x + _width * (y + _height * RED)];
+ row_pointers[y][k++] = _bit_map[x + _width * (y + _height * GREEN)];
+ row_pointers[y][k++] = _bit_map[x + _width * (y + _height * BLUE)];
+ }
+ }
+
+ png_write_image(png_ptr, row_pointers);
+ png_write_end(png_ptr, 0);
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ // cleanup heap allocation
+ for (int y = 0; y < _height; y++) free(row_pointers[y]);
+ free(row_pointers);
+
+ fclose(fp);
+}
+
+void RGBImage::write_jpg(const char *filename, int quality) {
+ struct jpeg_compress_struct cinfo;
+ struct my_error_mgr jerr;
+ FILE *outfile; /* target file */
+ JSAMPARRAY buffer; /* Output row buffer */
+
+ jpeg_create_compress (&cinfo);
+
+ if ((outfile = fopen (filename, "wb")) == 0) {
+ fprintf (stderr, "Can't open %s\n", filename);
+ exit(1);
+ }
+
+ cinfo.err = jpeg_std_error (&jerr.pub);
+ jerr.pub.error_exit = my_error_exit;
+
+ if (setjmp (jerr.setjmp_buffer)) {
+ jpeg_destroy_compress (&cinfo);
+ fclose (outfile);
+ exit(1);
+ }
+
+ jpeg_stdio_dest (&cinfo, outfile);
+
+ cinfo.image_width = _width;
+ cinfo.image_height = _height;
+ cinfo.input_components = RGB_DEPTH;
+
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults (&cinfo);
+ jpeg_set_quality (&cinfo, quality, TRUE);
+ jpeg_start_compress (&cinfo, TRUE);
+ int y = 0;
+ buffer =
+ (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE,
+ _width * RGB_DEPTH, 1);
+ while (int(cinfo.next_scanline) < _height) {
+ for(int d = 0; d < RGB_DEPTH; d++)
+ for(int x = 0; x < _width; x++)
+ buffer[0][x * RGB_DEPTH + d] =
+ (JSAMPLE) ((_bit_map[x + _width * (y + _height * d)] * (MAXJSAMPLE + 1)) / 255);
+ jpeg_write_scanlines (&cinfo, buffer, 1);
+ y++;
+ }
+
+ jpeg_finish_compress (&cinfo);
+ fclose (outfile);
+
+ jpeg_destroy_compress (&cinfo);
+}
+
+void RGBImage::read_jpg(const char *filename) {
+ struct jpeg_decompress_struct cinfo;
+ struct my_error_mgr jerr;
+ FILE *infile;
+ JSAMPARRAY buffer;
+
+ deallocate();
+
+ if ((infile = fopen (filename, "rb")) == 0) {
+ fprintf (stderr, "can't open %s\n", filename);
+ return;
+ }
+
+ cinfo.err = jpeg_std_error (&jerr.pub);
+ jerr.pub.error_exit = my_error_exit;
+
+ if (setjmp (jerr.setjmp_buffer)) {
+ jpeg_destroy_decompress (&cinfo);
+ fclose (infile);
+ delete[] _bit_map;
+ _width = 0;
+ _height = 0;
+ _bit_map = 0;
+ return;
+ }
+
+ jpeg_create_decompress (&cinfo);
+ jpeg_stdio_src (&cinfo, infile);
+ jpeg_read_header (&cinfo, TRUE);
+ jpeg_start_decompress (&cinfo);
+
+ _width = cinfo.output_width;
+ _height = cinfo.output_height;
+ int depth = cinfo.output_components;
+
+ allocate();
+
+ buffer =
+ (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE,
+ _width * depth, 1);
+
+ int y = 0;
+ while (cinfo.output_scanline < cinfo.output_height) {
+ jpeg_read_scanlines (&cinfo, buffer, 1);
+ if(depth == 1) {
+ for(int d = 0; d < RGB_DEPTH; d++)
+ for(int x = 0; x < _width; x++)
+ _bit_plans[d][y][x] =
+ (unsigned char) ((buffer[0][x * depth] * 255) / (MAXJSAMPLE + 1));
+ } else {
+ for(int d = 0; d < depth; d++)
+ for(int x = 0; x < _width; x++)
+ _bit_plans[d][y][x] =
+ (unsigned char) ((buffer[0][x * depth + d] * 255) / (MAXJSAMPLE + 1));
+ }
+ y++;
+ }
+
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+
+ fclose (infile);
+}
+
+void RGBImage::draw_line(int thickness,
+ unsigned char r, unsigned char g, unsigned char b,
+ scalar_t x0, scalar_t y0, scalar_t x1, scalar_t y1) {
+ int l = 0;
+ int dx, dy, h, v;
+ int ix0 = int(x0 + 0.5), iy0 = int(y0 + 0.5), ix1 = int(x1 + 0.5), iy1 = int(y1 + 0.5);
+
+ if(ix0 < ix1) { dx = 1; h = ix1 - ix0; } else { dx = -1; h = ix0 - ix1; }
+ if(iy0 < iy1) { dy = 1; v = iy1 - iy0; } else { dy = -1; v = iy0 - iy1; }
+
+ int x = ix0, y = iy0;
+
+ if(h > v) {
+ for(int i = 0; i < h + 1; i++) {
+ for(int ex = - thickness / 2 - 1; ex < (thickness + 1) / 2 + 1; ex++) {
+ for(int ey = - thickness / 2 - 1; ey < (thickness + 1) / 2 + 1; ey++) {
+ if(ex * ex + ey * ey <= thickness * thickness / 4) {
+ int xx = x + ex, yy = y + ey;
+ if(xx >= 0 && xx < _width && yy >= 0 && yy < _height)
+ set_pixel(xx, yy, r, g, b);
+ }
+ }
+ }
+
+ x += dx; l += v;
+ if(l > 0) { y += dy; l -= h; }
+ }
+
+ } else {
+
+ for(int i = 0; i < v + 1; i++) {
+ for(int ex = - thickness / 2 - 1; ex < (thickness + 1) / 2 + 1; ex++) {
+ for(int ey = - thickness / 2 - 1; ey < (thickness + 1) / 2 + 1; ey++) {
+ if(ex * ex + ey * ey <= thickness * thickness / 4) {
+ int xx = x + ex, yy = y + ey;
+ if(xx >= 0 && xx < _width && yy >= 0 && yy < _height)
+ set_pixel(xx, yy, r, g, b);
+ }
+ }
+ }
+
+ y += dy; l -= h;
+ if(l < 0) { x += dx; l += v; }
+ }
+
+ }
+
+}
+
+void RGBImage::draw_ellipse(int thickness,
+ unsigned char r, unsigned char g, unsigned char b,
+ scalar_t xc, scalar_t yc, scalar_t radius_1, scalar_t radius_2, scalar_t tilt) {
+ scalar_t ux1 = cos(tilt) * radius_1, uy1 = sin(tilt) * radius_1;
+ scalar_t ux2 = - sin(tilt) * radius_2, uy2 = cos(tilt) * radius_2;
+
+ const int nb_points_to_draw = 80;
+ scalar_t x, y, px = 0, py = 0;
+
+ for(int i = 0; i <= nb_points_to_draw; i++) {
+ scalar_t alpha = (M_PI * 2 * scalar_t(i)) / scalar_t(nb_points_to_draw);
+
+ x = xc + cos(alpha) * ux1 + sin(alpha) * ux2;
+ y = yc + cos(alpha) * uy1 + sin(alpha) * uy2;
+
+ if(i > 0) {
+ draw_line(thickness, r, g, b, px, py, x, y);
+ }
+
+ px = x; py = y;
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+
+ A simple image class to either load color images, or produce
+ materials.
+
+ */
+
+#ifndef RGB_IMAGE_H
+#define RGB_IMAGE_H
+
+#include "misc.h"
+
+class RGBImage {
+protected:
+ int _width, _height;
+ unsigned char ***_bit_plans, **_bit_lines, *_bit_map;
+ static const int RED = 0;
+ static const int GREEN = 1;
+ static const int BLUE = 2;
+ static const int RGB_DEPTH = 3;
+
+ void allocate();
+ void deallocate();
+
+public:
+
+ RGBImage();
+ RGBImage(int width, int height);
+ RGBImage(RGBImage *image, scalar_t scale);
+ virtual ~RGBImage();
+
+ inline int width() const { return _width; }
+ inline int height() const { return _height; }
+
+ inline void set_pixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) {
+ ASSERT(x >= 0 && x < _width && y >= 0 && y < _height);
+ _bit_plans[RED][y][x] = r;
+ _bit_plans[GREEN][y][x] = g;
+ _bit_plans[BLUE][y][x] = b;
+ }
+
+ inline unsigned char pixel(int x, int y, int d) {
+ ASSERT(x >= 0 && x < _width && y >= 0 && y < _height && d >= 0 && d < RGB_DEPTH);
+ return _bit_plans[d][y][x];
+ }
+
+ virtual void read_png(const char *filename);
+ virtual void write_png(const char *filename);
+
+ virtual void read_jpg(const char *filename);
+ virtual void write_jpg(const char *filename, int quality);
+
+ virtual void draw_line(int thickness,
+ unsigned char r, unsigned char g, unsigned char b,
+ scalar_t x0, scalar_t y0, scalar_t x1, scalar_t y1);
+
+ virtual void draw_ellipse(int thickness,
+ unsigned char r, unsigned char g, unsigned char b,
+ scalar_t xc, scalar_t yc, scalar_t radius_1, scalar_t radius_2, scalar_t tilt);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "shape.h"
+
+int Shape::generate_part_part(scalar_t *xp, scalar_t *yp, int *nb_pixels,
+ scalar_t radius, scalar_t hole_radius,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2) {
+ if(abs(x1 - x2) > gap_max || abs(y1 - y2) > gap_max) {
+
+ scalar_t d = sqrt(scalar_t(sq(x1 - x2) + sq(y1 - y2)))/5;
+ scalar_t x3, y3, dx, dy;
+
+ do {
+ // Isotropic jump
+ do {
+ dx = (2 * drand48() - 1) * d;
+ dy = (2 * drand48() - 1) * d;
+ } while(sq(dx) + sq(dy) > sq(d));
+ x3 = (x1 + x2) / 2 + dx;
+ y3 = (y1 + y2) / 2 + dy;
+ } while(sq(x3) + sq(y3) > sq(radius));
+
+ if(generate_part_part(xp, yp, nb_pixels,
+ radius, hole_radius, x1, y1, x3, y3)) {
+ return 1;
+ }
+
+ if(generate_part_part(xp, yp, nb_pixels,
+ radius, hole_radius, x3, y3, x2, y2)) {
+ return 1;
+ }
+
+ } else {
+
+ if(sq(x1) + sq(y1) >= sq(radius) || sq(x1) + sq(y1) < sq(hole_radius)) {
+ return 1;
+ }
+
+ xp[*nb_pixels] = x1;
+ yp[*nb_pixels] = y1;
+ (*nb_pixels)++;
+
+ }
+
+ return 0;
+}
+
+void Shape::generate_part(scalar_t *xp, scalar_t *yp, int *nb_pixels,
+ scalar_t radius, scalar_t hole_radius) {
+ scalar_t x1, y1, x2, y2, x3, y3, x4, y4;
+ int err1, err2, err3, err4;
+
+ do {
+ *nb_pixels = 0;
+
+ do {
+ x1 = drand48() * radius;
+ y1 = drand48() * radius;
+ } while(sq(x1) + sq(y1) > sq(radius) || sq(x1) + sq(y1) < sq(hole_radius));
+
+ do {
+ x2 = -drand48() * radius;
+ y2 = drand48() * radius;
+ } while(sq(x2) + sq(y2) > sq(radius) || sq(x2) + sq(y2) < sq(hole_radius));
+
+ do {
+ x3 = -drand48() * radius;
+ y3 = -drand48() * radius;
+ } while(sq(x3) + sq(y3) > sq(radius) || sq(x3) + sq(y3) < sq(hole_radius));
+
+ do {
+ x4 = drand48() * radius;
+ y4 = -drand48() * radius;
+ } while(sq(x4) + sq(y4) > sq(radius) || sq(x4) + sq(y4) < sq(hole_radius));
+
+ n_pixels1 = *nb_pixels;
+ err1 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x1, y1, x2, y2);
+ n_pixels2 = *nb_pixels;
+ err2 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x2, y2, x3, y3);
+ n_pixels3 = *nb_pixels;
+ err3 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x3, y3, x4, y4);
+ n_pixels4 = *nb_pixels;
+ err4 = generate_part_part(xp, yp, nb_pixels, radius, hole_radius, x4, y4, x1, y1);
+
+ } while(err1 || err2 || err3 || err4);
+}
+
+Shape::Shape() {
+ nb_pixels = 0;
+ x_pixels = 0;
+ y_pixels = 0;
+}
+
+Shape::~Shape() {
+ delete[] x_pixels;
+ delete[] y_pixels;
+}
+
+void Shape::randomize(scalar_t radius, scalar_t hole_radius) {
+ delete[] x_pixels;
+ delete[] y_pixels;
+ nb_pixels = 0;
+ scalar_t tmp_x_pixels[nb_max_pixels], tmp_y_pixels[nb_max_pixels];
+ generate_part(tmp_x_pixels, tmp_y_pixels, &nb_pixels, radius, hole_radius);
+ x_pixels = new scalar_t[nb_pixels];
+ y_pixels = new scalar_t[nb_pixels];
+ for(int p = 0; p < nb_pixels; p++) {
+ x_pixels[p] = tmp_x_pixels[p];
+ y_pixels[p] = tmp_y_pixels[p];
+ }
+
+ rotate(drand48() * M_PI * 2);
+
+ // { // ******************************* START ***************************
+// #warning Test code added on 2009 Sep 09 18:15:25
+ // for(int p = 0; p < nb_pixels; p++) {
+ // cout << x_pixels[p] << " " << y_pixels[p] << endl;
+ // }
+ // } // ******************************** END ****************************
+
+}
+
+void Shape::copy(Shape *shape) {
+ delete[] x_pixels;
+ delete[] y_pixels;
+ nb_pixels = shape->nb_pixels;
+ n_pixels1 = shape->n_pixels1;
+ n_pixels2 = shape->n_pixels2;
+ n_pixels3 = shape->n_pixels3;
+ n_pixels4 = shape->n_pixels4;
+ x_pixels = new scalar_t[nb_pixels];
+ y_pixels = new scalar_t[nb_pixels];
+ for(int p = 0; p < nb_pixels; p++) {
+ x_pixels[p] = shape->x_pixels[p];
+ y_pixels[p] = shape->y_pixels[p];
+ }
+}
+
+void Shape::scale(scalar_t s) {
+ for(int p = 0; p < nb_pixels; p++) {
+ x_pixels[p] *= s;
+ y_pixels[p] *= s;
+ }
+}
+
+void Shape::rotate(scalar_t alpha) {
+ scalar_t ux = cos(alpha), uy = -sin(alpha);
+ scalar_t vx = sin(alpha), vy = cos(alpha);
+ scalar_t x, y;
+ for(int p = 0; p < nb_pixels; p++) {
+ x = x_pixels[p] * ux + y_pixels[p] * uy;
+ y = x_pixels[p] * vx + y_pixels[p] * vy;
+ x_pixels[p] = x;
+ y_pixels[p] = y;
+ }
+}
+
+void Shape::symmetrize(scalar_t axis_x, scalar_t axis_y) {
+ scalar_t sql = sq(axis_x) + sq(axis_y);
+ scalar_t u, v;
+ for(int p = 0; p < nb_pixels; p++) {
+ u = x_pixels[p] * axis_y - y_pixels[p] * axis_x;
+ v = x_pixels[p] * axis_x + y_pixels[p] * axis_y;
+ u = - u;
+ x_pixels[p] = ( u * axis_y + v * axis_x) / sql;
+ y_pixels[p] = (- u * axis_x + v * axis_y) / sql;
+ }
+}
+
+
+int Shape::overwrites(Vignette *vignette, scalar_t xc, scalar_t yc, int n1, int n2) {
+ int x1 = int(x_pixels[n1 % nb_pixels] + xc);
+ int y1 = int(y_pixels[n1 % nb_pixels] + yc);
+ int x2 = int(x_pixels[n2 % nb_pixels] + xc);
+ int y2 = int(y_pixels[n2 % nb_pixels] + yc);
+ int n3 = (n1 + n2) / 2;
+
+ if(n1 + 1 < n2 && (abs(x1 - x2) > 1 || abs(y1 - y2) > 1)) {
+ return
+ overwrites(vignette, xc, yc, n1, n3) ||
+ overwrites(vignette, xc, yc, n3, n2);
+ } else {
+
+ if(x1 >= margin && x1 < Vignette::width - margin &&
+ y1 >= margin && y1 < Vignette::height - margin) {
+
+ if(margin > 0) {
+ for(int xx = x1 - margin; xx <= x1 + margin; xx++) {
+ for(int yy = y1 - margin; yy <= y1 + margin; yy++) {
+ if(vignette->content[xx + Vignette::width * yy] != 255) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+}
+
+int Shape::overwrites(Vignette *vignette, scalar_t xc, scalar_t yc) {
+ return
+ overwrites(vignette, xc, yc, n_pixels1, n_pixels2) ||
+ overwrites(vignette, xc, yc, n_pixels2, n_pixels3) ||
+ overwrites(vignette, xc, yc, n_pixels3, n_pixels4) ||
+ overwrites(vignette, xc, yc, n_pixels4, nb_pixels);
+}
+
+void Shape::draw(Vignette *vignette, scalar_t xc, scalar_t yc, int n1, int n2) {
+ int x1 = int(x_pixels[n1 % nb_pixels] + xc);
+ int y1 = int(y_pixels[n1 % nb_pixels] + yc);
+ int x2 = int(x_pixels[n2 % nb_pixels] + xc);
+ int y2 = int(y_pixels[n2 % nb_pixels] + yc);
+ int n3 = (n1 + n2) / 2;
+
+ if(n1 + 1 < n2 && (abs(x1 - x2) > 1 || abs(y1 - y2) > 1)) {
+ draw(vignette, xc, yc, n1, n3);
+ draw(vignette, xc, yc, n3, n2);
+ } else {
+ if(x1 >= margin && x1 < Vignette::width-margin &&
+ y1 >= margin && y1 < Vignette::height-margin) {
+ vignette->content[x1 + Vignette::width * y1] = 0;
+ }
+ }
+}
+
+void Shape::draw(Vignette *vignette, scalar_t xc, scalar_t yc) {
+ draw(vignette, xc, yc, n_pixels1, n_pixels2);
+ draw(vignette, xc, yc, n_pixels2, n_pixels3);
+ draw(vignette, xc, yc, n_pixels3, n_pixels4);
+ draw(vignette, xc, yc, n_pixels4, nb_pixels);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SHAPE_H
+#define SHAPE_H
+
+#include "misc.h"
+#include "vignette.h"
+
+class Shape {
+ static const int margin = 1;
+ static const int nb_max_pixels = Vignette::width * Vignette::height;
+ static const scalar_t gap_max = 0.25;
+ int n_pixels1, n_pixels2, n_pixels3, n_pixels4;
+ int nb_pixels;
+ scalar_t xc, yc;
+ scalar_t *x_pixels;
+ scalar_t *y_pixels;
+
+ int generate_part_part(scalar_t *xp, scalar_t *yp, int *nb_pixels, scalar_t radius, scalar_t hole_radius,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2);
+ void generate_part(scalar_t *xp, scalar_t *yp, int *nb_pixels, scalar_t radius, scalar_t hole_radius);
+ int overwrites(Vignette *vignette, scalar_t xc, scalar_t yc, int first, int nb);
+ void draw(Vignette *vignette, scalar_t xc, scalar_t yc, int first, int nb);
+
+public:
+ Shape();
+ ~Shape();
+
+ void randomize(scalar_t radius, scalar_t hole_radius);
+ void copy(Shape *shape);
+ void scale(scalar_t s);
+ void rotate(scalar_t alpha);
+ void symmetrize(scalar_t axis_x, scalar_t axis_y);
+
+ int overwrites(Vignette *vignette, scalar_t xc, scalar_t yc);
+ void draw(Vignette *vignette, scalar_t xc, scalar_t yc);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "stump.h"
+
+void compute_integral_image(Vignette *vignette, int *integral_image) {
+ int k = 0;
+ for(int y = 0; y <= Vignette::height; y++) {
+ for(int x = 0; x <= Vignette::width; x++) {
+ if(x == 0 || y == 0) {
+ integral_image[k] = 0;
+ } else {
+ ASSERT(k >= (Vignette::width + 1) + 1);
+ integral_image[k] = vignette->content[x - 1 + Vignette::width * (y - 1)]
+ + integral_image[k - (Vignette::width + 1)]
+ + integral_image[k - 1]
+ - integral_image[k - (Vignette::width + 1) - 1];
+ }
+ k++;
+ }
+ }
+}
+
+
+void Stump::randomize() {
+ do {
+ roi_x = int(drand48() * Vignette::width);
+ roi_y = int(drand48() * Vignette::height);
+ roi_w = int(drand48() * Vignette::width);
+ roi_h = int(drand48() * Vignette::height);
+ // #warning *!*!*!*!*!*!*!*!*!*!*!*!*!*
+ // roi_w = int(drand48() * Vignette::width/2);
+ // roi_h = int(drand48() * Vignette::height/2);
+ } while(roi_x + roi_w > Vignette::width || roi_y + roi_h > Vignette::height);
+
+ k1 = (roi_x + 0) + (roi_y + 0) * (Vignette::width + 1);
+ k2 = (roi_x + roi_w) + (roi_y + 0) * (Vignette::width + 1);
+ k3 = (roi_x + 0) + (roi_y + roi_h) * (Vignette::width + 1);
+ k4 = (roi_x + roi_w) + (roi_y + roi_h) * (Vignette::width + 1);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef STUMP_H
+#define STUMP_H
+
+#include "misc.h"
+#include "vignette.h"
+
+void compute_integral_image(Vignette *vignette, int *integral_mage);
+
+class Stump {
+public:
+ int roi_x, roi_y, roi_w, roi_h;
+ int k1, k2, k3, k4;
+ scalar_t threshold;
+ scalar_t weight0, weight1;
+
+ inline scalar_t count(int *iimage) {
+ return scalar_t(iimage[k1] + iimage[k4] - iimage[k2] - iimage[k3]);
+ }
+
+ inline scalar_t response(int *iimage) {
+ if(count(iimage) >= threshold) {
+ return weight1;
+ } else {
+ return weight0;
+ }
+ }
+
+ void randomize();
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "misc.h"
+#include "tools.h"
+#include "fusion_sort.h"
+
+scalar_t robust_sampling(int nb, scalar_t *weights, int nb_to_sample, int *sampled) {
+ ASSERT(nb > 0);
+ if(nb == 1) {
+ for(int k = 0; k < nb_to_sample; k++) sampled[k] = 0;
+ return weights[0];
+ } else {
+ scalar_t *pair_weights = new scalar_t[(nb+1)/2];
+ for(int k = 0; k < nb/2; k++)
+ pair_weights[k] = weights[2 * k] + weights[2 * k + 1];
+ if(nb%2)
+ pair_weights[(nb+1)/2 - 1] = weights[nb-1];
+ scalar_t result = robust_sampling((nb+1)/2, pair_weights, nb_to_sample, sampled);
+ for(int k = 0; k < nb_to_sample; k++) {
+ int s = sampled[k];
+ // There is a bit of a trick for the isolated sample in the odd
+ // case. Since the corresponding pair weight is the same as the
+ // one sample alone, the test is always true and the isolated
+ // sample will be taken for sure.
+ if(drand48() * pair_weights[s] <= weights[2 * s])
+ sampled[k] = 2 * s;
+ else
+ sampled[k] = 2 * s + 1;
+ }
+ delete[] pair_weights;
+ return result;
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TOOLS_H
+#define TOOLS_H
+
+#include <iostream>
+#include "misc.h"
+
+// This function is not trivial because it has to handle numerical
+// pitfalls due to the very large number of samples.
+
+scalar_t robust_sampling(int nb, scalar_t *weights, int nb_to_sample, int *sampled);
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vignette.h"
+#include "rgb_image.h"
+
+void Vignette::clear() {
+ for(int k = 0; k < width * height; k++) {
+ content[k] = 255;
+ }
+}
+
+void Vignette::write_png(const char *name, int delta) {
+ RGBImage result(width * delta - (delta > 1 ? 1 : 0), height * delta - (delta > 1 ? 1 : 0));
+ for(int y = 0; y < result.height(); y++) {
+ for(int x = 0; x < result.width(); x++) {
+ int c;
+ if(delta > 4 && (x%delta == 0 || y%delta == 0)) {
+ c = 255;
+ } else {
+ c = content[(x / delta) + width * (y / delta)];
+ }
+ result.set_pixel(x, y, c, c, c);
+ }
+ }
+
+ result.write_png(name);
+}
+
+void Vignette::fill(int x, int y, int v) {
+ if(x >= 0 && x < Vignette::width && y >= 0 && y < Vignette::height &&
+ content[x + Vignette::width * y] == 255) {
+ content[x + Vignette::width * y] = v;
+ fill(x + 1, y , v);
+ fill(x - 1, y , v);
+ fill(x , y + 1, v);
+ fill(x , y - 1, v);
+ }
+}
+
+void Vignette::switch_values(int v1, int v2) {
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ if(content[k] == v1) {
+ content[k] = v2;
+ } else if(content[k] == v2) {
+ content[k] = v1;
+ }
+ }
+}
+
+void Vignette::replace_value(int from, int to) {
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ if(content[k] == from) {
+ content[k] = to;
+ }
+ }
+}
+
+void Vignette::superpose(Vignette *infront, Vignette *inback) {
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ if(infront->content[k] < 255) {
+ content[k] = infront->content[k];
+ } else {
+ content[k] = inback->content[k];
+ }
+ }
+}
+
+int Vignette::surface() {
+ int n = 0;
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ if(content[k] < 255) {
+ n++;
+ }
+ }
+ return n;
+}
+
+int Vignette::intersection(Vignette *v) {
+ int n = 0;
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ if(content[k] < 255 && v->content[k] < 255) {
+ n++;
+ }
+ }
+ return n;
+}
+
+void Vignette::grow() {
+ int tmp[Vignette::width * Vignette::height];
+ for(int k = 0; k < Vignette::height * Vignette::width; k++) {
+ tmp[k] = content[k];
+ }
+ int k;
+ for(int y = 1; y < Vignette::height - 1; y++) {
+ for(int x = 1; x < Vignette::width - 1; x++) {
+ k = x + Vignette::width * y;
+ content[k] = min(tmp[k],
+ min(min(tmp[k - Vignette::width], tmp[k - 1]),
+ min(tmp[k + 1], tmp[k + Vignette::width])));
+ }
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VIGNETTE_H
+#define VIGNETTE_H
+
+#include "misc.h"
+#include "global.h"
+
+class Vignette {
+public:
+ static const int width = 128;
+ static const int height = width;
+ static const int nb_grayscales = 256;
+
+ // static const int small_part_size = 24;
+ // static const int small_part_hole_size = 2;
+ // static const int big_part_size = 64;
+ // static const int big_part_hole_size = 32;
+
+ int content[width * height];
+
+ void clear();
+
+ void write_png(const char *name, int delta);
+
+ void fill(int x, int y, int v);
+ void switch_values(int c1, int c2);
+ void replace_value(int from, int to);
+ void superpose(Vignette *infront, Vignette *inback);
+ int surface();
+ int intersection(Vignette *v);
+ void grow();
+
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vignette_generator.h"
+
+VignetteGenerator::~VignetteGenerator() { }
+
+void VignetteGenerator::precompute() { }
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VIGNETTE_GENERATOR_H
+#define VIGNETTE_GENERATOR_H
+
+#include "misc.h"
+#include "global.h"
+#include "vignette.h"
+#include "rgb_image.h"
+
+class VignetteGenerator {
+public:
+ // We need a virtual destructor since we have virtual methods
+ virtual ~VignetteGenerator();
+
+ // Some generators need to do pre-computations that can not be put
+ // in the constructor
+ virtual void precompute();
+
+ // Generate a vignette
+ virtual void generate(int label, Vignette *vignette) = 0;
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_1.h"
+#include "shape.h"
+
+VisionProblem_1::VisionProblem_1() { }
+
+void VisionProblem_1::generate(int label, Vignette *vignette) {
+ int nb_shapes = 2;
+ int xs[nb_shapes], ys[nb_shapes];
+ scalar_t scales[nb_shapes], angles[nb_shapes];
+ Shape shapes[nb_shapes];
+
+ int error;
+ do {
+
+ scalar_t max_scale = -1;
+
+ for(int n = 0; n < nb_shapes; n++) {
+ xs[n] = int(drand48() * Vignette::width);
+ ys[n] = int(drand48() * Vignette::height);
+
+ scales[n] = 2.5;
+
+ if(n == 0 || scales[n] > max_scale) max_scale = scales[n];
+
+ angles[n] = 0;
+ }
+
+ for(int n = 0; n < nb_shapes; n++) {
+ if(n == 0 || label == 0) {
+ shapes[n].randomize(max_scale * part_size / 2, max_scale * hole_size/2);
+ } else {
+ shapes[n].copy(&shapes[0]);
+ }
+ }
+
+ for(int n = 0; n < nb_shapes; n++) {
+ shapes[n].scale(scales[n] / max_scale);
+ shapes[n].rotate(angles[n]);
+ }
+
+ vignette->clear();
+
+ error = 0;
+ for(int n = 0; n < nb_shapes; n++) {
+ error |= shapes[n].overwrites(vignette, xs[n], ys[n]);
+ shapes[n].draw(vignette, xs[n], ys[n]);
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_1_H
+#define VISION_PROBLEM_1_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_1 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_1();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_11.h"
+#include "shape.h"
+
+VisionProblem_11::VisionProblem_11() { }
+
+void VisionProblem_11::generate(int label, Vignette *vignette) {
+ int nb_shapes;
+ int xs, ys, i, pxs, pys;
+ const int dist_min = Vignette::width/12;
+ int nb_attempts, max_nb_attempts = 100;
+
+ Vignette mask, tmp;
+
+ nb_shapes = 2;
+
+ do {
+ nb_attempts = 0;
+
+ mask.clear();
+ vignette->clear();
+
+ pxs = 0; pys = 0;
+
+ for(int s = 0; nb_attempts < max_nb_attempts && s < nb_shapes; s++) {
+ Shape shape;
+
+ do {
+ tmp.clear();
+
+ do {
+
+ if(s == 0) {
+ shape.randomize(big_part_size / 2, big_part_hole_size / 2);
+ } else {
+ shape.randomize(small_part_size / 2, small_part_hole_size / 2);
+ }
+
+ if(nb_shapes == 2 || s == 0 || label == 0) {
+ xs = int(drand48() * Vignette::width);
+ ys = int(drand48() * Vignette::height);
+ } else {
+ xs = pxs + int(4 * (drand48() - 0.5) * small_part_hole_size);
+ ys = pys + int(4 * (drand48() - 0.5) * small_part_hole_size);
+ }
+ nb_attempts++;
+
+ } while(nb_attempts < max_nb_attempts &&
+ shape.overwrites(&tmp, xs, ys));
+
+ shape.draw(&tmp, xs, ys);
+ tmp.fill(xs, ys, 128);
+ i = tmp.intersection(&mask);
+
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ s > 0 &&
+ ((label == 0 && i > 0) || (label == 1 && (i < 1 || i > 4))));
+
+ shape.draw(vignette, xs, ys);
+ pxs = xs; pys = ys;
+
+ if(label == 0) {
+ for(int k = 0; k < dist_min; k++) tmp.grow();
+ }
+
+ mask.superpose(&mask, &tmp);
+ }
+ } while(nb_attempts >= max_nb_attempts);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_11_H
+#define VISION_PROBLEM_11_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_11 : public VignetteGenerator {
+ static const int small_part_size = Vignette::width / 3;
+ static const int small_part_hole_size = Vignette::width / 9;
+ static const int big_part_size = (Vignette::width * 3)/4;
+ static const int big_part_hole_size = Vignette::width / 4;
+public:
+ VisionProblem_11();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_12.h"
+#include "shape.h"
+
+VisionProblem_12::VisionProblem_12() { }
+
+void VisionProblem_12::generate(int label, Vignette *vignette) {
+ int nb_shapes = 3;
+ scalar_t alpha, beta, gamma;
+ int xs, ys;
+ Shape shape;
+
+ int error;
+
+ do {
+ scalar_t xc, yc, radius;
+ xc = (drand48() * 0.5 + 0.25) * Vignette::width;
+ yc = (drand48() * 0.5 + 0.25) * Vignette::height;
+ radius = (drand48() * 0.5 + 0.1) * Vignette::width;
+ alpha = drand48() * 2 * M_PI;
+ beta = (drand48() * 0.4 + 0.1) * M_PI;
+
+ vignette->clear();
+ error = 0;
+
+ for(int n = 0; n < nb_shapes; n++) {
+ if(label) {
+ if(n == 0)
+ gamma = alpha + M_PI - beta/2;
+ else if(n == 1)
+ gamma = alpha + M_PI + beta/2;
+ else
+ gamma = alpha;
+ } else {
+ if(n == 0)
+ gamma = alpha + M_PI - beta/2;
+ else if(n == 1)
+ gamma = alpha;
+ else
+ gamma = alpha + M_PI + beta/2;
+ }
+
+ if(n < 2) {
+ shape.randomize(small_part_size, small_part_hole_size);
+ } else {
+ shape.randomize(big_part_size, big_part_hole_size);
+ }
+
+ xs = int(xc + radius * cos(gamma));
+ ys = int(yc + radius * sin(gamma));
+
+ error |= shape.overwrites(vignette, xs, ys);
+ shape.draw(vignette, xs, ys);
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_12_H
+#define VISION_PROBLEM_12_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_12 : public VignetteGenerator {
+ static const int small_part_size = Vignette::width / 12;
+ static const int small_part_hole_size = Vignette::width / 24;
+ static const int big_part_size = Vignette::width / 6;
+ static const int big_part_hole_size = Vignette::width / 12;
+public:
+ VisionProblem_12();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_13.h"
+#include "shape.h"
+
+VisionProblem_13::VisionProblem_13() { }
+
+void VisionProblem_13::generate(int label, Vignette *vignette) {
+ Shape big_shape, small_shape;
+ int big_xs1, big_ys1, small_xs1, small_ys1;
+ int big_xs2, big_ys2, small_xs2, small_ys2;
+ int translated_small_xs, translated_small_ys;
+ Vignette tmp;
+ const int dist_min = Vignette::width/4;
+ int nb_attempts;
+ const int max_nb_attempts = 100;
+
+ do {
+ nb_attempts = 0;
+ do {
+
+ vignette->clear();
+
+ big_shape.randomize(big_part_size / 2, big_part_hole_size / 2);
+
+ tmp.clear();
+ do {
+ big_xs1 = int(drand48() * Vignette::width);
+ big_ys1 = int(drand48() * Vignette::height);
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ big_shape.overwrites(vignette, big_xs1, big_ys1));
+
+ big_shape.draw(vignette, big_xs1, big_ys1);
+ big_shape.draw(&tmp, big_xs1, big_ys1);
+ for(int k = 0; k < dist_min; k++) tmp.grow();
+
+ do {
+ small_shape.randomize(small_part_size / 2, small_part_hole_size / 2);
+ small_xs1 = int(drand48() * Vignette::width);
+ small_ys1 = int(drand48() * Vignette::height);
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ (!small_shape.overwrites(&tmp, small_xs1, small_ys1) ||
+ small_shape.overwrites(vignette, small_xs1, small_ys1)));
+
+ small_shape.draw(vignette, small_xs1, small_ys1);
+
+ tmp.clear();
+ do {
+ big_xs2 = int(drand48() * Vignette::width);
+ big_ys2 = int(drand48() * Vignette::height);
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ big_shape.overwrites(vignette, big_xs2, big_ys2));
+ big_shape.draw(vignette, big_xs2, big_ys2);
+ big_shape.draw(&tmp, big_xs2, big_ys2);
+ for(int k = 0; k < dist_min; k++) tmp.grow();
+
+ translated_small_xs = small_xs1 + (big_xs2 - big_xs1);
+ translated_small_ys = small_ys1 + (big_ys2 - big_ys1);
+
+ } while(nb_attempts < max_nb_attempts &&
+ small_shape.overwrites(vignette,
+ translated_small_xs,
+ translated_small_ys));
+
+ if(label) {
+ small_xs2 = translated_small_xs;
+ small_ys2 = translated_small_ys;
+ } else {
+ do {
+ small_xs2 = int(drand48() * Vignette::width);
+ small_ys2 = int(drand48() * Vignette::height);
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ (sq(small_xs2 - translated_small_xs) + sq(small_ys2 - translated_small_ys) < sq(dist_min) ||
+ !small_shape.overwrites(&tmp, small_xs2, small_ys2) ||
+ small_shape.overwrites(vignette, small_xs2, small_ys2)));
+ }
+ } while(nb_attempts >= max_nb_attempts);
+ small_shape.draw(vignette, small_xs2, small_ys2);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_13_H
+#define VISION_PROBLEM_13_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_13 : public VignetteGenerator {
+ static const int small_part_size = Vignette::width / 6;
+ static const int small_part_hole_size = Vignette::width / 12;
+ static const int big_part_size = Vignette::width / 2;
+ static const int big_part_hole_size = Vignette::width / 4;
+public:
+ VisionProblem_13();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_17.h"
+#include "shape.h"
+
+VisionProblem_17::VisionProblem_17() { }
+
+void VisionProblem_17::generate(int label, Vignette *vignette) {
+ const int nb_shapes = 4;
+ int xs[nb_shapes], ys[nb_shapes];
+ int shape_number[nb_shapes];
+
+ ASSERT(nb_shapes == 4);
+
+ int too_ambiguous;
+
+ int error;
+
+ do {
+ Shape shape1, shape2;
+ shape1.randomize(part_size/2, hole_size/2);
+ shape2.randomize(part_size/2, hole_size/2);
+
+ //////////////////////////////////////////////////////////////////////
+
+ do {
+ for(int n = 0; n < nb_shapes; n++) {
+ if(n < nb_shapes - 1) {
+ shape_number[n] = 0;
+ } else {
+ shape_number[n] = 1;
+ }
+ xs[n] = int(drand48() * (Vignette::width - part_size)) + part_size/2;
+ ys[n] = int(drand48() * (Vignette::width - part_size)) + part_size/2;
+ }
+
+ scalar_t a = scalar_t(xs[1] - xs[0]), b = scalar_t(ys[1] - ys[0]);
+ scalar_t c = scalar_t(xs[2] - xs[1]), d = scalar_t(ys[2] - ys[1]);
+ scalar_t det = a * d - b * c;
+ scalar_t u = scalar_t(xs[1] * xs[1] - xs[0] * xs[0] + ys[1] * ys[1] - ys[0] * ys[0]);
+ scalar_t v = scalar_t(xs[2] * xs[2] - xs[1] * xs[1] + ys[2] * ys[2] - ys[1] * ys[1]);
+ scalar_t xc = 1/(2 * det) *( d * u - b * v);
+ scalar_t yc = 1/(2 * det) *(- c * u + a * v);
+
+ if(label == 1) {
+ xs[nb_shapes - 1] = int(xc);
+ ys[nb_shapes - 1] = int(yc);
+ too_ambiguous = 0;
+ } else {
+ too_ambiguous = sqrt(sq(scalar_t(xs[nb_shapes - 1]) - xc) +
+ sq(scalar_t(ys[nb_shapes - 1]) - yc)) < scalar_t(part_size);
+ }
+ } while(too_ambiguous ||
+ cluttered_shapes(part_size, nb_shapes, xs, ys));
+
+ //////////////////////////////////////////////////////////////////////
+
+ vignette->clear();
+
+ error = 0;
+ for(int n = 0; n < nb_shapes; n++) {
+ if(shape_number[n] == 0) {
+ error |= shape1.overwrites(vignette, xs[n], ys[n]);
+ shape1.draw(vignette, xs[n], ys[n]);
+ } else {
+ error |= shape2.overwrites(vignette, xs[n], ys[n]);
+ shape2.draw(vignette, xs[n], ys[n]);
+ }
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_17_H
+#define VISION_PROBLEM_17_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_17 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_17();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_18.h"
+#include "shape.h"
+
+VisionProblem_18::VisionProblem_18() { }
+
+void VisionProblem_18::generate(int label, Vignette *vignette) {
+ int error;
+
+ int nb_shapes = 6;
+ int xs[nb_shapes], ys[nb_shapes];
+ Shape shape1, shape2;
+ shape1.randomize(part_size / 2, hole_size / 2);
+ shape2.copy(&shape1);
+
+ do {
+ vignette->clear();
+ error = 0;
+
+ // First half of the shapes are random
+ for(int n = 0; n < nb_shapes/2; n++) {
+ xs[n] = int(drand48() * (Vignette::width - part_size + 1)) + part_size/2;
+ ys[n] = int(drand48() * (Vignette::height - part_size + 1)) + part_size/2;
+ error |= shape1.overwrites(vignette, xs[n], ys[n]);
+ shape1.draw(vignette, xs[n], ys[n]);
+ }
+
+ for(int n = nb_shapes/2; n < nb_shapes; n++) {
+ if(label == 1) {
+ xs[n] = Vignette::width - xs[n - nb_shapes/2];
+ ys[n] = ys[n - nb_shapes/2];
+ } else {
+ xs[n] = int(drand48() * (Vignette::width - part_size + 1)) + part_size/2;
+ ys[n] = ys[n - nb_shapes/2];
+ }
+ error |= shape2.overwrites(vignette, xs[n], ys[n]);
+ shape2.draw(vignette, xs[n], ys[n]);
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_18_H
+#define VISION_PROBLEM_18_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_18 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_18();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_2.h"
+#include "shape.h"
+
+VisionProblem_2::VisionProblem_2() { }
+
+void VisionProblem_2::generate(int label, Vignette *vignette) {
+ int x_big, y_big, x_small, y_small;
+ Shape big_shape, small_shape;
+ Vignette mask;
+ int nb_attempts, max_nb_attempts = 10;
+ int dist_min = Vignette::width/8;
+
+ do {
+ vignette->clear();
+ mask.clear();
+
+ big_shape.randomize(big_part_size / 2, big_part_hole_size / 2);
+
+ do {
+ x_big = int(drand48() * Vignette::width);
+ y_big = int(drand48() * Vignette::height);
+ } while(big_shape.overwrites(vignette, x_big, y_big));
+
+ // The mask will encode either a thin area the small shape should
+ // intersect with (class 1) or a thick one it should not (class 0)
+
+ big_shape.draw(&mask, x_big, y_big);
+
+ if(label) {
+ mask.grow();
+ } else {
+ for(int k = 0; k < dist_min; k++) {
+ mask.grow();
+ }
+ }
+
+ big_shape.draw(vignette, x_big, y_big);
+ vignette->fill(x_big, y_big, 128);
+ vignette->switch_values(128, 255);
+
+ nb_attempts = 0;
+ do {
+ do {
+ small_shape.randomize(small_part_size / 2, small_part_hole_size / 2);
+ x_small = x_big + int((drand48() - 0.5) * big_part_size);
+ y_small = y_big + int((drand48() - 0.5) * big_part_size);
+ } while(small_shape.overwrites(vignette, x_small, y_small)); // ||
+ nb_attempts++;
+ } while(nb_attempts < max_nb_attempts &&
+ ((label && !small_shape.overwrites(&mask, x_small, y_small)) ||
+ (!label && small_shape.overwrites(&mask, x_small, y_small))));
+
+ vignette->replace_value(128, 255);
+ small_shape.draw(vignette, x_small, y_small);
+ } while(nb_attempts >= max_nb_attempts);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_2_H
+#define VISION_PROBLEM_2_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_2 : public VignetteGenerator {
+ static const int small_part_size = Vignette::width/6;
+ static const int small_part_hole_size = Vignette::width/64;
+ static const int big_part_size = (Vignette::width * 3)/4;
+ static const int big_part_hole_size = Vignette::width / 3;
+
+public:
+ VisionProblem_2();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_20.h"
+#include "shape.h"
+
+VisionProblem_20::VisionProblem_20() { }
+
+
+void VisionProblem_20::generate(int label, Vignette *vignette) {
+ int nb_shapes = 2;
+ int xs[nb_shapes], ys[nb_shapes];
+ Shape shapes[nb_shapes];
+
+ int error;
+ do{
+ vignette->clear();
+ error = 0;
+ for(int n = 0; !error && n < nb_shapes; n++) {
+ xs[n] = int(drand48() * Vignette::width);
+ ys[n] = int(drand48() * Vignette::height);
+ if(!label || n == 0) {
+ shapes[n].randomize(part_size / 2, part_hole_size / 2);
+ } else {
+ shapes[n].copy(&shapes[0]);
+ shapes[n].symmetrize(ys[n] - ys[0], - xs[n] + xs[0]);
+ }
+ error |= shapes[n].overwrites(vignette, xs[n], ys[n]);
+ shapes[n].draw(vignette, xs[n], ys[n]);
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_20_H
+#define VISION_PROBLEM_20_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_20 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 4;
+ static const int part_hole_size = Vignette::width / 32;
+public:
+ VisionProblem_20();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_21.h"
+#include "shape.h"
+
+VisionProblem_21::VisionProblem_21() { }
+
+void VisionProblem_21::generate(int label, Vignette *vignette) {
+ int nb_shapes = 2;
+ int xs[nb_shapes], ys[nb_shapes];
+ scalar_t scales[nb_shapes], angles[nb_shapes];
+ Shape shapes[nb_shapes];
+
+ int error;
+ do {
+
+ scalar_t max_scale = -1;
+
+ for(int n = 0; n < nb_shapes; n++) {
+ xs[n] = int(drand48() * Vignette::width);
+ ys[n] = int(drand48() * Vignette::height);
+
+ scales[n] = 1.0 + 3.0 * drand48();
+
+ if(n == 0 || scales[n] > max_scale) max_scale = scales[n];
+
+ angles[n] = drand48() * 2 * M_PI;
+ }
+
+ for(int n = 0; n < nb_shapes; n++) {
+ if(n == 0 || label == 0) {
+ shapes[n].randomize(max_scale * part_size / 2, max_scale * hole_size/2);
+ } else {
+ shapes[n].copy(&shapes[0]);
+ }
+ }
+
+ for(int n = 0; n < nb_shapes; n++) {
+ shapes[n].scale(scales[n] / max_scale);
+ shapes[n].rotate(angles[n]);
+ }
+
+ vignette->clear();
+
+ error = 0;
+ for(int n = 0; n < nb_shapes; n++) {
+ error |= shapes[n].overwrites(vignette, xs[n], ys[n]);
+ shapes[n].draw(vignette, xs[n], ys[n]);
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_21_H
+#define VISION_PROBLEM_21_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_21 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_21();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_3.h"
+#include "shape.h"
+
+VisionProblem_3::VisionProblem_3() { }
+
+void VisionProblem_3::generate(int label, Vignette *vignette) {
+ int nb_shapes = 4;
+ Vignette avoid, tmp;
+ const int dist_min = Vignette::width / 8;
+
+ int nb_attempts;
+ const int max_nb_attempts = 100;
+
+ do {
+ avoid.clear();
+ vignette->clear();
+
+ nb_attempts = 0;
+
+ for(int s = 0; nb_attempts < max_nb_attempts && s < nb_shapes; s++) {
+ Shape shape;
+
+ int xs, ys, i, right_margin, right_connection;
+
+ do {
+ tmp.clear();
+ do {
+ do {
+ xs = int(drand48() * Vignette::width);
+ ys = int(drand48() * Vignette::height);
+ shape.randomize(part_size, hole_size);
+ } while(shape.overwrites(&tmp, xs, ys)); // check not out-of-vignette
+
+ // omg this is ugly
+ if(label && s == 1) {
+ right_margin = 1;
+ } else {
+ right_margin = !shape.overwrites(&avoid, xs, ys);
+ }
+
+ if((label && (s == 1 || s == 3)) || (!label && (s >= 2))) {
+ right_connection = shape.overwrites(vignette, xs, ys);
+ } else {
+ right_connection = 1;
+ }
+
+ nb_attempts++;
+
+ } while(nb_attempts < max_nb_attempts && !right_margin);
+
+ shape.draw(&tmp, xs, ys);
+ tmp.fill(xs, ys, 0);
+
+ if(right_margin && right_connection) {
+ if((label && (s == 1 || s == 3)) || (!label && (s >= 2))) {
+ i = vignette->intersection(&tmp);
+ right_connection = (i > 0) && (i < 4);
+ } else {
+ right_connection = 1;
+ }
+ } else right_connection = 0; // To avoid compilation warning
+ } while(nb_attempts < max_nb_attempts && (!right_margin || !right_connection));
+
+ if(nb_attempts < max_nb_attempts) {
+ shape.draw(vignette, xs, ys);
+ vignette->fill(xs, ys, 128);
+ if((label && s < 2) || (!label && s < 1)) {
+ for(int k = 0; k < dist_min; k++) tmp.grow();
+ avoid.superpose(&avoid, &tmp);
+ }
+ }
+ }
+ } while(nb_attempts >= max_nb_attempts);
+
+ vignette->replace_value(128, 255);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_3_H
+#define VISION_PROBLEM_3_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_3 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_3();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_5.h"
+#include "shape.h"
+
+VisionProblem_5::VisionProblem_5() { }
+
+void VisionProblem_5::generate(int label, Vignette *vignette) {
+ int nb_shapes;
+
+ nb_shapes = 4;
+
+ vignette->clear();
+ Shape shape;
+
+ for(int s = 0; s < nb_shapes; s++) {
+ if(label == 0 || s == 0 || s == nb_shapes/2) {
+ shape.randomize(part_size, part_hole_size);
+ }
+
+ int xs, ys;
+ do {
+ xs = int(drand48() * Vignette::width);
+ ys = int(drand48() * Vignette::height);
+ } while(shape.overwrites(vignette, xs, ys));
+ shape.draw(vignette, xs, ys);
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_5_H
+#define VISION_PROBLEM_5_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_5 : public VignetteGenerator {
+ static const int part_size = Vignette::width/6;
+ static const int part_hole_size = Vignette::width/64;
+public:
+ VisionProblem_5();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_6.h"
+#include "shape.h"
+
+VisionProblem_6::VisionProblem_6() { }
+
+void VisionProblem_6::generate(int label, Vignette *vignette) {
+ const int nb_shapes = 4;
+ int xs[nb_shapes], ys[nb_shapes];
+ int shape_number[nb_shapes];
+
+ ASSERT(nb_shapes == 4);
+
+ int too_ambiguous;
+
+ int error;
+
+ do {
+ Shape shape1, shape2;
+ shape1.randomize(part_size/2, hole_size/2);
+ shape2.randomize(part_size/2, hole_size/2);
+
+ scalar_t xc1, yc1, alpha1;
+ scalar_t xc2, yc2, alpha2;
+ scalar_t r;
+ shape_number[0] = 0;
+ shape_number[1] = 0;
+ shape_number[2] = 1;
+ shape_number[3] = 1;
+ do {
+ if(label == 1) {
+ xc1 = drand48() * (Vignette::width - part_size) ;
+ yc1 = drand48() * (Vignette::width - part_size) ;
+ alpha1 = drand48() * M_PI * 2;
+ r = drand48() * (Vignette::width + Vignette::height)/2;
+
+ xc2 = drand48() * (Vignette::width - part_size) ;
+ yc2 = drand48() * (Vignette::width - part_size) ;
+ alpha2 = drand48() * M_PI * 2;
+
+ xs[0] = int(xc1 + r * cos(alpha1));
+ ys[0] = int(yc1 + r * sin(alpha1));
+ xs[1] = int(xc1 - r * cos(alpha1));
+ ys[1] = int(yc1 - r * sin(alpha1));
+ xs[2] = int(xc2 + r * cos(alpha2));
+ ys[2] = int(yc2 + r * sin(alpha2));
+ xs[3] = int(xc2 - r * cos(alpha2));
+ ys[3] = int(yc2 - r * sin(alpha2));
+ too_ambiguous = 0;
+ } else {
+ for(int n = 0; n < nb_shapes; n++) {
+ xs[n] = int(drand48() * (Vignette::width - part_size));
+ ys[n] = int(drand48() * (Vignette::width - part_size));
+ }
+ scalar_t d1 = sqrt(sq(xs[0] - xs[1]) + sq(ys[0] - ys[1]));
+ scalar_t d2 = sqrt(sq(xs[2] - xs[3]) + sq(ys[2] - ys[3]));
+ too_ambiguous = abs(d1 - d2) < scalar_t(part_size);
+ }
+ } while(too_ambiguous ||
+ cluttered_shapes(part_size, nb_shapes, xs, ys));
+
+ vignette->clear();
+
+ error = 0;
+ for(int n = 0; n < nb_shapes; n++) {
+ if(shape_number[n] == 0) {
+ error |= shape1.overwrites(vignette, xs[n], ys[n]);
+ shape1.draw(vignette, xs[n], ys[n]);
+ } else {
+ error |= shape2.overwrites(vignette, xs[n], ys[n]);
+ shape2.draw(vignette, xs[n], ys[n]);
+ }
+ }
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_6_H
+#define VISION_PROBLEM_6_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_6 : public VignetteGenerator {
+ static const int part_size = Vignette::width / 6;
+ static const int hole_size = Vignette::width / 64;
+public:
+ VisionProblem_6();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_8.h"
+#include "shape.h"
+
+VisionProblem_8::VisionProblem_8() { }
+
+void VisionProblem_8::generate(int label, Vignette *vignette) {
+ int x_big, y_big, x_small, y_small;
+ Shape big_shape, small_shape;
+
+ int error;
+ do {
+
+ vignette->clear();
+
+ error = 0;
+
+ big_shape.randomize(big_part_size / 2, big_part_hole_size / 2);
+ small_shape.copy(&big_shape);
+ small_shape.scale(0.5);
+
+ do {
+ x_big = int(drand48() * Vignette::width);
+ y_big = int(drand48() * Vignette::height);
+ } while(big_shape.overwrites(vignette, x_big, y_big));
+
+ if(!error) {
+ big_shape.draw(vignette, x_big, y_big);
+
+ vignette->fill(x_big, y_big, 128);
+
+ if(label) {
+ vignette->switch_values(128, 255);
+ } else {
+ if(drand48() < 0.5) {
+ vignette->switch_values(128, 255);
+ Shape tmp;
+ tmp.randomize(big_part_size / 2, big_part_hole_size / 2);
+ small_shape.copy(&tmp);
+ small_shape.scale(0.5);
+ }
+ }
+
+ int nb_attempts = 0;
+ do {
+ x_small = int(drand48() * Vignette::width);
+ y_small = int(drand48() * Vignette::height);
+ error = small_shape.overwrites(vignette, x_small, y_small);
+ nb_attempts++;
+ } while(error && nb_attempts < 10);
+
+ if(!error) {
+ vignette->replace_value(128, 255);
+ small_shape.draw(vignette, x_small, y_small);
+ }
+ }
+
+ } while(error);
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_8_H
+#define VISION_PROBLEM_8_H
+
+#include "vignette_generator.h"
+#include "vision_problem_tools.h"
+
+class VisionProblem_8 : public VignetteGenerator {
+ static const int small_part_size = Vignette::width/6;
+ static const int small_part_hole_size = Vignette::width/64;
+ static const int big_part_size = (Vignette::width * 3)/4;
+ static const int big_part_hole_size = Vignette::width / 3;
+public:
+ VisionProblem_8();
+ virtual void generate(int label, Vignette *vignette);
+};
+
+#endif
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "vision_problem_tools.h"
+
+int cluttered_shapes(int part_size, int nb_shapes, int *xs, int *ys) {
+ for(int n = 0; n < nb_shapes; n++) {
+ for(int m = 0; m < n; m++) {
+ if(abs(xs[n] - xs[m]) < part_size && abs(ys[n] - ys[m]) < part_size)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+scalar_t dist_point_to_segment(scalar_t xp, scalar_t yp,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2) {
+ scalar_t s;
+ s = (xp - x1) * (x2 - x1) + (yp - y1) * (y2 - y1);
+ if(s < 0) {
+ return sqrt(sq(xp - x1) + sq(yp - y1));
+ } else if(s > sq(x2 - x1) + sq(y2 - y1)) {
+ return sqrt(sq(xp - x2) + sq(yp - y2));
+ } else {
+ return abs((xp - x1) * (y2 - y1) - (yp - y1) * (x2 - x1))/sqrt(sq(x2 - x1) + sq(y2 - y1));
+ }
+}
+
+int point_in_band(scalar_t xp, scalar_t yp,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2,
+ scalar_t width) {
+ scalar_t s;
+ s = (xp - x1) * (x2 - x1) + (yp - y1) * (y2 - y1);
+ if(s < 0) {
+ return 0;
+ } else if(s > sq(x2 - x1) + sq(y2 - y1)) {
+ return 0;
+ } else {
+ return abs((xp - x1) * (y2 - y1) - (yp - y1) * (x2 - x1))/sqrt(sq(x2 - x1) + sq(y2 - y1)) <= width;
+ }
+}
--- /dev/null
+/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VISION_PROBLEM_TOOLS_H
+#define VISION_PROBLEM_TOOLS_H
+
+#include "misc.h"
+#include "vignette.h"
+
+int cluttered_shapes(int part_size, int nb_shapes, int *xs, int *ys);
+
+scalar_t dist_point_to_segment(scalar_t xp, scalar_t yp,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2);
+
+int point_in_band(scalar_t xp, scalar_t yp,
+ scalar_t x1, scalar_t y1, scalar_t x2, scalar_t y2,
+ scalar_t width);
+
+#endif
--- /dev/null
+c/*
+ * svrt is the ``Synthetic Visual Reasoning Test'', an image
+ * generator for evaluating classification performance of machine
+ * learning systems, humans and primates.
+ *
+ * Copyright (c) 2009 Idiap Research Institute, http://www.idiap.ch/
+ * Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ * This file is part of svrt.
+ *
+ * svrt is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * svrt is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with selector. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <iostream>
+#include <fstream>
+#include <cmath>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace std;
+
+#include "rgb_image.h"
+#include "param_parser.h"
+#include "global.h"
+
+#include "vignette.h"
+#include "shape.h"
+#include "classifier.h"
+#include "classifier_reader.h"
+#include "naive_bayesian_classifier.h"
+#include "boosted_classifier.h"
+#include "error_rates.h"
+
+#include "vision_problem_1.h"
+#include "vision_problem_2.h"
+#include "vision_problem_3.h"
+#include "vision_problem_5.h"
+#include "vision_problem_6.h"
+#include "vision_problem_8.h"
+#include "vision_problem_11.h"
+#include "vision_problem_12.h"
+#include "vision_problem_13.h"
+#include "vision_problem_17.h"
+#include "vision_problem_18.h"
+#include "vision_problem_20.h"
+#include "vision_problem_21.h"
+
+//////////////////////////////////////////////////////////////////////
+
+void check(bool condition, const char *message) {
+ if(!condition) {
+ cerr << message << endl;
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv) {
+
+ char buffer[buffer_size];
+ char *new_argv[argc];
+ int new_argc = 0;
+
+ cout << "-- ARGUMENTS ---------------------------------------------------------" << endl;
+
+ for(int i = 0; i < argc; i++)
+ cout << (i > 0 ? " " : "") << argv[i] << (i < argc - 1 ? " \\" : "")
+ << endl;
+
+ cout << "-- PARAMETERS --------------------------------------------------------" << endl;
+
+ {
+ ParamParser parser;
+ global.init_parser(&parser);
+ parser.parse_options(argc, argv, false, &new_argc, new_argv);
+ global.read_parser(&parser);
+ parser.print_all(&cout);
+ }
+
+ nice(global.niceness);
+ srand48(global.random_seed);
+
+ VignetteGenerator *generator;
+
+ switch(global.problem_number) {
+ case 1:
+ generator = new VisionProblem_1();
+ break;
+ case 2:
+ generator = new VisionProblem_2();
+ break;
+ case 3:
+ generator = new VisionProblem_3();
+ break;
+ // case 4:
+ // generator = new VisionProblem_4();
+ // break;
+ case 5:
+ generator = new VisionProblem_5();
+ break;
+ case 6:
+ generator = new VisionProblem_6();
+ break;
+ // case 7:
+ // generator = new VisionProblem_7();
+ // break;
+ case 8:
+ generator = new VisionProblem_8();
+ break;
+ // case 9:
+ // generator = new VisionProblem_9();
+ // break;
+ // case 10:
+ // generator = new VisionProblem_10();
+ // break;
+ case 11:
+ generator = new VisionProblem_11();
+ break;
+ case 12:
+ generator = new VisionProblem_12();
+ break;
+ case 13:
+ generator = new VisionProblem_13();
+ break;
+ // case 14:
+ // generator = new VisionProblem_14();
+ // break;
+ // case 15:
+ // generator = new VisionProblem_15();
+ // break;
+ // case 16:
+ // generator = new VisionProblem_16();
+ // break;
+ case 17:
+ generator = new VisionProblem_17();
+ break;
+ case 18:
+ generator = new VisionProblem_18();
+ break;
+ // case 19:
+ // generator = new VisionProblem_19();
+ // break;
+ case 20:
+ generator = new VisionProblem_20();
+ break;
+ case 21:
+ generator = new VisionProblem_21();
+ break;
+ // case 22:
+ // generator = new VisionProblem_22();
+ // break;
+ // case 23:
+ // generator = new VisionProblem_23();
+ // break;
+ default:
+ cerr << "Can not find problem "
+ << global.problem_number
+ << endl;
+ exit(1);
+ }
+
+ generator->precompute();
+
+ //////////////////////////////////////////////////////////////////////
+
+ Vignette *train_samples;
+ int *train_labels;
+
+ train_samples = new Vignette[global.nb_train_samples];
+ train_labels = new int[global.nb_train_samples];
+
+ //////////////////////////////////////////////////////////////////////
+
+ Classifier *classifier = 0;
+
+ cout << "-- COMPUTATIONS ------------------------------------------------------" << endl;
+
+ for(int c = 1; c < new_argc; c++) {
+
+ if(strcmp(new_argv[c], "randomize-train") == 0) {
+ for(int n = 0; n < global.nb_train_samples; n++) {
+ if(n > 0 && n%100 == 0) cout << "*"; cout.flush();
+ // cout << "n = " << n << endl;
+ train_labels[n] = int(drand48() * 2);
+ generator->generate(train_labels[n], &train_samples[n]);
+ }
+ cout << endl;
+ }
+
+ else if(strcmp(new_argv[c], "adaboost") == 0) {
+ delete classifier;
+ cout << "Building and training adaboost classifier." << endl;
+ classifier = new BoostedClassifier(global.nb_weak_learners);
+ classifier->train(global.nb_train_samples, train_samples, train_labels);
+ }
+
+ else if(strcmp(new_argv[c], "naive-bayesian") == 0) {
+ delete classifier;
+ cout << "Building and training naive bayesian classifier." << endl;
+ classifier = new NaiveBayesianClassifier();
+ classifier->train(global.nb_train_samples, train_samples, train_labels);
+ }
+
+ else if(strcmp(new_argv[c], "read-classifier") == 0) {
+ delete classifier;
+ sprintf(buffer, "%s", global.classifier_name);
+ cout << "Reading classifier from " << buffer << "." << endl;
+ ifstream in(buffer);
+ if(in.fail()) {
+ cerr << "Can not open " << buffer << " for reading." << endl;
+ exit(1);
+ }
+ classifier = read_classifier(&in);
+ }
+
+ else if(strcmp(new_argv[c], "write-classifier") == 0) {
+ check(classifier, "No classifier.");
+ sprintf(buffer, "%s/%s", global.result_path, global.classifier_name);
+ cout << "Writing classifier to " << buffer << "." << endl;
+ ofstream out(buffer);
+ if(out.fail()) {
+ cerr << "Can not open " << buffer << " for writing." << endl;
+ exit(1);
+ }
+ classifier->write(&out);
+ }
+
+ else if(strcmp(new_argv[c], "compute-errors-vs-nb-samples") == 0) {
+ for(int t = global.nb_train_samples; t >= 100; t /= 10) {
+ for(int n = 0; n < t; n++) {
+ train_labels[n] = int(drand48() * 2);
+ generator->generate(train_labels[n], &train_samples[n]);
+ }
+ Classifier *classifier = 0;
+ cout << "Building and training adaboost classifier with " << t << " samples." << endl;
+ classifier = new BoostedClassifier(global.nb_weak_learners);
+ classifier->train(t, train_samples, train_labels);
+ cout << "ERROR_RATES_VS_NB_SAMPLES "
+ << t
+ << " TRAIN_ERROR "
+ << error_rate(classifier, t, train_samples, train_labels)
+ << " TEST_ERROR "
+ << test_error_rate(generator, classifier, global.nb_test_samples) << endl;
+ delete classifier;
+ }
+ }
+
+ else if(strcmp(new_argv[c], "compute-train-error") == 0) {
+ check(classifier, "No classifier.");
+ cout << "TRAIN_ERROR_RATE "
+ << classifier->name()
+ << " "
+ << error_rate(classifier, global.nb_train_samples, train_samples, train_labels)
+ << endl;
+ }
+
+ else if(strcmp(new_argv[c], "compute-test-error") == 0) {
+ check(classifier, "No classifier.");
+ cout << "TEST_ERROR_RATE "
+ << classifier->name()
+ << " "
+ << test_error_rate(generator, classifier, global.nb_test_samples) << endl;
+ }
+
+ else if(strcmp(new_argv[c], "write-samples") == 0) {
+ Vignette vignette;
+ for(int k = 0; k < global.nb_train_samples; k++) {
+ for(int l = 0; l < 2; l++) {
+ generator->generate(l, &vignette);
+ sprintf(buffer, "%s/sample_%01d_%04d.png", global.result_path, l, k);
+ vignette.write_png(buffer, 1);
+ cout << "Wrote " << buffer << endl;
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+
+ else {
+ cerr << "Unknown action " << new_argv[c] << endl;
+ exit(1);
+ }
+
+ }
+
+ cout << "-- FINISHED ----------------------------------------------------------" << endl;
+
+ delete classifier;
+ delete[] train_labels;
+ delete[] train_samples;
+ delete generator;
+}