From: Francois Fleuret Date: Sun, 22 Nov 2009 20:48:40 +0000 (+0100) Subject: Initia commit. X-Git-Url: https://www.fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=svrt.git;a=commitdiff_plain;h=194e1b60502426108c6f6c3cf2e08e95e7a2811d Initia commit. --- 194e1b60502426108c6f6c3cf2e08e95e7a2811d diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2e37a79 --- /dev/null +++ b/Makefile @@ -0,0 +1,75 @@ + +# 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 +# +# 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 . + +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 diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..eab2d84 --- /dev/null +++ b/README.txt @@ -0,0 +1,14 @@ +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. diff --git a/boosted_classifier.cc b/boosted_classifier.cc new file mode 100644 index 0000000..70f09d1 --- /dev/null +++ b/boosted_classifier.cc @@ -0,0 +1,243 @@ +/* + * 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 + * + * 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 . + * + */ + +#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; +} diff --git a/boosted_classifier.h b/boosted_classifier.h new file mode 100644 index 0000000..23039e6 --- /dev/null +++ b/boosted_classifier.h @@ -0,0 +1,49 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/classifier.cc b/classifier.cc new file mode 100644 index 0000000..491b194 --- /dev/null +++ b/classifier.cc @@ -0,0 +1,27 @@ +/* + * 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 + * + * 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 . + * + */ + +#include "classifier.h" + +Classifier::~Classifier() { } diff --git a/classifier.h b/classifier.h new file mode 100644 index 0000000..b38ba40 --- /dev/null +++ b/classifier.h @@ -0,0 +1,53 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/classifier_reader.cc b/classifier_reader.cc new file mode 100644 index 0000000..e118979 --- /dev/null +++ b/classifier_reader.cc @@ -0,0 +1,53 @@ +/* + * 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 + * + * 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 . + * + */ + +#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; +} diff --git a/classifier_reader.h b/classifier_reader.h new file mode 100644 index 0000000..70fa73a --- /dev/null +++ b/classifier_reader.h @@ -0,0 +1,37 @@ +/* + * 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 + * + * 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 . + * + */ + +#ifndef CLASSIFIER_READER_H +#define CLASSIFIER_READER_H + +#include "classifier.h" + +enum { + CT_NAIVE_BAYESIAN, + CT_BOOSTED +}; + +Classifier *read_classifier(istream *in); + +#endif diff --git a/discrete_density.cc b/discrete_density.cc new file mode 100644 index 0000000..d14ec8d --- /dev/null +++ b/discrete_density.cc @@ -0,0 +1,105 @@ +/* + * 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 + * + * 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 . + * + */ + +#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(); +} diff --git a/discrete_density.h b/discrete_density.h new file mode 100644 index 0000000..1c2b08d --- /dev/null +++ b/discrete_density.h @@ -0,0 +1,57 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/doit.sh b/doit.sh new file mode 100755 index 0000000..1315b59 --- /dev/null +++ b/doit.sh @@ -0,0 +1,53 @@ +#!/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 +# +# 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 . + +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 diff --git a/error_rates.cc b/error_rates.cc new file mode 100644 index 0000000..979edb4 --- /dev/null +++ b/error_rates.cc @@ -0,0 +1,88 @@ +/* + * 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 + * + * 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 . + * + */ + +#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)); +} diff --git a/error_rates.h b/error_rates.h new file mode 100644 index 0000000..899cd4d --- /dev/null +++ b/error_rates.h @@ -0,0 +1,35 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/fusion_sort.cc b/fusion_sort.cc new file mode 100644 index 0000000..96d056f --- /dev/null +++ b/fusion_sort.cc @@ -0,0 +1,91 @@ +/* + * 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 + * + * 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 . + * + */ + +#include "fusion_sort.h" +#include + +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]; +} diff --git a/fusion_sort.h b/fusion_sort.h new file mode 100644 index 0000000..e1254b9 --- /dev/null +++ b/fusion_sort.h @@ -0,0 +1,34 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/global.cc b/global.cc new file mode 100644 index 0000000..8137f35 --- /dev/null +++ b/global.cc @@ -0,0 +1,79 @@ +/* + * 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 + * + * 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 . + * + */ + +#include + +#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"); +} diff --git a/global.h b/global.h new file mode 100644 index 0000000..1066ac6 --- /dev/null +++ b/global.h @@ -0,0 +1,61 @@ +/* + * 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 + * + * 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 . + * + */ + +#ifndef GLOBAL_H +#define GLOBAL_H + +#include + +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 diff --git a/gpl-3.0.txt b/gpl-3.0.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/jpeg_misc.cc b/jpeg_misc.cc new file mode 100644 index 0000000..574bf13 --- /dev/null +++ b/jpeg_misc.cc @@ -0,0 +1,31 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/jpeg_misc.h b/jpeg_misc.h new file mode 100644 index 0000000..b34da02 --- /dev/null +++ b/jpeg_misc.h @@ -0,0 +1,42 @@ +/* + * 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 + * + * 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 . + * + */ + +#ifndef JPEG_MISC_H +#define JPEG_MISC_H + +#include +#include +#include +#include + +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 diff --git a/misc.cc b/misc.cc new file mode 100644 index 0000000..2f766a6 --- /dev/null +++ b/misc.cc @@ -0,0 +1,103 @@ +/* + * 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 + * + * 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 . + * + */ + +#include + +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 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; +} diff --git a/misc.h b/misc.h new file mode 100644 index 0000000..d5f956c --- /dev/null +++ b/misc.h @@ -0,0 +1,124 @@ +/* + * 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 + * + * 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 . + * + */ + +#ifndef MISC_H +#define MISC_H + +#include +#include +#include +#include +#include +#include + +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 +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 +void deallocate_array(T **array) { + delete[] array[0]; + delete[] array; +} + +template +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 +void write_var(ostream *os, const T *x) { os->write((char *) x, sizeof(T)); } + +template +void read_var(istream *is, T *x) { is->read((char *) x, sizeof(T)); } + +template +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 +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 diff --git a/naive_bayesian_classifier.cc b/naive_bayesian_classifier.cc new file mode 100644 index 0000000..f8799c1 --- /dev/null +++ b/naive_bayesian_classifier.cc @@ -0,0 +1,89 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/naive_bayesian_classifier.h b/naive_bayesian_classifier.h new file mode 100644 index 0000000..de045ff --- /dev/null +++ b/naive_bayesian_classifier.h @@ -0,0 +1,44 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/param_parser.cc b/param_parser.cc new file mode 100644 index 0000000..2d918bd --- /dev/null +++ b/param_parser.cc @@ -0,0 +1,163 @@ +/* + * 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 + * + * 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 . + * + */ + +// All this is clearly non-optimal, loaded with news and deletes and +// should be rewritten. + +#include + +#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; + } +} + diff --git a/param_parser.h b/param_parser.h new file mode 100644 index 0000000..3477c27 --- /dev/null +++ b/param_parser.h @@ -0,0 +1,57 @@ +/* + * 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 + * + * 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 . + * + */ + +/* + + A class to parse the arguments from the command line. + + */ + +#ifndef PARAM_PARSER_H +#define PARAM_PARSER_H + +#include +#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 diff --git a/progress_bar.cc b/progress_bar.cc new file mode 100644 index 0000000..96dc313 --- /dev/null +++ b/progress_bar.cc @@ -0,0 +1,97 @@ +/* + * 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 + * + * 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 . + * + */ + +#include +#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(); + } +} diff --git a/progress_bar.h b/progress_bar.h new file mode 100644 index 0000000..ef0a88d --- /dev/null +++ b/progress_bar.h @@ -0,0 +1,54 @@ +/* + * 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 + * + * 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 . + * + */ + +/* + + 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 + +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 diff --git a/rgb_image.cc b/rgb_image.cc new file mode 100644 index 0000000..f803363 --- /dev/null +++ b/rgb_image.cc @@ -0,0 +1,479 @@ +/* + * 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 + * + * 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 . + * + */ + +#include +#include + +#include +#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; + } +} diff --git a/rgb_image.h b/rgb_image.h new file mode 100644 index 0000000..0f7bf66 --- /dev/null +++ b/rgb_image.h @@ -0,0 +1,86 @@ +/* + * 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 + * + * 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 . + * + */ + +/* + + 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 diff --git a/shape.cc b/shape.cc new file mode 100644 index 0000000..a1932ae --- /dev/null +++ b/shape.cc @@ -0,0 +1,257 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/shape.h b/shape.h new file mode 100644 index 0000000..5440197 --- /dev/null +++ b/shape.h @@ -0,0 +1,61 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/stump.cc b/stump.cc new file mode 100644 index 0000000..c2835a5 --- /dev/null +++ b/stump.cc @@ -0,0 +1,61 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/stump.h b/stump.h new file mode 100644 index 0000000..7c3606e --- /dev/null +++ b/stump.h @@ -0,0 +1,55 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/tools.cc b/tools.cc new file mode 100644 index 0000000..1492e72 --- /dev/null +++ b/tools.cc @@ -0,0 +1,55 @@ +/* + * 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 + * + * 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 . + * + */ + +#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; + } +} diff --git a/tools.h b/tools.h new file mode 100644 index 0000000..3e498af --- /dev/null +++ b/tools.h @@ -0,0 +1,36 @@ +/* + * 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 + * + * 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 . + * + */ + +#ifndef TOOLS_H +#define TOOLS_H + +#include +#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 diff --git a/vignette.cc b/vignette.cc new file mode 100644 index 0000000..8402af0 --- /dev/null +++ b/vignette.cc @@ -0,0 +1,124 @@ +/* + * 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 + * + * 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 . + * + */ + +#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]))); + } + } +} diff --git a/vignette.h b/vignette.h new file mode 100644 index 0000000..5966ac6 --- /dev/null +++ b/vignette.h @@ -0,0 +1,58 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vignette_generator.cc b/vignette_generator.cc new file mode 100644 index 0000000..417fb22 --- /dev/null +++ b/vignette_generator.cc @@ -0,0 +1,29 @@ +/* + * 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 + * + * 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 . + * + */ + +#include "vignette_generator.h" + +VignetteGenerator::~VignetteGenerator() { } + +void VignetteGenerator::precompute() { } diff --git a/vignette_generator.h b/vignette_generator.h new file mode 100644 index 0000000..2390fbf --- /dev/null +++ b/vignette_generator.h @@ -0,0 +1,46 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_1.cc b/vision_problem_1.cc new file mode 100644 index 0000000..aa766e9 --- /dev/null +++ b/vision_problem_1.cc @@ -0,0 +1,73 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_1.h b/vision_problem_1.h new file mode 100644 index 0000000..afdf97a --- /dev/null +++ b/vision_problem_1.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_11.cc b/vision_problem_11.cc new file mode 100644 index 0000000..4cd1cff --- /dev/null +++ b/vision_problem_11.cc @@ -0,0 +1,93 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_11.h b/vision_problem_11.h new file mode 100644 index 0000000..a8cf1ef --- /dev/null +++ b/vision_problem_11.h @@ -0,0 +1,41 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_12.cc b/vision_problem_12.cc new file mode 100644 index 0000000..ea75acb --- /dev/null +++ b/vision_problem_12.cc @@ -0,0 +1,79 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_12.h b/vision_problem_12.h new file mode 100644 index 0000000..3d17d83 --- /dev/null +++ b/vision_problem_12.h @@ -0,0 +1,41 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_13.cc b/vision_problem_13.cc new file mode 100644 index 0000000..30e96f4 --- /dev/null +++ b/vision_problem_13.cc @@ -0,0 +1,105 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_13.h b/vision_problem_13.h new file mode 100644 index 0000000..98c49f8 --- /dev/null +++ b/vision_problem_13.h @@ -0,0 +1,41 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_17.cc b/vision_problem_17.cc new file mode 100644 index 0000000..8d3d9e6 --- /dev/null +++ b/vision_problem_17.cc @@ -0,0 +1,93 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_17.h b/vision_problem_17.h new file mode 100644 index 0000000..f614126 --- /dev/null +++ b/vision_problem_17.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_18.cc b/vision_problem_18.cc new file mode 100644 index 0000000..7064657 --- /dev/null +++ b/vision_problem_18.cc @@ -0,0 +1,63 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_18.h b/vision_problem_18.h new file mode 100644 index 0000000..b8c4dca --- /dev/null +++ b/vision_problem_18.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_2.cc b/vision_problem_2.cc new file mode 100644 index 0000000..75bcbc9 --- /dev/null +++ b/vision_problem_2.cc @@ -0,0 +1,80 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_2.h b/vision_problem_2.h new file mode 100644 index 0000000..a1239f0 --- /dev/null +++ b/vision_problem_2.h @@ -0,0 +1,42 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_20.cc b/vision_problem_20.cc new file mode 100644 index 0000000..e4af48f --- /dev/null +++ b/vision_problem_20.cc @@ -0,0 +1,53 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_20.h b/vision_problem_20.h new file mode 100644 index 0000000..a1f1b7a --- /dev/null +++ b/vision_problem_20.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_21.cc b/vision_problem_21.cc new file mode 100644 index 0000000..2c58a4d --- /dev/null +++ b/vision_problem_21.cc @@ -0,0 +1,73 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_21.h b/vision_problem_21.h new file mode 100644 index 0000000..3fa825a --- /dev/null +++ b/vision_problem_21.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_3.cc b/vision_problem_3.cc new file mode 100644 index 0000000..49a917b --- /dev/null +++ b/vision_problem_3.cc @@ -0,0 +1,100 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_3.h b/vision_problem_3.h new file mode 100644 index 0000000..2df8286 --- /dev/null +++ b/vision_problem_3.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_5.cc b/vision_problem_5.cc new file mode 100644 index 0000000..84b058b --- /dev/null +++ b/vision_problem_5.cc @@ -0,0 +1,50 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); + } +} diff --git a/vision_problem_5.h b/vision_problem_5.h new file mode 100644 index 0000000..8c23f0d --- /dev/null +++ b/vision_problem_5.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_6.cc b/vision_problem_6.cc new file mode 100644 index 0000000..b3b0dfb --- /dev/null +++ b/vision_problem_6.cc @@ -0,0 +1,98 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_6.h b/vision_problem_6.h new file mode 100644 index 0000000..1cbc3fb --- /dev/null +++ b/vision_problem_6.h @@ -0,0 +1,39 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_8.cc b/vision_problem_8.cc new file mode 100644 index 0000000..0d7a28e --- /dev/null +++ b/vision_problem_8.cc @@ -0,0 +1,82 @@ +/* + * 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 + * + * 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 . + * + */ + +#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); +} diff --git a/vision_problem_8.h b/vision_problem_8.h new file mode 100644 index 0000000..b194452 --- /dev/null +++ b/vision_problem_8.h @@ -0,0 +1,41 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_problem_tools.cc b/vision_problem_tools.cc new file mode 100644 index 0000000..0100e90 --- /dev/null +++ b/vision_problem_tools.cc @@ -0,0 +1,62 @@ +/* + * 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 + * + * 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 . + * + */ + +#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; + } +} diff --git a/vision_problem_tools.h b/vision_problem_tools.h new file mode 100644 index 0000000..c2082ae --- /dev/null +++ b/vision_problem_tools.h @@ -0,0 +1,40 @@ +/* + * 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 + * + * 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 . + * + */ + +#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 diff --git a/vision_test.cc b/vision_test.cc new file mode 100644 index 0000000..94591f1 --- /dev/null +++ b/vision_test.cc @@ -0,0 +1,304 @@ +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 + * + * 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 . + * + */ + +#include +#include +#include +#include +#include + +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; +}