Green channel equilibration algorithm, for cameras such as Olympus, Panasonic, Canon 7D, etc that have different properties for the G1/G2 channels of the Bayer color filter array. In addition, minor changes to line denoise and CA_correct.
This commit is contained in:
parent
7367521feb
commit
d6ae133924
@ -369,6 +369,8 @@ PREFERENCES_CACORRECTION;Apply CA auto correction
|
||||
PREFERENCES_HOTDEADPIXFILT;Apply hot/dead pixel filter
|
||||
#Emil's line noise filter
|
||||
PREFERENCES_LINEDENOISE;Line noise filter
|
||||
PREFERENCES_GREENEQUIL;Green equilibration
|
||||
|
||||
PREFERENCES_DEFAULTLANG;Default language
|
||||
PREFERENCES_DEFAULTTHEME;Default theme
|
||||
PREFERENCES_DEMOSAICINGALGO;Demosaicing Algorithm
|
||||
|
@ -371,6 +371,8 @@ PREFERENCES_CACORRECTION;Apply CA auto correction
|
||||
PREFERENCES_HOTDEADPIXFILT;Apply hot/dead pixel filter
|
||||
#Emil's line noise filter
|
||||
PREFERENCES_LINEDENOISE;Line noise filter
|
||||
PREFERENCES_GREENEQUIL;Green equilibration
|
||||
|
||||
PREFERENCES_DEFAULTLANG;Default language
|
||||
PREFERENCES_DEFAULTTHEME;Default theme
|
||||
PREFERENCES_DEMOSAICINGALGO;Demosaicing Algorithm
|
||||
|
@ -320,10 +320,10 @@ void RawImageSource::CA_correct_RT() {
|
||||
for (cc=4+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < cc1-4; cc+=2, indx+=2) {
|
||||
|
||||
|
||||
rbhpfv[indx] = fabs(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])) + \
|
||||
rbhpfv[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])) + \
|
||||
fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx][1]-rgb[indx][c])) - \
|
||||
fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])));
|
||||
rbhpfh[indx] = fabs(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+4][1]-rgb[indx+4][c])) + \
|
||||
rbhpfh[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+4][1]-rgb[indx+4][c])) + \
|
||||
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - \
|
||||
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c])));
|
||||
|
||||
@ -358,7 +358,7 @@ void RawImageSource::CA_correct_RT() {
|
||||
gdiff=0.3125*(rgb[indx+TS][1]-rgb[indx-TS][1])+0.09375*(rgb[indx+TS+1][1]-rgb[indx-TS+1][1]+rgb[indx+TS-1][1]-rgb[indx-TS-1][1]);
|
||||
deltgrb=(rgb[indx][c]-rgb[indx][1]);
|
||||
|
||||
gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) )*(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]);
|
||||
gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) );//*(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]);
|
||||
|
||||
coeff[0][0][c] += gradwt*deltgrb*deltgrb;
|
||||
coeff[0][1][c] += gradwt*gdiff*deltgrb;
|
||||
@ -370,7 +370,7 @@ void RawImageSource::CA_correct_RT() {
|
||||
gdiff=0.3125*(rgb[indx+1][1]-rgb[indx-1][1])+0.09375*(rgb[indx+1+TS][1]-rgb[indx-1+TS][1]+rgb[indx+1-TS][1]-rgb[indx-1-TS][1]);
|
||||
deltgrb=(rgb[indx][c]-rgb[indx][1]);
|
||||
|
||||
gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) )*(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]);
|
||||
gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) );//*(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]);
|
||||
|
||||
coeff[1][0][c] += gradwt*deltgrb*deltgrb;
|
||||
coeff[1][1][c] += gradwt*gdiff*deltgrb;
|
||||
@ -502,7 +502,7 @@ void RawImageSource::CA_correct_RT() {
|
||||
//if (verbose) fprintf (stderr,_("tile vshift hshift (%d %d %4f %4f)...\n"),vblock, hblock, blockshifts[(vblock)*hblsz+hblock][c][0], blockshifts[(vblock)*hblsz+hblock][c][1]);
|
||||
|
||||
|
||||
//now prepare coefficient matrix
|
||||
//now prepare coefficient matrix; use only data points within two std devs of zero
|
||||
if (SQR(blockshifts[(vblock)*hblsz+hblock][c][0])>4.0*blockvar[0][c] || SQR(blockshifts[(vblock)*hblsz+hblock][c][1])>4.0*blockvar[1][c]) continue;
|
||||
numblox[c] += 1;
|
||||
for (dir=0; dir<2; dir++) {
|
||||
@ -520,13 +520,11 @@ void RawImageSource::CA_correct_RT() {
|
||||
}//blocks
|
||||
|
||||
numblox[1]=MIN(numblox[0],numblox[2]);
|
||||
//if (numblox[1]<72) {
|
||||
// polyord=4; numpar=16;
|
||||
//if too few data points, restrict the order of the fit to linear
|
||||
if (numblox[1]<32) {
|
||||
polyord=2; numpar=4;
|
||||
if (numblox[1]< 10) return;
|
||||
}
|
||||
//}
|
||||
|
||||
//fit parameters to blockshifts
|
||||
for (c=0; c<3; c+=2)
|
||||
@ -536,7 +534,7 @@ void RawImageSource::CA_correct_RT() {
|
||||
for (i=0; i<numpar; i++) fitparams[c][dir][i]=0;
|
||||
}
|
||||
}
|
||||
//fitparams[5*i+j] gives the coefficients of (vblock^i hblock^j) in a polynomial fit for i,j<=4
|
||||
//fitparams[polyord*i+j] gives the coefficients of (vblock^i hblock^j) in a polynomial fit for i,j<=4
|
||||
|
||||
//end of initialization for CA correction pass
|
||||
|
||||
|
@ -59,8 +59,8 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
{
|
||||
// local variables
|
||||
int height=H, width=W;
|
||||
int top, bottom, left, right, row, col;
|
||||
int rr, cc, rr1, cc1, c, indx, i, j;
|
||||
int top, left, row, col;
|
||||
int rr, cc, indx, i, j;
|
||||
int ex, ey;
|
||||
int verbose=1;
|
||||
|
||||
@ -74,11 +74,13 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
float aarr[8][8], *dctblock[8];
|
||||
for (i = 0; i < 8; i++) dctblock[i] = aarr[i];
|
||||
|
||||
/*
|
||||
char *buffer; // TS*TS*16
|
||||
float (*cfain); // TS*TS*4
|
||||
float (*cfablur); // TS*TS*4
|
||||
float (*cfadiff); // TS*TS*4
|
||||
float (*cfadn); // TS*TS*4
|
||||
*/
|
||||
|
||||
double dt;
|
||||
clock_t t1, t2;
|
||||
@ -89,17 +91,23 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
//if (verbose) fprintf (stderr,_("CFA line denoise ...\n"));
|
||||
//t1 = clock();
|
||||
|
||||
|
||||
/*
|
||||
// assign working space
|
||||
buffer = (char *) malloc(16*TS*TS);
|
||||
buffer = (char *) malloc(4*TS*TS*sizeof(float));
|
||||
//merror(buffer,"cfa_linedn()");
|
||||
memset(buffer,0,16*TS*TS);
|
||||
memset(buffer,0,4*TS*TS*sizeof(float));
|
||||
// rgb array
|
||||
cfain = (float (*)) buffer; //pointers to rows of array
|
||||
cfablur = (float (*)) (buffer + 4*TS*TS);
|
||||
cfadiff = (float (*)) (buffer + 8*TS*TS);
|
||||
cfadn = (float (*)) (buffer + 12*TS*TS);
|
||||
|
||||
*/
|
||||
/*
|
||||
float cfain[TS*TS];
|
||||
float cfablur[TS*TS];
|
||||
float cfadiff[TS*TS];
|
||||
float cfadn[TS*TS];
|
||||
*/
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
@ -118,49 +126,53 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
// Main algorithm: Tile loop
|
||||
for (top=0; top < height-16; top += TS-32)
|
||||
for (left=0; left < width-16; left += TS-32) {
|
||||
bottom = MIN( top+TS,height);
|
||||
right = MIN(left+TS, width);
|
||||
rr1 = bottom - top;
|
||||
cc1 = right - left;
|
||||
int bottom = MIN( top+TS,height);
|
||||
int right = MIN(left+TS, width);
|
||||
int numrows = bottom - top;
|
||||
int numcols = right - left;
|
||||
|
||||
float cfain[TS*TS];
|
||||
float cfablur[TS*TS];
|
||||
float cfadiff[TS*TS];
|
||||
float cfadn[TS*TS];
|
||||
|
||||
// load CFA data; data should be in linear gamma space, before white balance multipliers are applied
|
||||
for (rr=0; rr < rr1; rr++)
|
||||
for (row=rr+top, cc=0, indx=rr*TS+cc; cc < cc1; cc++, indx++) {
|
||||
col = cc+left;
|
||||
c = FC(rr,cc);
|
||||
cfain[indx] = ri->data[row][col];
|
||||
for (rr=top; rr < top+numrows; rr++)
|
||||
for (cc=left, indx=(rr-top)*TS; cc < left+numcols; cc++, indx++) {
|
||||
cfain[indx] = ri->data[rr][cc];
|
||||
}
|
||||
//pad the block to a multiple of 16 on both sides
|
||||
|
||||
if (cc1 < TS) {
|
||||
indx=cc1 % 16;
|
||||
if (numcols < TS) {
|
||||
indx=numcols % 16;
|
||||
for (i=0; i<(16-indx); i++)
|
||||
for (rr=0; rr<rr1; rr++)
|
||||
cfain[(rr)*TS+cc1+i+1]=cfain[(rr)*TS+cc1-i];
|
||||
cc1 += 16-indx;
|
||||
for (rr=0; rr<numrows; rr++)
|
||||
cfain[(rr)*TS+numcols+i+1]=cfain[(rr)*TS+numcols-i];
|
||||
numcols += 16-indx;
|
||||
}
|
||||
|
||||
if (rr1 < TS) {
|
||||
indx=rr1 % 16;
|
||||
if (numrows < TS) {
|
||||
indx=numrows % 16;
|
||||
for (i=0; i<(16-indx); i++)
|
||||
for (cc=0; cc<cc1; cc++)
|
||||
cfain[(rr1+i+1)*TS+cc]=cfain[(rr1-i)*TS+cc];
|
||||
rr1 += 16-indx;
|
||||
for (cc=0; cc<numcols; cc++)
|
||||
cfain[(numrows+i+1)*TS+cc]=cfain[(numrows-i)*TS+cc];
|
||||
numrows += 16-indx;
|
||||
}
|
||||
|
||||
//The cleaning algorithm starts here
|
||||
|
||||
|
||||
//gaussian blur of CFA data
|
||||
for (rr=8; rr < rr1-8; rr++)
|
||||
for (cc=0, indx=rr*TS+cc; cc < cc1; cc++, indx++) {
|
||||
for (rr=8; rr < numrows-8; rr++)
|
||||
for (indx=rr*TS; indx < rr*TS+numcols; indx++) {
|
||||
|
||||
cfablur[indx]=gauss[0]*cfain[indx];
|
||||
for (i=1; i<5; i++) {
|
||||
cfablur[indx] += gauss[i]*(cfain[indx-(2*i)*TS]+cfain[indx+(2*i)*TS]);
|
||||
}
|
||||
}
|
||||
for (rr=8; rr < rr1-8; rr++)
|
||||
for (cc=8, indx=rr*TS+cc; cc < cc1-8; cc++, indx++) {
|
||||
for (rr=8; rr < numrows-8; rr++)
|
||||
for (indx=rr*TS+8; indx < rr*TS+numcols-8; indx++) {
|
||||
|
||||
cfadn[indx] = gauss[0]*cfablur[indx];
|
||||
for (i=1; i<5; i++) {
|
||||
@ -172,8 +184,8 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
//begin block DCT
|
||||
for (ey=0; ey<2; ey++) // (ex,ey) specify RGGB subarray
|
||||
for (ex=0; ex<2; ex++)
|
||||
for (rr=8+ey; rr < rr1-22; rr+=8) // (rr,cc) shift by 8 to overlap blocks
|
||||
for (cc=8+ex; cc < cc1-22; cc+=8) {
|
||||
for (rr=8+ey; rr < numrows-22; rr+=8) // (rr,cc) shift by 8 to overlap blocks
|
||||
for (cc=8+ex; cc < numcols-22; cc+=8) {
|
||||
//grab an 8x8 block of a given RGGB channel
|
||||
for (i=0; i<8; i++)
|
||||
for (j=0; j<8; j++) {
|
||||
@ -211,18 +223,18 @@ void RawImageSource::CLASS cfa_linedn(float noise)
|
||||
}
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
// copy smoothed results back to image matrix
|
||||
for (rr=16; rr < rr1-16; rr++)
|
||||
for (row=rr+top, cc=16, indx=rr*TS+cc; cc < cc1-16; cc++, indx++) {
|
||||
col = cc + left;
|
||||
for (rr=16; rr < numrows-16; rr++) {
|
||||
row = rr + top;
|
||||
for (col=16+left, indx=rr*TS+16; indx < rr*TS+numcols-16; indx++, col++) {
|
||||
ri->data[row][col] = CLIP((int)(cfadn[indx]+ 0.5));
|
||||
}
|
||||
}
|
||||
if(plistener) plistener->setProgress(fabs((float)top/height));
|
||||
}
|
||||
|
||||
// clean up
|
||||
free(buffer);
|
||||
//free(buffer);
|
||||
|
||||
// done
|
||||
/*t2 = clock();
|
||||
|
211
rtengine/green_equil_RT.cc
Normal file
211
rtengine/green_equil_RT.cc
Normal file
@ -0,0 +1,211 @@
|
||||
// CFA pixel cleaning via directional average
|
||||
// by Emil Martinec
|
||||
// 2/18/2010
|
||||
#define TS 256 // Tile size
|
||||
|
||||
#define CLASS
|
||||
/*#define ushort UshORt
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define SQR(x) ((x)*(x))
|
||||
|
||||
|
||||
//void CLASS green_equilibrate()//for dcraw implementation
|
||||
void CLASS RawImageSource::green_equilibrate(float thresh)
|
||||
{
|
||||
// local variables
|
||||
static const int border=8;
|
||||
static const int border2=16;
|
||||
static const int v1=TS, v2=2*TS, v3=3*TS, /*v4=4*TS,*/ p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3;
|
||||
|
||||
int height=H, width=W; //for RT only
|
||||
int top, left;
|
||||
|
||||
int verbose=1;
|
||||
|
||||
static const float eps=1.0; //tolerance to avoid dividing by zero
|
||||
//static const float thresh=0.03; //threshold for performing green equilibration; max percentage difference of G1 vs G2
|
||||
// G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched
|
||||
static const float diffthresh=0.25; //threshold for texture, not to be equilibrated
|
||||
|
||||
/*double dt;
|
||||
clock_t t1, t2;
|
||||
|
||||
//clock_t t1_main, t2_main = 0;
|
||||
|
||||
// start
|
||||
if (verbose) fprintf (stderr,_("Green equilibration ...\n"));
|
||||
t1 = clock();*/
|
||||
|
||||
|
||||
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
// Fill G interpolated values with border interpolation and input values
|
||||
// Main algorithm: Tile loop
|
||||
//#pragma omp parallel for shared(image,height,width) private(top,left) schedule(dynamic)
|
||||
|
||||
for (top=0; top < height-border; top += TS-border2)
|
||||
for (left=0; left < width-border; left += TS-border2) {
|
||||
int bottom = MIN( top+TS,height);
|
||||
int right = MIN(left+TS, width);
|
||||
int numrows = bottom - top;
|
||||
int numcols = right - left;
|
||||
|
||||
int row, col;
|
||||
int rr, cc, c, indx;
|
||||
int vote1, vote2;
|
||||
|
||||
float val1;
|
||||
|
||||
float gin, gse, gsw, gne, gnw, wtse, wtsw, wtne, wtnw;
|
||||
float gu, gd, gl, gr;
|
||||
float mcorr, pcorr;
|
||||
float ginterp;
|
||||
float diffvarh, diffvarv, hvwt;
|
||||
|
||||
char *buffer; // TS*TS*16
|
||||
float (*cfa); // TS*TS*4
|
||||
float (*checker); // TS*TS*4
|
||||
float (*gvar); // TS*TS*4
|
||||
float (*gdiffv); // TS*TS*4
|
||||
float (*gdiffh); // TS*TS*4
|
||||
|
||||
/* assign working space */
|
||||
buffer = (char *) malloc(5*sizeof(float)*TS*TS);
|
||||
//merror(buffer,"green_equil()");
|
||||
memset(buffer,0,5*sizeof(float)*TS*TS);
|
||||
|
||||
cfa = (float (*)) buffer;
|
||||
checker = (float (*)) (buffer + sizeof(float)*TS*TS);
|
||||
gvar = (float (*)) (buffer + 2*sizeof(float)*TS*TS);
|
||||
gdiffv = (float (*)) (buffer + 3*sizeof(float)*TS*TS);
|
||||
gdiffh = (float (*)) (buffer + 4*sizeof(float)*TS*TS);
|
||||
|
||||
/*float cfa[TS*TS];
|
||||
float checker[TS*TS]; //this memory allocation crashes RT
|
||||
float gvar[TS*TS];
|
||||
|
||||
memset( (void *)&cfa[0], 0 ,sizeof(cfa) );*/
|
||||
|
||||
// rgb from input CFA data
|
||||
/* rgb values should be floating point number between 0 and 1
|
||||
after white balance multipliers are applied */
|
||||
for (rr=0; rr < numrows; rr++)
|
||||
for (row=rr+top, cc=0; cc < numcols; cc++) {
|
||||
col = cc+left;
|
||||
//cfa[rr*TS+cc] = image[row*width+col][FC(row,col)];//for dcraw implementation
|
||||
cfa[rr*TS+cc] = ri->data[row][col];
|
||||
|
||||
}
|
||||
|
||||
//The green equilibration algorithm starts here
|
||||
|
||||
for (rr=2; rr < numrows-2; rr++)
|
||||
//for (cc=3-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-2; cc+=2, indx+=2) {
|
||||
for (indx=rr*TS+2; indx < rr*TS+numcols-2; indx++) {
|
||||
|
||||
if (FC(rr,indx)&1) {
|
||||
pcorr = (cfa[indx+p1]-cfa[indx])*(cfa[indx-p1]-cfa[indx]);
|
||||
mcorr = (cfa[indx+m1]-cfa[indx])*(cfa[indx-m1]-cfa[indx]);
|
||||
|
||||
if (pcorr>0 && mcorr>0) {checker[indx]=1;} else {checker[indx]=0;}
|
||||
|
||||
//checker[indx]=1;//test what happens if we always interpolate
|
||||
} else {
|
||||
gu=cfa[indx-v1]+0.5*(cfa[indx]-cfa[indx-v2]);
|
||||
gd=cfa[indx+v1]+0.5*(cfa[indx]-cfa[indx+v2]);
|
||||
gl=cfa[indx-1]+0.5*(cfa[indx]-cfa[indx-2]);
|
||||
gr=cfa[indx+1]+0.5*(cfa[indx]-cfa[indx+2]);
|
||||
|
||||
gdiffh[indx] = SQR((gl-gr)/(eps+gl+gr));
|
||||
gdiffv[indx] = SQR((gu-gd)/(eps+gu+gd));
|
||||
|
||||
//gvar[indx] = 0.25*(gu*gu+gd*gd+gl*gl+gr*gr)-SQR(0.25*(gu+gd+gl+gr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//now smooth the cfa data
|
||||
for (rr=6; rr < numrows-6; rr++)
|
||||
for (cc=7-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-6; cc+=2, indx+=2) {
|
||||
if (checker[indx]) {
|
||||
|
||||
diffvarh = eps+(gdiffh[indx-v1]+gdiffh[indx-1]+gdiffh[indx+1]+gdiffh[indx+v1]);
|
||||
diffvarv = eps+(gdiffv[indx-v1]+gdiffv[indx-1]+gdiffv[indx+1]+gdiffv[indx+v1]);
|
||||
hvwt = fabs(diffvarv-diffvarh)/(diffvarv+diffvarh);
|
||||
|
||||
|
||||
vote1=(checker[indx-v2]+checker[indx-2]+checker[indx+2]+checker[indx+v2]);
|
||||
vote2=(checker[indx-m1]+checker[indx+p1]+checker[indx-p1]+checker[indx+m1]);
|
||||
if (vote1>0 && vote2>0 && hvwt<diffthresh) {
|
||||
//pixel interpolation
|
||||
|
||||
gin=cfa[indx];
|
||||
|
||||
gse=(cfa[indx+m1])+0.5*(cfa[indx]-cfa[indx+m2]);
|
||||
gnw=(cfa[indx-m1])+0.5*(cfa[indx]-cfa[indx-m2]);
|
||||
gne=(cfa[indx+p1])+0.5*(cfa[indx]-cfa[indx+p2]);
|
||||
gsw=(cfa[indx-p1])+0.5*(cfa[indx]-cfa[indx-p2]);
|
||||
|
||||
|
||||
|
||||
wtse=1/(eps+SQR(cfa[indx+m2]-cfa[indx])+SQR(cfa[indx+m3]-cfa[indx+m1]));
|
||||
wtnw=1/(eps+SQR(cfa[indx-m2]-cfa[indx])+SQR(cfa[indx-m3]-cfa[indx-m1]));
|
||||
wtne=1/(eps+SQR(cfa[indx+p2]-cfa[indx])+SQR(cfa[indx+p3]-cfa[indx+p1]));
|
||||
wtsw=1/(eps+SQR(cfa[indx-p2]-cfa[indx])+SQR(cfa[indx-p3]-cfa[indx-p1]));
|
||||
|
||||
ginterp=(gse*wtse+gnw*wtnw+gne*wtne+gsw*wtsw)/(wtse+wtnw+wtne+wtsw);
|
||||
|
||||
if (/*(SQR(ginterp-gin) > 0.125*(gvar[indx-1]+gvar[indx+1]+gvar[indx-v1]+gvar[indx+v1])) &&*/ ((ginterp-gin) < thresh*(ginterp+gin)) ) {
|
||||
cfa[indx]=0.5*(ginterp+gin);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
// copy smoothed results back to image matrix
|
||||
for (rr=border; rr < numrows-border; rr++)
|
||||
for (row=rr+top, cc=border+1-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-border; cc+=2, indx+=2) {
|
||||
if (cfa[indx]<1) continue;
|
||||
col = cc + left;
|
||||
//c = FC(row,col);
|
||||
//image[row*width + col][c] = CLIP((int)(cfa[indx] + 0.5)); //for dcraw implementation
|
||||
ri->data[row][col] = CLIP((int)(cfa[indx] + 0.5));
|
||||
}
|
||||
|
||||
// clean up
|
||||
free(buffer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// done
|
||||
/*t2 = clock();
|
||||
dt = ((double)(t2-t1)) / CLOCKS_PER_SEC;
|
||||
if (verbose) {
|
||||
fprintf(stderr,_("elapsed time = %5.3fs\n"),dt);
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
#undef TS
|
@ -777,7 +777,7 @@ int RawImageSource::load (Glib::ustring fname) {
|
||||
idata = new ImageData (fname, &rml);
|
||||
|
||||
// check if it is an olympus E camera, if yes, compute G channel pre-compensation factors
|
||||
if (((idata->getMake().size()>=7 && idata->getMake().substr(0,7)=="OLYMPUS" && idata->getModel()[0]=='E') || (idata->getMake().size()>=9 && idata->getMake().substr(0,7)=="Panasonic")) && settings->demosaicMethod!="vng4" && ri->filters) {
|
||||
if (settings->greenthresh || (((idata->getMake().size()>=7 && idata->getMake().substr(0,7)=="OLYMPUS" && idata->getModel()[0]=='E') || (idata->getMake().size()>=9 && idata->getMake().substr(0,7)=="Panasonic")) && settings->demosaicMethod!="vng4" && ri->filters) ) {
|
||||
// global correction
|
||||
int ng1=0, ng2=0;
|
||||
double avgg1=0, avgg2=0;
|
||||
@ -799,8 +799,18 @@ int RawImageSource::load (Glib::ustring fname) {
|
||||
for (int j=border; j<W-border; j++)
|
||||
if (ISGREEN(ri,i,j))
|
||||
ri->data[i][j] = CLIP(ri->data[i][j] * (i%2 ? corrg2 : corrg1));
|
||||
}
|
||||
|
||||
|
||||
// local correction in a 9x9 box
|
||||
if (settings->greenthresh) {
|
||||
//Emil's green equilbration
|
||||
if (plistener) {
|
||||
plistener->setProgressStr ("Green equilibrate...");
|
||||
plistener->setProgress (0.0);
|
||||
}
|
||||
green_equilibrate(0.01*(settings->greenthresh));
|
||||
|
||||
// local correction in a 9x9 box
|
||||
/* unsigned short* corr_alloc = new unsigned short[W*H];
|
||||
unsigned short** corr_data = new unsigned short* [H];
|
||||
for (int i=0; i<H; i++)
|
||||
@ -822,8 +832,8 @@ int RawImageSource::load (Glib::ustring fname) {
|
||||
}
|
||||
memcpy (ri->allocation, corr_alloc, W*H*sizeof(unsigned short));
|
||||
delete corr_alloc;
|
||||
delete corr_data;
|
||||
*/
|
||||
delete corr_data; */
|
||||
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
@ -3222,6 +3232,7 @@ void RawImageSource::dcb_demosaic(int iterations, int dcb_enhance)
|
||||
#include "amaze_interpolate_RT.cc"//AMaZE demosaic
|
||||
#include "CA_correct_RT.cc"//Emil's CA auto correction
|
||||
#include "cfa_linedn_RT.cc"//Emil's CA auto correction
|
||||
#include "green_equil_RT.cc"//Emil's green channel equilibration
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
@ -142,6 +142,9 @@ class RawImageSource : public ImageSource {
|
||||
void ddct8x8s(int isgn, float **a);
|
||||
|
||||
void cfa_linedn (float linenoiselevel);//Emil's line denoise
|
||||
|
||||
void green_equilibrate (float greenthresh);//Emil's green equilibration
|
||||
|
||||
|
||||
void eahd_demosaic ();
|
||||
void hphd_demosaic ();
|
||||
|
@ -36,6 +36,7 @@ namespace rtengine {
|
||||
bool ca_autocorrect; // Emil's CA auto correction
|
||||
bool hotdeadpix_filt; // Emil's hot/dead pixel filter
|
||||
int linenoise; //Emil's line denoise
|
||||
int greenthresh; //Emil's Green equilibration
|
||||
|
||||
/** Creates a new instance of Settings.
|
||||
* @return a pointer to the new Settings instance. */
|
||||
|
@ -124,7 +124,8 @@ void Options::setDefaults () {
|
||||
rtSettings.hotdeadpix_filt = true;//Emil's hot/dead pixel filter
|
||||
|
||||
rtSettings.linenoise = 0;//Emil's line denoise
|
||||
|
||||
rtSettings.greenthresh = 0;//Emil's Green equilibration
|
||||
|
||||
rtSettings.colorCorrectionSteps = 0;
|
||||
rtSettings.dcb_iterations = 2;
|
||||
rtSettings.dcb_enhance = true;
|
||||
@ -269,6 +270,7 @@ if (keyFile.has_group ("Algorithms")) {
|
||||
if(keyFile.has_key("Algorithms", "CACorrect")) rtSettings.ca_autocorrect = keyFile.get_boolean("Algorithms", "CACorrect");//Emil's CA autocorrect
|
||||
if(keyFile.has_key("Algorithms", "HotDeadPixFilt")) rtSettings.hotdeadpix_filt = keyFile.get_boolean("Algorithms", "HotDeadPixFilt");//Emil's hot/dead pixel filter
|
||||
if(keyFile.has_key("Algorithms", "LineDenoise")) rtSettings.linenoise = keyFile.get_integer("Algorithms", "LineDenoise");//Emil's line denoise
|
||||
if(keyFile.has_key("Algorithms", "GreenEquil")) rtSettings.greenthresh = keyFile.get_integer("Algorithms", "GreenEquil");//Emil's Green equilibration
|
||||
}
|
||||
|
||||
if (keyFile.has_group ("Crop Settings")) {
|
||||
@ -395,7 +397,8 @@ int Options::saveToFile (Glib::ustring fname) {
|
||||
keyFile.set_boolean ("Algorithms", "CACorrect", rtSettings.ca_autocorrect);//Emil's CA correction
|
||||
keyFile.set_boolean ("Algorithms", "HotDeadPixFilt", rtSettings.hotdeadpix_filt);//Emil's hot/dead pixel filter
|
||||
keyFile.set_integer ("Algorithms", "LineDenoise", rtSettings.linenoise);//Emil's line denoise
|
||||
|
||||
keyFile.set_integer ("Algorithms", "GreenEquil", rtSettings.greenthresh);//Emil's Green equilibration
|
||||
|
||||
keyFile.set_integer ("Crop Settings", "DPI", cropDPI);
|
||||
|
||||
keyFile.set_string ("Color Management", "ICCDirectory", rtSettings.iccDirectory);
|
||||
|
@ -302,6 +302,18 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
|
||||
hb14->pack_start (*LineDenoise);
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//Emil's Green equilibration
|
||||
GreenEquilLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_GREENEQUIL")+":"));
|
||||
GreenEquil = Gtk::manage(new Gtk::SpinButton ());
|
||||
GreenEquil->set_digits(0);
|
||||
GreenEquil->set_increments(1, 10);
|
||||
GreenEquil->set_range(0, 100);
|
||||
Gtk::HBox* hb15 = Gtk::manage(new Gtk::HBox());
|
||||
hb15->pack_start (*GreenEquilLabel, Gtk::PACK_SHRINK, 4);
|
||||
hb15->pack_start (*GreenEquil);
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
fdb->pack_start (*hb11, Gtk::PACK_SHRINK, 4);
|
||||
fdb->pack_start (*hb12, Gtk::PACK_SHRINK, 4);
|
||||
fdb->pack_start (*hb13, Gtk::PACK_SHRINK, 4);
|
||||
@ -309,6 +321,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
|
||||
fdb->pack_start (*caAutoCorrect, Gtk::PACK_SHRINK, 4);//Emil's CA correction
|
||||
fdb->pack_start (*HotDeadPixFilt, Gtk::PACK_SHRINK, 4);//Emil's hot/dead pixel filter
|
||||
fdb->pack_start (*hb14, Gtk::PACK_SHRINK, 4);//Emil's line denoise
|
||||
fdb->pack_start (*hb15, Gtk::PACK_SHRINK, 4);//Emil's Green equlibration
|
||||
|
||||
mvbpp->pack_start (*fdem, Gtk::PACK_SHRINK, 4);
|
||||
mvbpp->set_border_width (4);
|
||||
@ -740,6 +753,7 @@ void Preferences::storePreferences () {
|
||||
moptions.rtSettings.ca_autocorrect=caAutoCorrect->get_active();//Emil's CA correction
|
||||
moptions.rtSettings.hotdeadpix_filt=HotDeadPixFilt->get_active();//Emil's hot/dead pixel filter
|
||||
moptions.rtSettings.linenoise=(int)LineDenoise->get_value();//Emil's line denoise
|
||||
moptions.rtSettings.greenthresh=(int)GreenEquil->get_value();//Emil's Green equilibration
|
||||
|
||||
|
||||
if (sdcurrent->get_active ())
|
||||
@ -842,6 +856,7 @@ void Preferences::fillPreferences () {
|
||||
caAutoCorrect->set_active(moptions.rtSettings.ca_autocorrect);//Emil's CA Auto Correction
|
||||
HotDeadPixFilt->set_active(moptions.rtSettings.hotdeadpix_filt);//Emil's hot/dead pixel filter
|
||||
LineDenoise->set_value(moptions.rtSettings.linenoise);//Emil's line denoise
|
||||
GreenEquil->set_value(moptions.rtSettings.greenthresh);//Emil's Green equilibration
|
||||
|
||||
|
||||
|
||||
|
@ -79,6 +79,8 @@ class Preferences : public Gtk::Dialog {
|
||||
Gtk::CheckButton* HotDeadPixFilt;//Emil's hot/dead pixel filter
|
||||
Gtk::Label* LineDenoiseLabel;//Emil's line denoise
|
||||
Gtk::SpinButton* LineDenoise;
|
||||
Gtk::Label* GreenEquilLabel;//Emil's Green equilibration
|
||||
Gtk::SpinButton* GreenEquil;
|
||||
|
||||
Gtk::FileChooserButton* iccDir;
|
||||
Gtk::FileChooserButton* monProfile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user