Improvements for autoexposure and 'blend' highlight reconstruction.
This commit is contained in:
@@ -621,7 +621,7 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) {
|
|||||||
|
|
||||||
double corr = 1;//pow(2.0, defgain);//defgain may be redundant legacy of superceded code???
|
double corr = 1;//pow(2.0, defgain);//defgain may be redundant legacy of superceded code???
|
||||||
float scale = 65536.0;
|
float scale = 65536.0;
|
||||||
float midgray=0.18445f;//middle gray in linear gamma = 0.18445*65535
|
float midgray=0.15;//0.18445f;//middle gray in linear gamma = 0.18445*65535
|
||||||
|
|
||||||
int imax=65536>>histcompr;
|
int imax=65536>>histcompr;
|
||||||
|
|
||||||
@@ -630,7 +630,7 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) {
|
|||||||
//find average luminance
|
//find average luminance
|
||||||
for (int i=0; i<imax; i++) {
|
for (int i=0; i<imax; i++) {
|
||||||
sum += histogram[i];
|
sum += histogram[i];
|
||||||
ave += histogram[i] * i;//log((float)(i+1))/log(2.0);
|
ave += histogram[i] * i;
|
||||||
}
|
}
|
||||||
ave /= (sum);
|
ave /= (sum);
|
||||||
|
|
||||||
@@ -646,24 +646,29 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) {
|
|||||||
float octile[8]={0,0,0,0,0,0,0,0},ospread=0;
|
float octile[8]={0,0,0,0,0,0,0,0},ospread=0;
|
||||||
count=0;
|
count=0;
|
||||||
for (int i=0; i<imax; i++) {
|
for (int i=0; i<imax; i++) {
|
||||||
|
if (count<8) {
|
||||||
octile[count] += histogram[i];
|
octile[count] += histogram[i];
|
||||||
if (octile[count]>sum/8) {
|
if (octile[count]>sum/8 || (count==7 && octile[count]>sum/16)) {
|
||||||
octile[count]=log(1+i)/log(2);
|
octile[count]=log(1+i)/log(2);
|
||||||
count = MIN(count+1,7);
|
count++;// = MIN(count+1,7);
|
||||||
}
|
}
|
||||||
if (i<median) {
|
}
|
||||||
|
if (i<ave) {
|
||||||
//lodev += SQR(ave-i)*histogram[i];
|
//lodev += SQR(ave-i)*histogram[i];
|
||||||
lodev += (log(median+1)-log(i+1))*histogram[i];
|
lodev += (log(ave+1)-log(i+1))*histogram[i];
|
||||||
losum += histogram[i];
|
losum += histogram[i];
|
||||||
} else {
|
} else {
|
||||||
//hidev += SQR(i-ave)*histogram[i];
|
//hidev += SQR(i-ave)*histogram[i];
|
||||||
hidev += (log(i+1)-log(median+1))*histogram[i];
|
hidev += (log(i+1)-log(ave+1))*histogram[i];
|
||||||
hisum += histogram[i];
|
hisum += histogram[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
lodev = (lodev/(log(2)*losum));
|
lodev = (lodev/(log(2)*losum));
|
||||||
hidev = (hidev/(log(2)*hisum));
|
hidev = (hidev/(log(2)*hisum));
|
||||||
|
if (octile[7]>log(imax+1)/log2(2)) {
|
||||||
|
octile[7]=1.5*octile[6]-0.5*octile[5];
|
||||||
|
}
|
||||||
// compute weighted average separation of octiles
|
// compute weighted average separation of octiles
|
||||||
// for future use in contrast setting
|
// for future use in contrast setting
|
||||||
for (int i=1; i<6; i++) {
|
for (int i=1; i<6; i++) {
|
||||||
@@ -708,49 +713,64 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) {
|
|||||||
if (lodev==0) lodev=1;
|
if (lodev==0) lodev=1;
|
||||||
|
|
||||||
//compute exposure compensation as geometric mean of the amount that
|
//compute exposure compensation as geometric mean of the amount that
|
||||||
//sets the median at middle gray, and the amount that sets the clipped white point
|
//sets the mean or median at middle gray, and the amount that sets the estimated top
|
||||||
//at 65535. Apply a correction factor of median/ave so that high/low key images
|
//of the histogram at or near clipping.
|
||||||
//are treated properly
|
|
||||||
float gain = /*corr**/midgray*scale/(median-shc+midgray*shc);
|
|
||||||
|
|
||||||
gain = (median/ave)*sqrt(gain*scale/rawmax);
|
float expcomp1 = log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc))/log(2);
|
||||||
|
float expcomp2 = 0.5*( (15.5f-histcompr-(2*octile[7]-octile[6])) + log(scale/rawmax)/log(2) );
|
||||||
|
|
||||||
|
/*expcomp = (expcomp1*fabs(expcomp2)+expcomp2*fabs(expcomp1))/(fabs(expcomp1)+fabs(expcomp2));
|
||||||
|
if (expcomp<0) {
|
||||||
|
MIN(0.0f,MAX(expcomp1,expcomp2));
|
||||||
|
}*/
|
||||||
|
expcomp = 0.5 * (expcomp1 + expcomp2);
|
||||||
|
float gain = exp(expcomp*log(2));
|
||||||
|
|
||||||
|
|
||||||
|
gain = /*(median/ave)*/sqrt(gain*scale/rawmax);
|
||||||
black = shc*gain;
|
black = shc*gain;
|
||||||
expcomp = log(gain)/log(2.0);//convert to stops
|
expcomp = log(gain)/log(2.0);//convert to stops
|
||||||
|
|
||||||
|
black = shc*gain;
|
||||||
|
|
||||||
//now tune hlcompr to bring back rawmax to 65535
|
//now tune hlcompr to bring back rawmax to 65535
|
||||||
hlcomprthresh = 33;
|
hlcomprthresh = 33;
|
||||||
float shoulder = ((scale/MAX(1,gain))*(hlcomprthresh/200.0))+0.1;
|
float shoulder = ((scale/MAX(1,gain))*(hlcomprthresh/200.0))+0.1;
|
||||||
//this is a series approximation of the actual formula for comp,
|
//this is a series approximation of the actual formula for comp,
|
||||||
//which is a transcendental equation
|
//which is a transcendental equation
|
||||||
float comp = (gain*whiteclip/scale - 1)*2*(1-shoulder/scale);
|
float comp = (gain*((float)whiteclip)/scale - 1)*2;//*(1-shoulder/scale);
|
||||||
hlcompr=(int)(100*comp/(MAX(0,expcomp) + 1.0));
|
hlcompr=(int)(100*comp/(MAX(0,expcomp) + 1.0));
|
||||||
hlcompr = MAX(0,MIN(100,hlcompr));
|
hlcompr = MAX(0,MIN(100,hlcompr));
|
||||||
|
|
||||||
//now find brightness if gain didn't bring ave to midgray using
|
//now find brightness if gain didn't bring ave to midgray using
|
||||||
//the envelope of the actual 'control cage' brightness curve for simplicity
|
//the envelope of the actual 'control cage' brightness curve for simplicity
|
||||||
float midtmp = gain*(median)/scale;
|
float midtmp = gain*sqrt(median*ave)/scale;
|
||||||
if (midtmp<0.1) {
|
if (midtmp<0.1) {
|
||||||
bright = (midgray-midtmp)*15.0/(midtmp);
|
bright = (midgray-midtmp)*15.0/(midtmp);
|
||||||
} else {
|
} else {
|
||||||
bright = (midgray-midtmp)*15.0/(0.10833-0.0833*midtmp);
|
bright = (midgray-midtmp)*15.0/(0.10833-0.0833*midtmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bright = 0.25*(median/ave)*(hidev/lodev)*MAX(0,bright);
|
bright = 0.25*/*(median/ave)*(hidev/lodev)*/MAX(0,bright);
|
||||||
|
|
||||||
//compute contrast that spreads the average spacing of octiles
|
//compute contrast that spreads the average spacing of octiles
|
||||||
contr = 50.0*(1.1-ospread);
|
contr = 50.0*(1.1-ospread);
|
||||||
contr = MAX(0,MIN(100,contr));
|
contr = MAX(0,MIN(100,contr));
|
||||||
|
|
||||||
//diagnostics
|
//diagnostics
|
||||||
/*printf ("**************** AUTO LEVELS ****************\n");
|
printf ("**************** AUTO LEVELS ****************\n");
|
||||||
printf ("median: %i\n",median);
|
printf ("gain1= %f gain2= %f gain= %f\n",expcomp1,expcomp2,gain);
|
||||||
printf ("average: %f\n",ave);
|
printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave);
|
||||||
printf ("median/average: %f\n",median/ave);
|
//printf ("average: %f\n",ave);
|
||||||
printf ("hidev/lodev: %f\n",hidev/lodev);
|
//printf ("median/average: %f\n",median/ave);
|
||||||
printf ("lodev: %f\n",lodev);
|
printf ("lodev: %f hidev: %f hidev/lodev: %f\n",lodev,hidev,hidev/lodev);
|
||||||
printf ("hidev: %f\n",hidev);
|
//printf ("lodev: %f\n",lodev);
|
||||||
printf ("octiles: %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6]);
|
//printf ("hidev: %f\n",hidev);
|
||||||
printf ("ospread= %f\n",ospread);*/
|
printf ("rawmax= %d whiteclip= %d gain= %f\n",rawmax,whiteclip,gain);
|
||||||
|
|
||||||
|
printf ("octiles: %f %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6],octile[7]);
|
||||||
|
printf ("ospread= %f\n",ospread);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// %%%%%%%%%% LEGACY AUTOEXPOSURE CODE %%%%%%%%%%%%%
|
// %%%%%%%%%% LEGACY AUTOEXPOSURE CODE %%%%%%%%%%%%%
|
||||||
@@ -778,9 +798,11 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) {
|
|||||||
|
|
||||||
if (expcomp<0.0) expcomp = 0.0;*/
|
if (expcomp<0.0) expcomp = 0.0;*/
|
||||||
|
|
||||||
|
if (expcomp<-5.0) expcomp = -5.0;
|
||||||
if (expcomp>10.0) expcomp = 10.0;
|
if (expcomp>10.0) expcomp = 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
#include "calc_distort.h"
|
#include "calc_distort.h"
|
||||||
|
@@ -1921,10 +1921,11 @@ void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int wi
|
|||||||
#define SQR(x) ((x)*(x))
|
#define SQR(x) ((x)*(x))
|
||||||
|
|
||||||
|
|
||||||
float minpt=MIN(MIN(hlmax[0],hlmax[1]),hlmax[2]);
|
float minpt=MIN(MIN(hlmax[0],hlmax[1]),hlmax[2]);//min of the raw clip points
|
||||||
//float maxpt=MAX(MAX(hlmax[0],hlmax[1]),hlmax[2]);
|
//float maxpt=MAX(MAX(hlmax[0],hlmax[1]),hlmax[2]);//max of the raw clip points
|
||||||
//float medpt=hlmax[0]+hlmax[1]+hlmax[2]-minpt-maxpt;
|
//float medpt=hlmax[0]+hlmax[1]+hlmax[2]-minpt-maxpt;//median of the raw clip points
|
||||||
float maxave=(hlmax[0]+hlmax[1]+hlmax[2])/3;
|
float maxave=(hlmax[0]+hlmax[1]+hlmax[2])/3;//ave of the raw clip points
|
||||||
|
//some thresholds:
|
||||||
const float clipthresh = 0.95;
|
const float clipthresh = 0.95;
|
||||||
const float fixthresh = 0.5;
|
const float fixthresh = 0.5;
|
||||||
const float satthresh = 0.5;
|
const float satthresh = 0.5;
|
||||||
@@ -1940,7 +1941,7 @@ void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int wi
|
|||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (int col=0; col<width; col++) {
|
for (int col=0; col<width; col++) {
|
||||||
float rgb[ColorCount], cam[2][ColorCount], lab[2][ColorCount], sum[2], chratio;
|
float rgb[ColorCount], cam[2][ColorCount], lab[2][ColorCount], sum[2], chratio, lratio=0;
|
||||||
float L,C,H,Lfrac;
|
float L,C,H,Lfrac;
|
||||||
|
|
||||||
// Copy input pixel to rgb so it's easier to access in loops
|
// Copy input pixel to rgb so it's easier to access in loops
|
||||||
@@ -1956,6 +1957,7 @@ void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int wi
|
|||||||
|
|
||||||
// Initialize cam with raw input [0] and potentially clipped input [1]
|
// Initialize cam with raw input [0] and potentially clipped input [1]
|
||||||
FOREACHCOLOR {
|
FOREACHCOLOR {
|
||||||
|
lratio += MIN(rgb[c],clip[c]);
|
||||||
cam[0][c] = rgb[c];
|
cam[0][c] = rgb[c];
|
||||||
cam[1][c] = MIN(cam[0][c],maxval);
|
cam[1][c] = MIN(cam[0][c],maxval);
|
||||||
}
|
}
|
||||||
@@ -1972,13 +1974,13 @@ void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int wi
|
|||||||
for (int c=1; c < ColorCount; c++)
|
for (int c=1; c < ColorCount; c++)
|
||||||
sum[i] += SQR(lab[i][c]);
|
sum[i] += SQR(lab[i][c]);
|
||||||
}
|
}
|
||||||
chratio = sqrt(sqrt(sum[1]/sum[0]));
|
chratio = (sqrt(sum[1]/sum[0]));
|
||||||
|
|
||||||
// Apply ratio to lightness in lab space
|
// Apply ratio to lightness in LCH space
|
||||||
for (int c=1; c < ColorCount; c++)
|
for (int c=1; c < ColorCount; c++)
|
||||||
lab[0][c] *= chratio;
|
lab[0][c] *= chratio;
|
||||||
|
|
||||||
// Transform back from lab to RGB
|
// Transform back from LCH to RGB
|
||||||
FOREACHCOLOR {
|
FOREACHCOLOR {
|
||||||
cam[0][c]=0;
|
cam[0][c]=0;
|
||||||
for (int j=0; j < ColorCount; j++) {
|
for (int j=0; j < ColorCount; j++) {
|
||||||
@@ -2001,6 +2003,14 @@ void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int wi
|
|||||||
bin[col]= MIN(maxave,bfrac*rgb[2]+(1-bfrac)*bin[col]);
|
bin[col]= MIN(maxave,bfrac*rgb[2]+(1-bfrac)*bin[col]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lratio /= (rin[col]+gin[col]+bin[col]);
|
||||||
|
L = (rin[col]+gin[col]+bin[col])/3;
|
||||||
|
C = lratio * 1.732050808 * (rin[col] - gin[col]);
|
||||||
|
H = lratio * (2 * bin[col] - rin[col] - gin[col]);
|
||||||
|
rin[col] = L - H / 6.0 + C / 3.464101615;
|
||||||
|
gin[col] = L - H / 6.0 - C / 3.464101615;
|
||||||
|
bin[col] = L + H / 3.0;
|
||||||
|
|
||||||
if ((L=(rin[col]+gin[col]+bin[col])/3) > desatpt) {
|
if ((L=(rin[col]+gin[col]+bin[col])/3) > desatpt) {
|
||||||
Lfrac = MAX(0,(maxave-L)/(maxave-desatpt));
|
Lfrac = MAX(0,(maxave-L)/(maxave-desatpt));
|
||||||
C = Lfrac * 1.732050808 * (rin[col] - gin[col]);
|
C = Lfrac * 1.732050808 * (rin[col] - gin[col]);
|
||||||
|
Reference in New Issue
Block a user