X-Git-Url: https://www.fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=pom.git;a=blobdiff_plain;f=pom_solver.cc;fp=pom_solver.cc;h=76cc9a5cc3f1b0bb928bee4bf1784bd799f180e1;hp=0000000000000000000000000000000000000000;hb=97a7e68f234cc09807d2d55f550e2516be0e9093;hpb=48c9926a2ed03737a3b024a85cda348caebf4cfe diff --git a/pom_solver.cc b/pom_solver.cc new file mode 100644 index 0000000..76cc9a5 --- /dev/null +++ b/pom_solver.cc @@ -0,0 +1,143 @@ + +////////////////////////////////////////////////////////////////////////////////// +// This program is free software: you can redistribute it and/or modify // +// it under the terms of the version 3 of the GNU General Public License // +// as published by the Free Software Foundation. // +// // +// 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 . // +// // +// Written by Francois Fleuret // +// (C) Ecole Polytechnique Federale de Lausanne // +// Contact for comments & bug reports // +////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +using namespace std; + +#include "pom_solver.h" +#include "global.h" + +////////////////////////////////////////////////////////////////////// + +POMSolver::POMSolver(Room *room) : neg(room->view_width(), room->view_height()), + neg_view(room->view_width(), room->view_height()), + ii_neg(room->view_width(), room->view_height()), + ii_neg_view(room->view_width(), room->view_height()) { + global_difference.set(global_mu_image_density, global_sigma_image_density); +} + +////////////////////////////////////////////////////////////////////// + +void POMSolver::compute_average_images(int camera, + Room *room, + Vector *proba_absence) { + neg.fill(1.0); + + for(int n = 0; n < room->nb_positions(); n++) if((*proba_absence)[n] <= global_proba_ignored) { + Rectangle *r = room->avatar(camera, n); + if(r->visible) + neg.multiply_subarray(r->xmin, r->ymin, r->xmax + 1, r->ymax + 1, (*proba_absence)[n]); + } +} + +////////////////////////////////////////////////////////////////////// + +void POMSolver::add_log_ratio(int camera, + Room *room, + ProbaView *view, + Vector *proba_absence, + Vector *sum) { + + // Computes the average on the complete picture + + compute_average_images(camera, room, proba_absence); + + double s = ii_neg.compute_sum(&neg); + double sv = ii_neg_view.compute_sum(&neg, view); + + scalar_t noise_proba = 0.01; // 1% of the scene can remain unexplained + scalar_t average_surface = room->view_width() * room->view_height() * (1 + noise_proba) - s; + scalar_t average_diff = average_surface + sv; + + // Cycles throw all positions and adds the log likelihood ratio to + // the total sum for each + + for(int i = 0; i < room->nb_positions(); i++) { + Rectangle *r = room->avatar(camera, i); + if(r->visible) { + scalar_t lambda = 1 - 1/(*proba_absence)[i]; + + scalar_t integral_neg = ii_neg.integral(r->xmin, r->ymin, r->xmax + 1, r->ymax + 1); + scalar_t average_surface_givpre = average_surface + integral_neg; + scalar_t average_surface_givabs = average_surface + lambda * integral_neg; + + scalar_t integral_neg_view = ii_neg_view.integral(r->xmin, r->ymin, r->xmax + 1, r->ymax + 1); + scalar_t average_diff_givpre = average_diff + integral_neg - 2 * integral_neg_view; + scalar_t average_diff_givabs = average_diff + lambda * (integral_neg - 2 * integral_neg_view); + + scalar_t log_mu0 = global_difference.log_proba(average_diff_givabs / average_surface_givabs); + scalar_t log_mu1 = global_difference.log_proba(average_diff_givpre / average_surface_givpre); + + (*sum)[i] += log_mu1 - log_mu0; + + } + } +} + +void POMSolver::solve(Room *room, + Vector *prior, + Vector *views, + Vector *proba_presence, + int nb_frame, + char *convergence_file_format) { + + Vector log_prior_ratio(prior->length()); + + Vector sum(room->nb_positions()); + Vector proba_absence(room->nb_positions()); + + for(int i = 0; i < room->nb_positions(); i++) { + log_prior_ratio[i] = log((*prior)[i]/(1 - (*prior)[i])); + proba_absence[i] = 1 - (*prior)[i]; + } + + int nb_stab = 0; + + for(int it = 0; (nb_stab < global_nb_stable_error_for_convergence) && (it < global_max_nb_solver_iterations); it++) { + + sum.clear(); + for(int c = 0; c < room->nb_cameras(); c++) + add_log_ratio(c, room, (*views)[c], &proba_absence, &sum); + + scalar_t e = 0; + for(int i = 0; i < room->nb_positions(); i++) { + scalar_t np = global_smoothing_coefficient * proba_absence[i] + (1 - global_smoothing_coefficient) / (1 + exp(log_prior_ratio[i] + sum[i])); + if(abs(proba_absence[i] - np) > e) e = abs(proba_absence[i] - np); + proba_absence[i] = np; + } + + if(e < global_error_max) nb_stab++; else nb_stab = 0; + + if(convergence_file_format) { + char buffer[buffer_size]; + for(int p = 0; p < room->nb_positions(); p++) (*proba_presence)[p] = 1 - proba_absence[p]; + for(int c = 0; c < room->nb_cameras(); c++) { + pomsprintf(buffer, buffer_size, convergence_file_format, c, nb_frame, it); + cout << "Saving " << buffer << "\n"; cout.flush(); + room->save_stochastic_view(buffer, c, (*views)[c], proba_presence); + } + } + + } + + for(int p = 0; p < room->nb_positions(); p++) (*proba_presence)[p] = 1 - proba_absence[p]; +}