示例#1
0
文件: slice.cpp 项目: belcour/alta
		BrdfSlice(const arguments& args,
              int width, int height, int slice,
              double* content)
        : data(brdf_slice_parameters(args),
               width * height * slice),
          _width(width), _height(height), _slice(slice),
          _data(content)
		{
			// Allocate data
      if (args.is_defined("param") && parametrization().dimX() == 3)
          _phi = (M_PI / 180.0) * args.get_float("phi", 90);
      else
          _phi = 0.5*M_PI;

			// Is the position of the slice componnent (third coordinate)
			// reversed? This ensure that some params can be displayed.
      auto in_param = parametrization().input_parametrization();
			_reverse = in_param == params::ISOTROPIC_TL_TV_PROJ_DPHI ||
          in_param == params::SCHLICK_TL_TK_PROJ_DPHI   ||
          in_param == params::RETRO_TL_TVL_PROJ_DPHI;

			// Update the domain
			_max = max();
			_min = min();
		}
示例#2
0
文件: slice.cpp 项目: belcour/alta
// Allow for a different parametrization depending on the arguments provided.
static const alta::parameters
brdf_slice_parameters(const arguments& args)
{
    auto result = alta::parameters(2, 3,
                                   params::STARK_2D, params::RGB_COLOR);

    if(args.is_defined("param")) {
				params::input param = params::parse_input(args["param"]);

				// The param is a 2D param
				if(params::dimension(param) == 2) {
            std::cout << "<<INFO>> Specified param \"" << args["param"] << "\"" << std::endl;
            result = alta::parameters(result.dimX(), result.dimY(),
                                      param, result.output_parametrization());

            // The oaram is a 3D param
				} else if(params::dimension(param) == 3) {
            std::cout << "<<INFO>> Specified param \"" << args["param"] << "\"" << std::endl;
            result = alta::parameters(3, result.dimY(),
                                      param, result.output_parametrization());

				} else {
            std::cout << "<<ERROR>> Invalid specified param \"" << args["param"] << "\"" << std::endl;
            std::cout << "<<ERROR>> Must have 2D input dimension" << std::endl;
				}
    }

    return result;
}
示例#3
0
bool rational_fitter_parallel::fit_data(const ptr<data>& dat, ptr<function>& fit, const arguments &args)
{
  ptr<rational_function> r = dynamic_pointer_cast<rational_function>(fit) ;
  if(!r)
  {
    std::cerr << "<<ERROR>> not passing the correct function class to the fitter: must be a rational_function" << std::endl ;
    return false ;
  }

  ptr<vertical_segment> d = dynamic_pointer_cast<vertical_segment>(dat) ;
  if(!d
     || d->confidence_interval_kind() != vertical_segment::ASYMMETRICAL_CONFIDENCE_INTERVAL)
  {
    std::cerr << "<<WARNING>> automatic convertion of the data object to vertical_segment," << std::endl;
    std::cerr << "<<WARNING>> we advise you to perform convertion with a separate command." << std::endl;

    size_t elem_size =
        dat->parametrization().dimX() + 3*dat->parametrization().dimY();
    double* content = new double[dat->size() * elem_size];

    for(int i=0; i<dat->size(); ++i)
    {
      const vec x = dat->get(i);

      for(int k=0; k<x.size(); ++k) {
          content[i + k] = x[k];
      }
      for(int k=0; k<dat->parametrization().dimY(); ++k) {
          content[i + k + dat->parametrization().dimX() + dat->parametrization().dimY()] =
              (1.0 - args.get_float("dt", 0.1)) * x[k + dat->parametrization().dimX()];
      }
      for(int k=0; k<dat->parametrization().dimY(); ++k) {
          content[i + k + dat->parametrization().dimX() + 2*dat->parametrization().dimY()] =
              (1.0 + args.get_float("dt", 0.1)) * x[k + dat->parametrization().dimX()];
      }
    }

    ptr<vertical_segment> vs(new vertical_segment(dat->parametrization(),
                                                  dat->size(),
                                                  std::shared_ptr<double>(content)));

    d = vs;
  }

  // XXX: FIT and D may have different values of dimX() and dimY(), but
  // this is fine: we convert values as needed in operator().
  r->setMin(d->min());
  r->setMax(d->max());

  const int _min_np = args.get_int("min-np", 10);
  const int _max_np = args.get_int("np", _min_np);
  std::cout << "<<INFO>> N in  [" << _min_np << ", " << _max_np << "]"  << std::endl ;

  const int nb_starting_points = args.get_int("nb-starting-points", 100);
  std::cout << "<<INFO>> number of data point used in start: " << nb_starting_points << std::endl;

  const int  step      = args.get_int("np-step", 1);
  const bool use_delta = args.is_defined("use_delta");

  for(int i=_min_np; i<=_max_np; i+=step)
  {
    std::cout << "<<INFO>> fit using np+nq = " << i << std::endl ;
    std::cout.flush() ;
    timer time ;
    time.start() ;

#ifdef _OPENMP
      const int nb_cores = args.get_int("nb-cores", omp_get_num_procs());
#ifdef DEBUG
    std::cout << "<<DEBUG>> will use " << nb_cores << " threads to compute the quadratic programs" << std::endl ;
#endif

    omp_set_num_threads(nb_cores) ;
#endif

    double min_delta   = std::numeric_limits<double>::max();
    double min_l2_dist = std::numeric_limits<double>::max();
    double mean_delta = 0.0;
    int nb_sol_found  = 0;
    int nb_sol_tested = 0;

    #pragma omp parallel for shared(r, args, nb_sol_found, nb_sol_tested, min_delta, mean_delta), schedule(dynamic,1)
    for(int j=1; j<i; ++j)
    {
      // Compute the number of coefficients in the numerator and in the denominator
      // from the current number of coefficients i and the current index in the
      // loop j.
      int temp_np = i - j;
      int temp_nq = j;

      //vec p(temp_np*r->dimY()), q(temp_nq*r->dimY());

      // Allocate a rational function and set it to the correct size, dimensions
      // and parametrizations.
      ptr<rational_function> rk(NULL);
      #pragma omp critical (args)
      {
        rk = dynamic_pointer_cast<rational_function>(
            ptr<function>(plugins_manager::get_function(args,
                                                        r->parametrization())));
      }
      if(!rk)
      {
          std::cerr << "<<ERROR>> unable to obtain a rational function from the plugins manager" << std::endl;
          throw;
      }

      rk->setMin(r->min()) ;
      rk->setMax(r->max()) ;

      // Set the rational function size
      rk->setSize(temp_np, temp_nq);

      double delta = 1.0;
      double linf_dist, l2_dist;
      bool is_fitted = fit_data(d, temp_np, temp_nq, rk, args, delta, linf_dist, l2_dist);
      if(is_fitted)
      {
        #pragma omp critical (r)
        {
          ++nb_sol_found ;
          mean_delta += delta ;

          std::cout << "<<INFO>> found a solution with np=" << temp_np
            << ", nq = " << temp_nq << std::endl;
          std::cout << "<<INFO>> Linf error = " << linf_dist << std::endl;
          std::cout << "<<INFO>> L2   error = " << l2_dist << std::endl;
          std::cout << "<<INFO>>      delta = " << delta << std::endl;
          std::cout << std::endl;

          // Get the solution with the minimum delta or the minimum L2 distance,
          // and update the main rational function r.
          if((use_delta && delta < min_delta) || (!use_delta && l2_dist < min_l2_dist))
          {
            min_delta   = delta ;
            min_l2_dist = l2_dist ;
            r->setSize(temp_np, temp_nq);
            r->update(rk);
          }
        }
      }

      #pragma omp critical (nb_sol_tested)
      {
        // Update the solution
        nb_sol_tested++;

        std::cout << "<<DEBUG>> nb solutions tested: " << nb_sol_tested << " / " << i << "\r";
        std::cout.flush();
      }
    }

    if(min_delta < std::numeric_limits<double>::max())
    {
      std::cout << "<<INFO>> mean delta = " << mean_delta/nb_sol_found << std::endl;
      std::cout << "<<INFO>>  min delta = " << min_delta << std::endl;
      std::cout << *(r.get()) << std::endl;

      time.stop();
      std::cout << "<<INFO>> got a fit using N = " << i << std::endl ;
      std::cout << "<<INFO>> it took " << time << std::endl ;
      std::cout << "<<INFO>> I got " << nb_sol_found << " solutions to the QP" << std::endl ;
      return true ;
    }
  }

  return false ;
}
示例#4
0
// dat is the data object, it contains all the points to fit
// np and nq are the degree of the RP to fit to the data
// y is the dimension to fit on the y-data (e.g. R, G or B for RGB signals)
// the function returns a rational BRDF function and a boolean
bool rational_fitter_parallel::fit_data(const ptr<vertical_segment>& d, int np, int nq, int ny,
                                        rational_function_1d* r, const arguments& args,
                                        vec& p, vec& q, double& delta)
{
  const int m = d->size(); // 2*m = number of constraints
  const int n = np+nq;     // n = np+nq

  quadratic_program qp(np, nq, args.is_defined("use_delta"));

  // Starting with only a nb_starting_points vertical segments
  std::list<unsigned int> training_set;
  const int di = std::max((m-1) / (nb_starting_points-1), 1);
  for(int i=0; i<m; ++i)
  {
    if(i % di == 0)
    {
        // Create two vector of constraints
        vec c1(n), c2(n);
        get_constraint(i, np, nq, ny, d, r, c1, c2);

        qp.add_constraints(c1);
        qp.add_constraints(c2);

    }
    else
    {
        training_set.push_back(i);
    }
  }
  qp.set_training_set(training_set);

  do
  {
#ifdef _OPENMP
#ifdef DEBUG
        std::cout << "<<DEBUG>> thread " << omp_get_thread_num() << ", number of intervals tested = " << qp.nb_constraints()/2 << std::endl ;
#endif
#endif
    Eigen::VectorXd x(n);
    bool solves_qp = qp.solve_program(x, delta, p, q);
    r->update(p, q);

    if(solves_qp)
    {
      if(qp.test_constraints(ny, r, d))
      {
#ifdef DEBUG
        std::cout << "<<INFO>> got solution " << *r << std::endl ;
#endif
        return true;
      }
    }
    else
    {
#ifdef DEBUG
      std::cout << "<<DEBUG>> not enough coefficients" << std::endl;
#endif
      return false;
    }
  } while(qp.nb_constraints() < 2*m);

  return false;
}