fattal: optimized memory usage

This commit is contained in:
heckflosse
2017-12-07 22:51:19 +01:00
parent 58c9f5a4da
commit a633f3d233

View File

@@ -69,7 +69,7 @@
#include "improcfun.h"
#include "settings.h"
#include "iccstore.h"
//#define BENCHMARK
#define BENCHMARK
#include "StopWatch.h"
#include "sleef.c"
#include "opthelper.h"
@@ -233,18 +233,12 @@ void gaussianBlur (const Array2Df& I, Array2Df& L, bool multithread)
}
}
void createGaussianPyramids ( Array2Df* H, Array2Df** pyramids, int nlevels, bool multithread)
void createGaussianPyramids (Array2Df** pyramids, int nlevels, bool multithread)
{
int width = H->getCols();
int height = H->getRows();
const int size = width * height;
// pyramids[0] is already set
int width = pyramids[0]->getCols();
int height = pyramids[0]->getRows();
pyramids[0] = new Array2Df (width, height);
//#pragma omp parallel for shared(pyramids, H)
for ( int i = 0 ; i < size ; i++ ) {
(*pyramids[0]) (i) = (*H) (i);
}
Array2Df* L = new Array2Df (width, height);
gaussianBlur ( *pyramids[0], *L, multithread );
@@ -531,77 +525,54 @@ void tmo_fattal02 (size_t width,
/** RT */
// create gaussian pyramids
// int mins = (width<height) ? width : height; // smaller dimension
// int nlevels = 0;
// while ( mins >= MSIZE )
// {
// nlevels++;
// mins /= 2;
// }
// // std::cout << "DEBUG: nlevels = " << nlevels << ", mins = " << mins << std::endl;
// // The following lines solves a bug with images particularly small
// if (nlevels == 0) nlevels = 1;
const int nlevels = 7; // RT -- see above
Array2Df** pyramids = new Array2Df*[nlevels];
createGaussianPyramids (H, pyramids, nlevels, multithread);
// ph.setValue(8);
Array2Df* pyramids[nlevels];
pyramids[0] = H;
createGaussianPyramids (pyramids, nlevels, multithread);
// calculate gradients and its average values on pyramid levels
Array2Df** gradients = new Array2Df*[nlevels];
float* avgGrad = new float[nlevels];
Array2Df* gradients[nlevels];
float avgGrad[nlevels];
for ( int k = 0 ; k < nlevels ; k++ ) {
gradients[k] = new Array2Df (pyramids[k]->getCols(), pyramids[k]->getRows());
avgGrad[k] = calculateGradients (pyramids[k], gradients[k], k, multithread);
if(k != 0) // pyramids[0] is H. Will be deleted later
delete pyramids[k];
}
delete[] pyramids;
// ph.setValue(12);
// calculate fi matrix
Array2Df* FI = new Array2Df (width, height);
calculateFiMatrix (FI, gradients, avgGrad, nlevels, detail_level, alfa, beta, noise, multithread);
// dumpPFS( "FI.pfs", FI, "Y" );
for ( int i = 0 ; i < nlevels ; i++ ) {
delete gradients[i];
}
delete[] gradients;
delete[] avgGrad;
// ph.setValue(16);
// if (ph.canceled()){
// delete FI;
// delete H;
// return;
// }
/** - RT - bring back the FI image to the input size if it was downscaled */
if (fullH) {
delete H;
H = fullH;
Array2Df *FI2 = new Array2Df (fullwidth, fullheight);
rescale_bilinear (*FI, *FI2, multithread);
delete FI;
FI = FI2;
width = fullwidth;
height = fullheight;
delete H;
H = fullH;
}
/** RT */
// attenuate gradients
Array2Df* Gx = new Array2Df (width, height);
Array2Df* Gy = new Array2Df (width, height);
Array2Df* Gy = &L; // use L as buffer for Gy
// the fft solver solves the Poisson pde but with slightly different
// boundary conditions, so we need to adjust the assembly of the right hand
// side accordingly (basically fft solver assumes U(-1) = U(1), whereas zero
// Neumann conditions assume U(-1)=U(0)), see also divergence calculation
// if (fftsolver)
#pragma omp parallel for if(multithread)
for ( size_t y = 0 ; y < height ; y++ ) {
@@ -634,8 +605,6 @@ void tmo_fattal02 (size_t width,
(*FI) (x, y) -= (*Gy) (x, y - 1);
}
// if (fftsolver)
{
if (x == 0) {
(*FI) (x, y) += (*Gx) (x, y);
}
@@ -643,35 +612,20 @@ void tmo_fattal02 (size_t width,
if (y == 0) {
(*FI) (x, y) += (*Gy) (x, y);
}
}
}
}
//delete Gx; // RT - reused as temp buffer in solve_pde_fft, deleted later
delete Gy;
// solve pde and exponentiate (ie recover compressed image)
{
// if (fftsolver)
{
MyMutex::MyLock lock (*fftwMutex);
solve_pde_fft (FI, &L, Gx, multithread); //, ph);
solve_pde_fft (FI, &L, Gx, multithread);
}
delete Gx;
delete FI;
// else
// {
// solve_pde_multigrid(&DivG, &U, ph);
// }
// #ifndef NDEBUG
// printf("\npde residual error: %f\n", residual_pde(&U, &DivG));
// #endif
// ph.setValue(90);
// if ( ph.canceled() )
// {
// return;
// }
#pragma omp parallel if(multithread)
{
#ifdef __SSE2__
@@ -694,8 +648,6 @@ void tmo_fattal02 (size_t width,
}
}
}
}
// ph.setValue(95);
// remove percentile of min and max values and renormalize
float cut_min = 0.01f * black_point;
@@ -759,31 +711,6 @@ void tmo_fattal02 (size_t width,
// atimes(). This means the assembly of the right hand side F is different
// for both solvers.
// #include <iostream>
// #include <boost/math/constants/constants.hpp>
// #include <stdio.h>
// #include <stdlib.h>
// #include "arch/math.h"
// #include <cassert>
// #ifdef _OPENMP
// #include <omp.h>
// #endif
// #include <vector>
// #include <fftw3.h>
// #include "Libpfs/progress.h"
// #include "Libpfs/array2d.h"
// #include "pde.h"
// using namespace std;
// #ifndef SQR
// #define SQR(x) (x)*(x)
// #endif
// returns T = EVy A EVx^tr
// note, modifies input data
@@ -955,23 +882,13 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/*
// transforms F into eigenvector space: Ftr =
//DEBUG_STR << "solve_pde_fft: transform F to ev space (fft)" << std::endl;
Array2Df* F_tr = buf; //new Array2Df(width,height);
Array2Df* F_tr = buf;
transform_normal2ev (F, F_tr, multithread);
// TODO: F no longer needed so could release memory, but as it is an
// input parameter we won't do that
// ph.setValue(50);
// if (ph.canceled())
// {
// delete F_tr;
// return;
// }
//DEBUG_STR << "solve_pde_fft: F_tr(0,0) = " << (*F_tr)(0,0);
//DEBUG_STR << " (must be 0 for solution to exist)" << std::endl;
// in the eigenvector space the solution is very simple
//DEBUG_STR << "solve_pde_fft: solve in eigenvector space" << std::endl;
// Array2Df* U_tr = new Array2Df(width,height);
std::vector<double> l1 = get_lambda (height);
std::vector<double> l2 = get_lambda (width);
@@ -985,10 +902,8 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/*
(*F_tr) (0, 0) = 0.f; // any value ok, only adds a const to the solution
// transforms U_tr back to the normal space
//DEBUG_STR << "solve_pde_fft: transform U_tr to normal space (fft)" << std::endl;
// transforms F_tr back to the normal space
transform_ev2normal (F_tr, U, multithread);
// delete F_tr; // no longer needed so release memory
// the solution U as calculated will satisfy something like int U = 0
// since for any constant c, U-c is also a solution and we are mainly