double e2data_multi_gauss(double x, double beta1, double t1, double beta2, double t2, double a, int N = 1000) { double xa,xb,xi,step; // a2 = 1.0 - a; // xb = 8.0/(beta*beta); xb = 100.0; xa = -xb; step = (xb - xa)/N; double e2 = 0.0; for(int i = 0; i <= N; i++) { xi = xa + i * step; e2 += (a*GAUSS((t1 - xi),beta1) + (1.0-a) * GAUSS((t2 - xi),beta2)) *e2data(x-xi); } e2 *= step; return e2; }
double e2datagauss_exakt(double x, double beta, int N = 1000) { double xa,xb,xi,step; xb = 8.0/(beta*beta); xa = -xb; step = (xb - xa)/N; double e2 = 0.0; for(int i = 0; i <= N; i++) { xi = xa + i * step; e2 += GAUSS(xi,beta)*e2data(x-xi); } e2 *= step; return e2; }
double e2datagauss(double x, double beta, int N = 10000) { double xa,xb,xi,step,nu; // xb = 8.0/(beta*beta); xb = 10.0; xa = -xb; step = (xb - xa)/N; // nu = Xi4double(x); nu = 0.0; double e2 = 0.0; for(int i = 0; i <= N; i++) { xi = xa + i * step; e2 += GAUSS(xi,beta)*e2data(x-xi); } e2 *= step; // e2 *= (1.0 + 0.01 * nu); return e2; }
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out) { dt_iop_relight_data_t *data = (dt_iop_relight_data_t *)piece->data; const int ch = piece->colors; // Precalculate parameters for gauss function const float a = 1.0; // Height of top const float b = -1.0+(data->center*2); // Center of top const float c = (data->width/10.0)/2.0; // Width #ifdef _OPENMP #pragma omp parallel for default(none) shared(roi_out, ivoid, ovoid, data) schedule(static) #endif for(int k=0; k<roi_out->height; k++) { float *in = ((float *)ivoid) + ch*k*roi_out->width; float *out = ((float *)ovoid) + ch*k*roi_out->width; for(int j=0; j<roi_out->width; j++,in+=ch,out+=ch) { const float lightness = in[0]/100.0; const float x = -1.0+(lightness*2.0); float gauss = GAUSS(a,b,c,x); if(isnan(gauss) || isinf(gauss)) gauss = 0.0; float relight = 1.0 / exp2f ( -data->ev * CLIP(gauss)); if(isnan(relight) || isinf(relight)) relight = 1.0; out[0] = 100.0*CLIP (lightness*relight); out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; } } }
PPMImage PerformAA(const PPMImage& original, const PPMImage& filtered) { NetPBMLoader loader; PPMImage recovered(original.getLength(), original.getWidth()); PPMImage maxVarDir(original.getLength(), original.getWidth()); PPMImage sobel(original.getLength(), original.getWidth()); for(int i = 0; i < recovered.getLength(); ++i) { for(int j = 0; j < recovered.getWidth(); ++j) { // don't treat border pixels if(i == 0 || j == 0 || i == recovered.getLength()-1 || j == recovered.getWidth()-1) { recovered(i,j) = filtered(i,j); continue; } PPMImage neighbors(3,3); PPMImage neighborsAliased(3,3); Vector3D pixel = original(i,j); Vector3D pixelAlias = filtered(i,j); // colors are changing most rapidly considering this direction Vector3D varDir; // the distance vector from the average value of neighbors Vector3D dAverage[9]; // the average value computed considering the neighbors Vector3D average; // parameters to compute recovery float alpha = 0; float beta = 0; float dp = 0; float Gd = 0; float ep = 0; float Ge = 0; // construct neighbors of aliased and original images for(int k = i-1; k <= i+1; ++k) { for(int l = j-1; l <= j+1; ++l) { neighbors((k-i)+1, (l-j)+1) = original(k,l); neighborsAliased((k-i)+1, (l-j)+1) = filtered(k,l); } } // compute the average for(int k = 0; k < neighbors.getLength(); ++k) { for(int l = 0; l < neighbors.getWidth(); ++l) { average += neighbors(k,l); } } average /= neighbors.getSize(); // compute the distance from the average color value for(int k = 0; k < neighbors.getLength(); ++k) { for(int l = 0; l < neighbors.getWidth(); ++l) { dAverage[k*neighbors.getLength()+l] = neighbors(k,l) - average; } } varDir = Vector3D(average.normalize() + EPSILON); EM(dAverage, 3, varDir, neighbors.getSize()); Vector2D maxColorPos; Vector2D minColorPos; // compute the two maximum colors along the straight line directed by varDir if(ExtremeColors(neighbors, varDir, maxColorPos, minColorPos)) { Vector3D ca = neighbors(minColorPos.x, minColorPos.y); Vector3D cb = neighbors(maxColorPos.x, maxColorPos.y); Vector3D cacb = cb - ca; Vector3D d; alpha = (pixel - ca).dot(cacb) / cacb.dot(cacb); d = pixel - (alpha * cacb) - ca; dp = d.length(); Gd = GAUSS(dp, SIGMA_D); } float eo = Sobel(neighbors); float ef = Sobel(neighborsAliased); ep = ef * eo; Ge = GAUSS(ep, SIGMA_E); Vector3D cbAliased = neighborsAliased(maxColorPos.x, maxColorPos.y); Vector3D caAliased = neighborsAliased(minColorPos.x, minColorPos.y); beta = Gd * (1- Ge); // final composition recovered(i,j) = beta * (caAliased * (1-alpha) + cbAliased * alpha) + (1-beta) * pixelAlias; maxVarDir(i,j) = varDir * 255; sobel(i,j) = Vector3D(sqrt(eo)); } } loader.savePPM(maxVarDir, "max_variance_direction"); loader.savePPM(sobel, "sobel"); return recovered; }