Commit d472356a authored by pacanows's avatar pacanows
Browse files

Merge

parents 1a47c706 b8d5db00
......@@ -2,32 +2,43 @@ This is the repository for the ALTA Project
Repository Organization
data/: contains the data for which the fitting techniques are tested against.
documents/: contains the documentation, should be build using doxygen into that
directiory.
sources/: Contains all the source files. A Makefile or VS project can be created
there from the .pro file.
data/: contains the data for which the fitting techniques are tested
against. Files are separated by dimension of the input domain
(e.g. 1d, 2d, 3d, ...).
documents/: contains the documentation, should be build using doxygen into
that directiory.
external/: contains any third party library that needs to be used by ALTA.
Contains a modified QuadProg++ library using Eigen. You can
download and compile automaticaly some third party libraries using
the Scons scripts.
sources/: contains all the source files. A Makefile or VS project can be
created there from the .pro file. Scons generation of the
project is also supported.
Building Advises
Building Advises (for Qt enthousiasts)
We use heavily the Qt profile functionality. To build some of the plugins you will
be required to create your own system dependant .prf for any used library. For example
all the rational BRDF fitters use the Eigen library. Therefore it is mandatory that you
provide a eigen.prf file and that this file is in your QMAKEFEATURES directory.
We use heavily the Qt profile functionality. To build some of the plugins you
will be required to create your own system dependant .prf for any used library.
For example ALTA core use the Eigen library. Therefore it is mandatory that
you provide a eigen.prf file and that this file is in your QMAKEFEATURES
directory.
Dependencies:
Plugin rational_eigen: Eigen
ALTA core: Eigen
Plugin rational_eigen: Eigen
Plugin rational_quadprog: Quadprog++
Plugin rational_quadproge: Quadprog++ and Eigen
Plugin rational_cgal: The CGAL library
Plugin rational_cgal: The CGAL library
Plugin rational_parallel: The OpenMP library, Quadprog++ library and Eigen
Plugin rational_matlab: Matlab engine (matlab.prf required)
Plugin rational_matlab: Matlab engine (matlab.prf required)
Plugin nonlinear_eigen: Eigen
Plugin nonlinear_ceres: CERES library and its dependancies
Plugin nonlinear_nlopt: NLOpt library and its dependancies
Plugin nonlinear_ipopt: IpOpt library and its dependancies
Eigen Plugins
You must provide an eigen.prf file that contains
INCLUDEPATH *= PATH_TO_EIGEN_DIRECTORY
......
import os
env = Environment()
ret = os.system('doxygen doxygen.conf')
env = Environment()
env.SConscript('SConscript')
This diff is collapsed.
/*!
\page contacts Contacts
Here are the names, affiliations, and mails of people involved in ALTA. Please
do not hesitate to share your experience of using this library, bug reports,
or feature requests.<br />
<ul>
<li><a href="mailto:laurent.belcour@inria.fr">Laurent Belcour</a></li>
<li><a href="mailto:romain.pacanowski@inria.fr">Romain Pacanowski</a></li>
<li><a href="mailto:xavier.granier@inria.fr">Xavier Granier</a></li>
</ul>
*/
PROJECT_NAME = ALTA
PROJECT_NUMBER = alpha
SEARCHENGINE = NO
INPUT = ../sources ../sources/scripts .
OUTPUT_DIRECTORY = ./doxygen
RECURSIVE = YES
GENERATE_LATEX = NO
EXTRACT_ALL = NO
#DISABLE_INDEX = YES
LAYOUT_FILE = doxygen.xml
CLASS_GRAPH = NO
PROJECT_LOGO = alta_logo.svg
DETAILS_AT_TOP = YES
MULTILINE_CPP_IS_BRIEF = NO
HTML_STYLESHEET = doxygen.css
IMAGE_PATH = ./images
EXCLUDE_PATTERNS = params.* *retro*
This diff is collapsed.
<doxygenlayout version="1.0">
<navindex>
<tab type="mainpage" visible="yes" title="Overview"/>
<tab type="user" url="@ref examples" title="Examples"/>
<tab type="user" url="@ref license" title="License"/>
<tab type="user" url="@ref contacts" title="Contacts"/>
</navindex>
</doxygenlayout>
/*!
\page license License
ALTA source code is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
We however require that you inform us of any use or modification of ALTA.
Copyright (c) 2013, Inria
*/
/**
\mainpage A BRDF analysis library
<center style="color:red">
We have not released ALTA yet, you will not have access to source code and
data. They will be shipped afterwards. This page was generated automatically
using doxygen. Consequently, you could experience broken links.
</center>
<h2>Description</h2>
ALTA is a software library to analyse, fit and understand BRDFs. It
provides a set of command line softwares to fit measured data to analytical
forms, new tools to understand models and data.
This package provide C++ code to analyze BRDF, fit measured data to
analytical formulation, etc. It is decomposed in three components:
<ul>
<li><em>\ref core</em>: a set of classes providing interfaces to BRDFs,
data type and fitting algorithms. All the code using this library should
rely on this part.</li>
<li><em>\ref plugins</em>: a set of plugins providing fitting algorithms
for rational BRDFs, non-linear BRDFs, etc.</li>
<li><em>\ref softs</em>: a set of tools to fit data, convert data,
export fitting to plots, etc.</li>
</ul>
Three types of plugins are availables:
<ul>
<li><em>\ref data</em> plugins allow to load BRDF measurements files.
</li>
<li><em>\ref function</em> plugins provide BRDF representations.</li>
<li><em>\ref fitter</em> plugins provide fitting algorithms.</li>
</ul>
<h2>Obtain sources</h2>
forms, tools to understand models and data.
ALTA is part of the <a href="http://maverick.inria.fr/Projets/ALTA/ ">
ANR 11-BS02-006</a>, a research project on light transport analysis.
<h3>Target audience</h3>
You are working on BRDFs and you want to <b>benchmark new BRDF models</b> and
compare it with state-of-the-art BRDF models and data easily. You have working
on optical measurements and you want <b>experiment different fitting procedures
and models</b>, or just perform <b>statistical analysis</b> on your data.
<h3>Sample results</h3>
\image html sample_result_01.png
<h2>Download and install</h2>
<h3>Obtain sources</h3>
To access the sources of ALTA, you can clone the mercurial repository:
\verbatim
hg clone https://manao.inria.fr/mercurial/alta
\endverbatim
<h3>Build</h3>
You can build ALTA using either QMake or Scons. To start, we advise to use
Scons as it is lightweight and only requires Python to be installed (ALTA
uses Python for its high level scripting mechanism). To build using scons,
go to the root directory of ALTA and type:
\verbatim
scons -i
\endverbatim
This should obtain some of ALTA's dependencies (such as Eigen) and compile the
main package of the library (i.e. the core, the command line tools, and some
plugins).
To use QMake, or for a more detailed view of ALTA's building scripts and
dependencies, please refer to \ref install.
<h2>How to use it</h2>
After compiling the different command line tools and associated plugins,
go to the sources directory and launch this command line (for Linux users only):
\verbatim
./build/data2brdf --input ../data/1d/Kirby2/Kirby2.dat --output Kirby.brdf --fitter ./build/librational_fitter_eigen.so
\endverbatim
Tada! You have produced your first fit. The produced output is a 1D rational
function, using a monomial basis, interpolating the
<a href="http://www.itl.nist.gov/div898/strd/nls/data/kirby2.shtml">Kirby 2</a>
dataset. Note that this fit is not a BRDF.
The \a data2brdf is one of many \ref commands available in ALTA. It
allows to perform a fitting procedure by converting a \ref data object into a
brdf object (also named \ref function).
To convert this brdf file (in ALTA \ref format), you will need another command:
\verbatim
./build/brdf2brdf --input Kirby.brdf --output Kirby.m --export matlab
\endverbatim
<i>brdf2brdf</i> converts an ALTA brdf file into another format such as
Matlab m file, C++ code, or BRDF Explorer shader. Note that this tool cannot
convert to another ALTA file (e.g. converting a Blinn lobe to a Beckmann
distribution).
<h2>Install and use ALTA</h2>
<h2>Contribute</h2>
Documentation to \ref install
There are many ways in which you can extend ALTA. Please refer to
\ref contribute for more information.
Documentation to \ref contribute
The \ref plugins_manager class allows to load plugins and provide access
to requested elements. See the documentation of this class.
\defgroup core
\defgroup commands
\defgroup plugins
\defgroup softs
*/
......@@ -157,6 +157,8 @@ unsigned int timer::current_time() const
SYSTEMTIME res;
GetSystemTime(&res);
return (unsigned int)(res.wSecond + res.wMinute*60 + res.wHour*360);
#elif __APPLE__
return 0;
#else
struct timespec res;
clock_gettime(CLOCK_MONOTONIC, &res);
......
......@@ -144,12 +144,12 @@ double function::L2_distance(const data* d) const
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec x(d->dimX()), y(d->dimY());
for(int j=0; j<d->dimX(); ++j) { x[j] = dat[j]; }
for(int j=0; j<d->dimY(); ++j) { y[j] = dat[d->dimX()+j]; }
vec x(dimX()), y(d->dimY());
params::convert(&dat[0], d->input_parametrization(), input_parametrization(), &x[0]);
for(int j=0; j<d->dimY(); ++j) { y[j] = dat[d->dimX()+j]; }
//linf_dist = std::max<double>(linf_dist, std::abs<double>(norm(y-rj->value(dat))));
l2_dist += std::pow(norm(y-value(x)), 2);
l2_dist += std::pow(norm(y-value(x)), 2);
}
l2_dist = std::sqrt(l2_dist / d->size());
return l2_dist;
......@@ -163,11 +163,11 @@ double function::Linf_distance(const data* d) const
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec x(d->dimX()), y(d->dimY());
for(int j=0; j<d->dimX(); ++j) { x[j] = dat[j]; }
for(int j=0; j<d->dimY(); ++j) { y[j] = dat[d->dimX()+j]; }
vec x(dimX()), y(d->dimY());
params::convert(&dat[0], d->input_parametrization(), input_parametrization(), &x[0]);
for(int j=0; j<d->dimY(); ++j) { y[j] = dat[d->dimX()+j]; }
linf_dist = std::max<double>(linf_dist, std::abs(norm(y-value(dat))));
linf_dist = std::max<double>(linf_dist, std::abs(norm(y-value(x))));
}
return linf_dist;
......
......@@ -22,7 +22,6 @@ std::map<params::input, const param_info> create_map()
/* 2D Params */
_map.insert(std::make_pair<params::input, const param_info>(params::RUSIN_TH_TD, param_info("RUSIN_TH_TD", 2, "Radialy symmetric Half angle parametrization")));
_map.insert(std::make_pair<params::input, const param_info>(params::ISOTROPIC_TV_PROJ_DPHI, param_info("ISOTROPIC_TV_PROJ_DPHI", 2, "Isoptropic projected phi parametrization without a light direction.")));
_map.insert(std::make_pair<params::input, const param_info>(params::ISOTROPIC_TV_PROJ_DPHI, param_info("THETA_OUT_COS_DPHI_THETA_OUT_SIN_DPHI", 2, "Isoptropic projected phi parametrization without a light direction.")));
/* 3D Params */
_map.insert(std::make_pair<params::input, const param_info>(params::RUSIN_TH_TD_PD, param_info("RUSIN_TH_TD_PD", 3, "Isotropic Half angle parametrization")));
......@@ -93,9 +92,17 @@ void params::to_cartesian(const double* invec, params::input intype,
break;
case ISOTROPIC_TV_PROJ_DPHI:
{
const double theta = 0.5*sqrt(invec[0]*invec[0] + invec[1]*invec[1]);
outvec[3] = invec[0]/theta*sin(theta);
outvec[4] = invec[1]/theta*sin(theta);
const double theta = sqrt(invec[0]*invec[0] + invec[1]*invec[1]);
if(theta > 0.0)
{
outvec[3] = (invec[0]/theta)*sin(theta);
outvec[4] = (invec[1]/theta)*sin(theta);
}
else
{
outvec[3] = 0.0;
outvec[4] = 0.0;
}
outvec[5] = cos(theta);
outvec[0] = 0.0;
outvec[1] = 0.0;
......@@ -130,11 +137,19 @@ void params::to_cartesian(const double* invec, params::input intype,
break;
case ISOTROPIC_TL_TV_PROJ_DPHI:
{
const double theta = 0.5*sqrt(invec[1]*invec[1] + invec[2]*invec[2]);
outvec[3] = invec[1]/theta*sin(theta);
outvec[4] = invec[2]/theta*sin(theta);
const double theta = sqrt(invec[1]*invec[1] + invec[2]*invec[2]);
if(theta > 0.0)
{
outvec[3] = (invec[1]/theta)*sin(theta);
outvec[4] = (invec[2]/theta)*sin(theta);
}
else
{
outvec[3] = 0.0;
outvec[4] = 0.0;
}
outvec[5] = cos(theta);
outvec[0] = 0.0;
outvec[0] = sin(invec[0]);
outvec[1] = 0.0;
outvec[2] = cos(invec[0]);
}
......@@ -358,6 +373,7 @@ params::input params::parse_input(const std::string& txt)
{
if(txt.compare(it->second.name) == 0)
{
std::cout << "<<INFO>> parsed input parametrization " << it->second.name << std::endl;
return it->first;
}
}
......
......@@ -326,7 +326,8 @@ class parametrized
else
{
std::cout << "<<ERROR>> an input parametrization is already defined: " << params::get_name(_in_param) << std::endl;
std::cout << "<<ERROR>> trying to change to: " << params::get_name(new_param) << std::endl;
std::cout << "<<ERROR>> changing to: " << params::get_name(new_param) << std::endl;
_in_param = new_param;
}
}
......
......@@ -478,6 +478,11 @@ size_t plugins_manager::get_system_memory()
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
}
#elif __APPLE__
size_t plugins_manager::get_system_memory()
{
return 0;
}
#else
#include <unistd.h>
size_t plugins_manager::get_system_memory()
......
......@@ -5,12 +5,14 @@ SConscript('data_interpolant/SConscript')
# Building fitters
SConscript('nonlinear_fitter_ceres/SConscript')
SConscript('rational_fitter_eigen/SConscript')
SConscript('rational_fitter_quadprog/SConscript')
# Building functions
SConscript('nonlinear_function_diffuse/SConscript')
SConscript('nonlinear_function_beckmann/SConscript')
SConscript('nonlinear_function_retrobeckmann/SConscript')
SConscript('nonlinear_function_abc/SConscript')
SConscript('nonlinear_function_blinn/SConscript')
SConscript('nonlinear_function_retroblinn/SConscript')
SConscript('nonlinear_function_retroyoo/SConscript')
......
env = Environment()
env.Append(CPPPATH = ['../../../external/build/include', '../../'])
env.Append(LIBPATH = ['../../../external/build/lib', '../../build'])
sources = ['function.cpp']
libs = ['-lcore']
env.SharedLibrary('../../build/nonlinear_function_abc', sources, LIBS=libs)
#include "function.h"
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>
#include <core/common.h>
ALTA_DLL_EXPORT function* provide_function()
{
return new abc_function();
}
// Overload the function operator
vec abc_function::operator()(const vec& x) const
{
return value(x);
}
vec abc_function::value(const vec& x) const
{
// Compute the Shadow term to init res
vec res = vec::Zero(dimY());
const double hn = 1.0 - x[0];
for(int i=0; i<dimY(); ++i)
{
res[i] = _a[i] / pow(1.0 + _b[i]*hn, _c[i]);
}
return res;
}
// Reset the output dimension
void abc_function::setDimY(int nY)
{
_nY = nY ;
// Update the length of the vectors
_a.resize(_nY) ;
_b.resize(_nY) ;
_c.resize(_nY) ;
}
//! Number of parameters to this non-linear function
int abc_function::nbParameters() const
{
return 3*dimY();
}
//! Get the vector of parameters for the function
vec abc_function::parameters() const
{
vec res(nbParameters());
for(int i=0; i<dimY(); ++i)
{
res[i*3 + 0] = _a[i];
res[i*3 + 1] = _b[i];
res[i*3 + 2] = _c[i];
}
return res;
}
//! \brief get the min values for the parameters
vec abc_function::getParametersMin() const
{
vec res(nbParameters());
for(int i=0; i<dimY(); ++i)
{
res[i*3 + 0] = 0.0;
res[i*3 + 1] = 0.0;
res[i*3 + 2] = 0.0;
}
return res;
}
//! Update the vector of parameters for the function
void abc_function::setParameters(const vec& p)
{
for(int i=0; i<dimY(); ++i)
{
_a[i] = p[i*3 + 0];
_b[i] = p[i*3 + 1];
_c[i] = p[i*3 + 2];
}
}
//! Obtain the derivatives of the function with respect to the
//! parameters
//! \todo finish.
vec abc_function::parametersJacobian(const vec& x) const
{
vec jac(dimY()*nbParameters());
for(int i=0; i<dimY(); ++i)
{
for(int j=0; j<dimY(); ++j)
{
if(i == j)
{
const double hn = 1.0 - x[0];
const double f = 1.0 + _b[i]*hn;
const double denom = pow(f, _c[i]);
const double fact = 1.0 / denom;
const double fact2 = fact*fact;
// df / da
jac[i*nbParameters() + j*3+0] = fact;
// df / db
jac[i*nbParameters() + j*3+1] = - _a[i] * hn *_c[i] * pow(f, _c[i]-1.0) * fact2;
// df / dc
if(f > 0.0)
{
jac[i*nbParameters() + j*3+2] = - _a[i] * log(f) * fact;
}
else
{
jac[i*nbParameters() + j*3+2] = 0.0;
}
}
else
{
jac[i*nbParameters() + j*3+0] = 0.0;
jac[i*nbParameters() + j*3+1] = 0.0;
jac[i*nbParameters() + j*3+2] = 0.0;
}
}
}
return jac;
}
void abc_function::bootstrap(const data* d, const arguments& args)
{
for(int i=0; i<dimY(); ++i)
{
_a[i] = 1.0;
_b[i] = 1.0;
_c[i] = 1.0;
}
if(args.is_defined("param"))
{
setParametrization(params::parse_input(args["param"]));
}
else
{
setParametrization(params::COS_TH);
}
if(params::dimension(input_parametrization()) != 1)
{
std::cerr << "<<ERROR>> the parametrization specifed in the file for the ABC model is incorrect" << std::endl;
}
}
//! Load function specific files
bool abc_function::load(std::istream& in)
{
// Parse line until the next comment
while(in.peek() != '#')
{
char line[256];
in.getline(line, 256);
// If we cross the end of the file, or the badbit is
// set, the file cannot be loaded
if(!in.good())
return false;
}
// Checking for the comment line #FUNC nonlinear_function_lafortune
std::string token;
in >> token;
if(token.compare("#FUNC") != 0)
{
std::cerr << "<<ERROR>> parsing the stream. The #FUNC is not the next line defined." << std::endl;
return false;
}
in >> token;
if(token.compare("nonlinear_function_abc") != 0)
{
std::cerr << "<<ERROR>> parsing the stream. function name is not the next token." << std::endl;
return false;
}