Skip to content

Commit

Permalink
[feature] Read and write the exr alpha channel
Browse files Browse the repository at this point in the history
The weight is now different for every patch values.
It currently only works with a single scale.
  • Loading branch information
hulud75 authored and Benjamin Legros committed Nov 25, 2015
1 parent 092b9f5 commit 5b2def2
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 44 deletions.
16 changes: 12 additions & 4 deletions io_exr.cpp
Expand Up @@ -44,7 +44,7 @@ struct sRGB
};


float *ReadImageEXR(const char fileName[], int *nx, int *ny)
float *ReadImageEXR(const char fileName[], int *nx, int *ny, float *&alpha)
{


Expand All @@ -61,12 +61,15 @@ float *ReadImageEXR(const char fileName[], int *nx, int *ny)

*nx = width;
*ny = height;

const bool hasAlpha = file.header().channels().findChannel("A") != NULL;

// Allocate memory to read image bits. We will only try to read R, G and B
// here, but additional channels like A (alpha) could also be added...
float *pixelsR = new float[width * height];
float *pixelsG = new float[width * height];
float *pixelsB = new float[width * height];
alpha = hasAlpha ? new float[width * height] : NULL;

// Now create the frame buffer to feed the image reader with. We will use
// the Slice method flexibility to directly read R, G and B data in an
Expand All @@ -91,6 +94,13 @@ float *ReadImageEXR(const char fileName[], int *nx, int *ny)
width * sizeof(float),
1, 1, // x/y sampling
0.0));
if (alpha)
frameBuffer.insert("A", Slice(FLOAT, (char*)(alpha -
dw.min.x -dw.min.y*width),
sizeof(float),
width * sizeof(float),
1, 1, // x/y sampling
0.0));

file.setFrameBuffer(frameBuffer);

Expand Down Expand Up @@ -131,7 +141,7 @@ float *ReadImageEXR(const char fileName[], int *nx, int *ny)



void WriteImageEXR(const char *name, float *pixels,
void WriteImageEXR(const char *name, float *pixels, float *alpha,
int xRes, int yRes, int channelStride)
{

Expand All @@ -141,8 +151,6 @@ void WriteImageEXR(const char *name, float *pixels,
int totalXRes = xRes;
int totalYRes = yRes;

float *alpha = NULL;

Rgba *hrgba = new Rgba[xRes * yRes];
for (int i = 0; i < xRes * yRes; ++i)
{
Expand Down
4 changes: 2 additions & 2 deletions io_exr.h
Expand Up @@ -28,9 +28,9 @@
#define IO_EXR_H_


float *ReadImageEXR(const char fileName[], int *nx, int *ny);
float *ReadImageEXR(const char fileName[], int *nx, int *ny, float *&alpha);

void WriteImageEXR(const char *name, float *pixels,
void WriteImageEXR(const char *name, float *pixels, float *alpha,
int xRes, int yRes, int channelStride);

void WriteImageEXR(const char *name, float **pixels,
Expand Down
34 changes: 33 additions & 1 deletion libauxiliar.cpp
Expand Up @@ -53,7 +53,9 @@ float fiChiSquareNDfFloatDist(int *df, float *k0, float *k1, float *u0,

float sum = (*ptr0 + *ptr1);

if(sum>1.00f)//to avoid problems due to little values.
if (sum>1.00f && //to avoid problems due to little values.
*ptrK0 != 0.f && // to avoid inf in empty pixels
*ptrK1 != 0.f)
{
float dif = (*ptr0)*(*ptrK1) - (*ptr1)*(*ptrK0);
dist += (dif*dif)/((*ptrK0)*(*ptrK1)*sum);
Expand Down Expand Up @@ -592,3 +594,33 @@ void compute_knn_index(int k, float *ivect_dist, int *ovect_ind, int n)

}

void alpha_mul (float *rgb, float *alpha, int np)
{
for (int i = 0; i < np; ++i)
{
const float a = alpha[i];
rgb[i] *= a;
rgb[i+np] *= a;
rgb[i+2*np] *= a;
}
}

void alpha_div (float *rgb, float *alpha, int np)
{
for (int i = 0; i < np; ++i)
{
const float a = alpha[i];
if (a == 0.f)
{
rgb[i] = 0;
rgb[i+np] = 0;
rgb[i+2*np] = 0;
}
else
{
rgb[i] /= a;
rgb[i+np] /= a;
rgb[i+2*np] /= a;
}
}
}
4 changes: 4 additions & 0 deletions libauxiliar.h
Expand Up @@ -73,4 +73,8 @@ float** bicubic_interpolation(float** in, int nx, int ny, int nch,

int compute_filter_mask(float** in, int x, int y, int nx, int ny, int nch);

void alpha_mul (float *rgb, float *alpha, int np);

void alpha_div (float *rgb, float *alpha, int np);

#endif
63 changes: 30 additions & 33 deletions libdenoising.cpp
Expand Up @@ -39,6 +39,7 @@ void rhf_multiscale(int iDWin, // Half size of patch
float **fhI, // Histogram
float **fpI, // Input
float **fpO, // Output
float *alpha, // Alpha channel, can be NULL
int iChannels, // Number of channels
int iWidth, // Image width
int iHeight, // Image height
Expand Down Expand Up @@ -135,6 +136,7 @@ void rhf_multiscale(int iDWin, // Half size of patch
fhIs, // Histogram
fpIs, // Input
fpOs, // Output
alpha, // Alpha
iChannels, nxS, nyS, iBins);
}
else
Expand All @@ -145,6 +147,7 @@ void rhf_multiscale(int iDWin, // Half size of patch
fhIs, // Histogram
fpIs, // Input
fpOs, // Output
alpha, // Alpha
iChannels, nxS, nyS, iBins);
}

Expand Down Expand Up @@ -250,6 +253,7 @@ void rhf_knn(int iDWin, // Half size of patch
float **fhI, // Histogram Image
float **fpI, // Input image
float **fpO, // Output image
float *alpha, // Alpha channel, can be NULL
int iChannels, // Number of channels
int iWidth, // Image width
int iHeight, // Image height
Expand Down Expand Up @@ -278,7 +282,7 @@ void rhf_knn(int iDWin, // Half size of patch

// PROCESS STARTS
// for each pixel (x,y)
#pragma omp parallel shared(fpI, fpO)
#pragma omp parallel shared(fpI, fpO, alpha)
{

#pragma omp for schedule(dynamic) nowait
Expand All @@ -290,6 +294,7 @@ void rhf_knn(int iDWin, // Half size of patch
float **fpODenoised = new float*[iChannels];
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii] = new float[iwl];
float *fTotalWeight = new float[iwl];

for (int x=0 ; x < iWidth; x++) {

Expand All @@ -309,12 +314,10 @@ void rhf_knn(int iDWin, // Half size of patch
for (int ii=0; ii < iChannels; ii++)
fpClear(fpODenoised[ii], 0.0f, iwl);


/*Check if we need to denoise this pixel!!*/
// sum of weights
float fTotalWeight = 0.0f;

// weights
float fWeight = 1.0f;
fpClear(fTotalWeight, 0.0f, iwl);

int dj = jmax-jmin+1;
int di = imax-imin+1;
Expand Down Expand Up @@ -344,9 +347,6 @@ void rhf_knn(int iDWin, // Half size of patch
int kk;
for(kk=0;kk<knnT;kk++)
{

fTotalWeight += fWeight;

//Reconvert index
int i = ovect_ind[kk]/dj + imin;
int j = ovect_ind[kk]%dj + jmin;
Expand All @@ -360,8 +360,10 @@ void rhf_knn(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il= ail +ir;

const float weight = alpha ? alpha[il] : 1.f;
fTotalWeight[iindex] += weight;
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii][iindex] += fWeight*fpI[ii][il];
fpODenoised[ii][iindex] += weight*fpI[ii][il];
}
}
}
Expand All @@ -371,9 +373,6 @@ void rhf_knn(int iDWin, // Half size of patch
{
if (fDif_all[kk] < fDistance)
{

fTotalWeight += fWeight;

int i = ovect_ind[kk]/dj + imin;
int j = ovect_ind[kk]%dj + jmin;

Expand All @@ -386,9 +385,10 @@ void rhf_knn(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il= ail +ir;

const float weight = alpha ? alpha[il] : 1.f;
fTotalWeight[iindex] += weight;
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii][iindex] +=
fWeight*fpI[ii][il];
fpODenoised[ii][iindex] += weight*fpI[ii][il];
}
}
}
Expand All @@ -404,14 +404,13 @@ void rhf_knn(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il=ail+ ir;

const float weight = fTotalWeight[iindex];
#pragma omp atomic
fpCount[il]++;

for (int ii=0; ii < iChannels; ii++) {
#pragma omp atomic

fpO[ii][il] += fpODenoised[ii][iindex]/fTotalWeight;

fpO[ii][il] += weight == 0.f ? 0.f : fpODenoised[ii][iindex]/weight;
}
}
}
Expand All @@ -424,6 +423,7 @@ void rhf_knn(int iDWin, // Half size of patch

for (int ii=0; ii < iChannels; ii++) delete[] fpODenoised[ii];
delete[] fpODenoised;
delete[] fTotalWeight;

}//yloop end
}//pragma end
Expand All @@ -442,13 +442,13 @@ void rhf_knn(int iDWin, // Half size of patch

}


void rhf(int iDWin, // Half size of patch
int iDBloc, // Half size of research window
float fDistance, // Max-Distance parameter
float **fhI, // Histogram
float **fpI, // Input
float **fpO, // Output
float *alpha, // Alpha channel, can be NULL
int iChannels, // Number of channels
int iWidth, // Image width
int iHeight, // Image height
Expand Down Expand Up @@ -486,15 +486,13 @@ void rhf(int iDWin, // Half size of patch
float **fpODenoised = new float*[iChannels];
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii] = new float[iwl];

float *fTotalWeight = new float[iwl];

for (int x=0 ; x < iWidth; x++)
{
/*Check if we need to denoise this pixel!!*/
// sum of weights
float fTotalWeight = 0.0f;

// weights
float fWeight = 1.0f;
fpClear(fTotalWeight, 0.0f, iwl);

//Reduce the size of comparison window near the boundary
int iDWin0 = MIN(iDWin,MIN(iWidth-1-x,
Expand Down Expand Up @@ -525,8 +523,6 @@ void rhf(int iDWin, // Half size of patch
iWidth);
if(fDifHist < fDistance*df)
{
fTotalWeight += fWeight;

for (int is=-iDWin0; is <=iDWin0; is++) {
int aiindex = (iDWin+is) * ihwl + iDWin;
int ail = (j+is)*iWidth+i;
Expand All @@ -536,9 +532,11 @@ void rhf(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il= ail +ir;

const float weight = alpha ? alpha[il] : 1.f;
fTotalWeight[iindex] += weight;
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii][iindex] +=
fWeight * fpI[ii][il];
weight* fpI[ii][il];
}
}
}
Expand All @@ -554,16 +552,14 @@ void rhf(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il=ail+ir;

const float weight = alpha ? alpha[il] : 1.f;
fTotalWeight[iindex] += weight;
for (int ii=0; ii < iChannels; ii++)
fpODenoised[ii][iindex] += fWeight * fpI[ii][il];
fpODenoised[ii][iindex] += weight * fpI[ii][il];
}
}

fTotalWeight += fWeight;

// normalize average value when fTotalweight is not near zero
if (fTotalWeight > fTiny) {

for (int is=-iDWin0; is <=iDWin0; is++) {
int aiindex = (iDWin+is) * ihwl + iDWin;
int ail=(y+is)*iWidth+x;
Expand All @@ -572,21 +568,22 @@ void rhf(int iDWin, // Half size of patch
int iindex = aiindex + ir;
int il=ail+ ir;

const float weight = fTotalWeight[iindex];
#pragma omp atomic
fpCount[il]++;

for (int ii=0; ii < iChannels; ii++) {
#pragma omp atomic
fpO[ii][il] +=
fpODenoised[ii][iindex]/fTotalWeight;
weight == 0.f ? 0.f : fpODenoised[ii][iindex]/weight;
}
}
}
}//end if Tiny
}

for (int ii=0; ii < iChannels; ii++) delete[] fpODenoised[ii];
delete[] fpODenoised;
delete[] fTotalWeight;
}
}

Expand Down
3 changes: 3 additions & 0 deletions libdenoising.h
Expand Up @@ -50,6 +50,7 @@ void rhf_knn(int iDWin, // Half size of patch
float **fhI, // Histogram
float **fpI, // Input
float **fpO, // Output
float *alpha, // Alpha channel, can be NULL
int iChannels, int iWidth,int iHeight, int iBins);


Expand All @@ -75,6 +76,7 @@ void rhf(int iDWin, // Half size of patch
float **fhI, // Histogram
float **fpI, // Input
float **fpO, // Output
float *alpha, // Alpha channel, can be NULL
int iChannels, int iWidth,int iHeight, int iBins);


Expand Down Expand Up @@ -103,6 +105,7 @@ void rhf_multiscale(int iDWin, // Half size of patch
float **fhI, // Histogram
float **fpI, // Input
float **fpO, // Output
float *alpha, // Alpha channel, can be NULL
int iChannels, int iWidth,int iHeight, int iBins);


Expand Down

0 comments on commit 5b2def2

Please sign in to comment.