/* -*- mona-c++ -*-
* Copyright (c) Leipzig, Madrid 2004 - 2008
* Max-Planck-Institute for Human Cognitive and Brain Science
* Max-Planck-Institute for Evolutionary Anthropology
* BIT, ETSI Telecomunicacion, UPM
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
// $Id: adjuster.cc 672 2005-06-29 13:32:02Z wollny $
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <math.h>
#include <assert.h>
#include <iostream>
#include <iomanip>
#include "adjuster.hh"
TAdjuster::TAdjuster(int thresh)
{
for (int i = 0; i < 256; i++) {
if (i >= thresh ) {
map_table[i] = 1.0;
}else{
map_table[i] = float(i) / float(thresh);
}
}
}
TAdjuster::~TAdjuster()
{
}
TBruteForceAdjuster::TBruteForceAdjuster(int thresh,float _alpha, int _g):
TAdjuster(thresh),alpha(_alpha),g(_g),c_min(0),b_min(0)
{
assert(g);
}
TMapper TBruteForceAdjuster::get_adjust_map(const THistTester *hist)
{
float diff = calc_grid(hist);
mona::cverb << "done: diff = " << diff << " brightness = " << b_min << " contrast = " << c_min << std::endl;
return TMapper(b_min, c_min, map_table);
}
float TBruteForceAdjuster::calc_grid(const THistTester *hist)
{
float c = c_min-alpha;
float c_delta = 2.0 * alpha / g;
float fit_min = hist->get_fit();
float b_min_save = b_min;
float b_delta = 2.0 * alpha / g;
for (int i = 0; i <= g; i++, c += c_delta ) {
float b = b_min_save - alpha;
for ( int j = 0; j <= g; j++, b += b_delta) {
mona::cverb << "(" << std::setw(3) << i
<< ":" << std::setw(3) << j
<< ") b=" << std::setw(8) << std::setprecision(5) << b
<< " c=" << std::setw(8) << std::setprecision(5) << c;
THistTester *help = hist->clone();
help->map(TMapper(b, c, map_table));
float fit = help->get_fit();
delete help;
// mona::cverb << " fit=" << setw(10) << setprecision(5) << fit;
if (fit < fit_min) {
fit_min = fit;
c_min = c;
b_min = b;
if (fit < 0.001)
goto ready;
mona::cverb << '\n';
}else{
mona::cverb << "\r";
}
}
}
ready:
return fit_min;
}
TBruteForceRefinementAdjuster::TBruteForceRefinementAdjuster(int thresh,
float _alpha, int _g,float _epsilon):
TBruteForceAdjuster(thresh,_alpha, _g),
epsilon(_epsilon)
{
}
TMapper TBruteForceRefinementAdjuster::get_adjust_map(const THistTester *hist)
{
float last_diff = hist->get_fit();
float diff;
do {
float old_b_min = b_min;
float old_c_min = c_min;
diff = calc_grid(hist);
if (diff < last_diff) {
//alpha /= g;
last_diff = diff;
}else{
b_min = old_b_min;
c_min = old_c_min;
}
alpha /= 8.0;
}while (alpha > epsilon && diff > epsilon);
return TMapper(b_min, c_min, map_table);
}
TSimpleSearchAdjuster::TSimpleSearchAdjuster(int thresh,int _sectors,float _epsilon):
TAdjuster(thresh),sectors(_sectors),epsilon(_epsilon)
{
assert(sectors);
SinX = new FLOAT[sectors];
CosX = new FLOAT[sectors];
FLOAT steps = (2* M_PI) / sectors;
for (int i = 0; i < sectors; i++) {
SinX[i] = sin( i * steps );
CosX[i] = cos( i * steps );
}
}
TSimpleSearchAdjuster::~TSimpleSearchAdjuster()
{
delete[] CosX;
delete[] SinX;
}
TMapper TSimpleSearchAdjuster::get_adjust_map(const THistTester *hist)
{
float brightness = 0.0;
float contrast = 0.0;
int step = 0;
FLOAT fit = hist->get_fit();
double radius = 0.5;
// Do the game
do {
int i_sector = -1;
// Calulate Distances around Origin, and mark Min
FLOAT fit_min = fit;
for (int i=0;i<sectors;i++) {
THistTester *help = hist->clone();
help->map(TMapper(brightness + radius * SinX[i],
contrast + radius * CosX[i],
map_table));
fit = help->get_fit();
delete help;
if (fit < fit_min) {
fit_min = fit;
i_sector = i;
}
}
// No Min found - slower step
if (i_sector == -1) {
radius /= 2.0;
fit = fit_min;
continue;
}
while (fit > 0.0001) {
THistTester *help = hist->clone();
help->map(TMapper(brightness + 2 * radius * SinX[i_sector],
contrast + 2 * radius * CosX[i_sector],
map_table));
fit = help->get_fit();
delete help;
if ( fit < fit_min ) {
radius *= 2;
fit_min = fit;
}
else
break;
};
brightness += radius * SinX[i_sector];
contrast += radius * CosX[i_sector];
fit = fit_min;
}while( step++ < 100 && radius > epsilon && fit > 0.0001);
return TMapper(brightness,contrast,map_table);
}
#ifdef HAVE_LIBBRIAN
class TAdjustPowell: public powell {
const THistTester *hist_tester;
FLOAT *map_table;
public:
TAdjustPowell(const THistTester *,FLOAT map_table_[]);
double goal(double *);
void search(double *, double **,double&);
};
TAdjustPowell::TAdjustPowell(const THistTester *hist_tester_, FLOAT *map_table_):
powell(2),
hist_tester(hist_tester_),
map_table(map_table_)
{
}
double TAdjustPowell::goal(double *point)
{
THistTester *c = hist_tester->clone();
c->map(TMapper(point[0],point[1],map_table));
double retval = c->get_fit();
delete c;
return retval;
}
void TAdjustPowell::search(double *a, double **b,double& c)
{
}
TPowellAdjuster::TPowellAdjuster(int thresh):
TAdjuster(thresh)
{
}
TMapper TPowellAdjuster::get_adjust_map(const THistTester *hist)
{
TAdjustPowell ap(hist,map_table);
double min[2] = {-2.0,-2.0};
double max[2] = { 2.0, 2.0};
double pos[2] = { 0.0, 0.0};
double f;
double res = ap.minimize(min,max,pos,16,1e-6);
return TMapper(pos[0],pos[1],map_table);
}
class TAdjustGenetic: public population {
T2DFVector region;
T2DFVector minimum;
const THistTester *tester;
double initial_fit;
FLOAT *map_table;
public:
TAdjustGenetic(const T2DFVector ®ion_,
const T2DFVector &minimum_,const THistTester *tester_,
double initial_fit_,FLOAT *map_table_);
private:
virtual void mapValues (member *m, double *pos);
virtual double eval (member *m);
};
TAdjustGenetic::TAdjustGenetic(const T2DFVector ®ion_,
const T2DFVector &minimum_,const THistTester *tester_,
double initial_fit_,
FLOAT *map_table_):
population(100,50,2,0.9,0.07,0.8),
region(region_),
minimum(minimum_),
tester(tester_),
initial_fit(initial_fit_),
map_table(map_table_)
{
}
void TAdjustGenetic::mapValues (member *m, double *pos)
{
pos[0] = m->mapGene(0) * region.x + minimum.x;
pos[1] = m->mapGene(1) * region.y + minimum.y;
}
double TAdjustGenetic::eval (member *m)
{
double fitness;
double pos[2];
if (m->checkFitness (fitness) == true) {
mapValues (m, pos);
THistTester *c = tester->clone();
c->map(TMapper(pos[0],pos[1],map_table));
fitness = c->get_fit() / initial_fit;
delete c;
m->setFitness (fitness);
};
return fitness;
}
TGeneticAdjuster::TGeneticAdjuster(int thresh):
TAdjuster(thresh)
{
}
TMapper TGeneticAdjuster::get_adjust_map(const THistTester *hist)
{
double pos[2];
double initial_fit = hist->get_fit();
if (initial_fit > 0.0) {
T2DFVector range(4.0,4.0);
T2DFVector mini(-2,-2);
TAdjustGenetic ag(range, mini, hist,initial_fit, map_table);
if (ag.generate(pos) < initial_fit)
return TMapper(pos[0],pos[1],map_table);
}
return TMapper(0,0,map_table);
}
#endif