Skip to content

Commit

Permalink
hdr fusion: work in linear colorspace LuminanceHDR#185
Browse files Browse the repository at this point in the history
  • Loading branch information
fcomida committed Aug 21, 2019
1 parent 48648da commit 92f8d98
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 784 deletions.
3 changes: 2 additions & 1 deletion librtprocess/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ ADD_LIBRARY(librtprocess STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/demosaic/ahd.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/demosaic/rcd.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/demosaic/vng4.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/demosaic/xtransfast.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/postprocess/hilite_recon.cc)
${CMAKE_CURRENT_SOURCE_DIR}/src/postprocess/hilite_recon.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/preprocess/CA_correct.cc)

SET(LUMINANCE_MODULES_CLI ${LUMINANCE_MODULES_CLI} librtprocess PARENT_SCOPE)
SET(LUMINANCE_MODULES_GUI ${LUMINANCE_MODULES_GUI} librtprocess PARENT_SCOPE)
58 changes: 4 additions & 54 deletions src/HdrCreation/debevec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

//! \author Giuseppe Rota <[email protected]>
//! \author Davide Anastasia <[email protected]>
//! \author Franco Comida <[email protected]>

#include "HdrCreation/debevec.h"
#include <Libpfs/colorspace/normalizer.h>
Expand Down Expand Up @@ -118,33 +119,6 @@ void DebevecOperator::computeFusion(ResponseCurve &response,
images[i].frame()->getXYZChannels(Ch[0], Ch[1], Ch[2]);
Array2Df *imagesCh[channels] = {Ch[0], Ch[1], Ch[2]};

float cmax[3];
float cmin[3];
#ifdef _OPENMP
#pragma omp parallel for num_threads(nestedthreads) if (nestedthreads>1)
#endif
for (int c = 0; c < channels; c++) {
float minval = numeric_limits<float>::max();
float maxval = numeric_limits<float>::min();
for (size_t k = 0; k < size; k++) {
minval = std::min(minval, (*imagesCh[c])(k));
maxval = std::max(maxval, (*imagesCh[c])(k));
}
cmax[c] = maxval;
cmin[c] = minval;
}

float Max = max(cmax[0], max(cmax[1], cmax[2]));
float Min = min(cmin[0], min(cmin[1], cmin[2]));

#ifdef _OPENMP
#pragma omp parallel for num_threads(nestedthreads) if (nestedthreads>1)
#endif
for (int c = 0; c < channels; c++) {
transform(Ch[c]->begin(), Ch[c]->end(), Ch[c]->begin(),
Normalizer(Min, Max));
}

Array2Df response_img(W, H);
Array2Df w(W, H);

Expand Down Expand Up @@ -212,22 +186,6 @@ void DebevecOperator::computeFusion(ResponseCurve &response,
}
}
}
float cmax[3];
for (int c = 0; c < channels; c++) {
float max = numeric_limits<float>::min();
#ifdef _OPENMP
#pragma omp parallel for reduction(max:max)
#endif
for (size_t k = 0; k < size; k++) {
float val = (*resultCh[c])(k);
if(std::isnormal(val)) {
max = std::max(max, val);
}
}
cmax[c] = max;
}

float Max = max(cmax[0], max(cmax[1], cmax[2]));

for (int c = 0; c < channels; c++) {
#ifdef _OPENMP
Expand All @@ -236,18 +194,10 @@ void DebevecOperator::computeFusion(ResponseCurve &response,
for (size_t k = 0; k < size; k++) {
float val = (*resultCh[c])(k);
if(!std::isnormal(val)) {
(*resultCh[c])(k) = Max;
(*resultCh[c])(k) = 0.f;
}
}
}

// TODO: Investigate why scaling hdr yields better result
for (int c = 0; c < channels; c++) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t k = 0; k < size; k++) {
(*resultCh[c])(k) *= 0.1f;
(*resultCh[c])(k) = (val < 0.f) ? 0.f : val;
(*resultCh[c])(k) = (val > 1.f) ? 1.f : val;
}
}

Expand Down
30 changes: 15 additions & 15 deletions src/HdrWizard/HdrCreationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,21 +561,21 @@ pfs::Frame *HdrCreationManager::doAntiGhosting(bool patches[][agGridSize],
std::unique_ptr<Frame> ghosted(createHdr());
ghosted->getXYZChannels(Ch[0], Ch[1], Ch[2]);

for (int c = 0; c < 3; c++) {
cmax[c] = *max_element(Ch[c]->begin(), Ch[c]->end());
cmin[c] = *min_element(Ch[c]->begin(), Ch[c]->end());
}
Max = std::max(cmax[0], std::max(cmax[1], cmax[2]));
Min = std::min(cmin[0], std::min(cmin[1], cmin[2]));

for (int c = 0; c < 3; c++) {
replace_if(Ch[c]->begin(), Ch[c]->end(),
[](float f) { return !isnormal(f); }, Max);
replace_if(Ch[c]->begin(), Ch[c]->end(),
[](float f) { return !isfinite(f); }, Max);
transform(Ch[c]->begin(), Ch[c]->end(), Ch[c]->begin(),
Normalizer(Min, Max));
}
/* for (int c = 0; c < 3; c++) { */
/* cmax[c] = *max_element(Ch[c]->begin(), Ch[c]->end()); */
/* cmin[c] = *min_element(Ch[c]->begin(), Ch[c]->end()); */
/* } */
/* Max = std::max(cmax[0], std::max(cmax[1], cmax[2])); */
/* Min = std::min(cmin[0], std::min(cmin[1], cmin[2])); */

/* for (int c = 0; c < 3; c++) { */
/* replace_if(Ch[c]->begin(), Ch[c]->end(), */
/* [](float f) { return !isnormal(f); }, Max); */
/* replace_if(Ch[c]->begin(), Ch[c]->end(), */
/* [](float f) { return !isfinite(f); }, Max); */
/* transform(Ch[c]->begin(), Ch[c]->end(), Ch[c]->begin(), */
/* Normalizer(Min, Max)); */
/* } */

Rc = Ch[0];
Gc = Ch[1];
Expand Down
4 changes: 4 additions & 0 deletions src/Libpfs/colorspace/gamma.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
namespace pfs {
namespace colorspace {

struct Inv_Gamma2_2 {
static float gamma() { return 2.2f; }
};

struct Gamma2_2 {
static float gamma() { return 1.f / 2.2f; }
};
Expand Down
19 changes: 12 additions & 7 deletions src/Libpfs/io/jpegreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <Libpfs/colorspace/cmyk.h>
#include <Libpfs/colorspace/copy.h>
#include <Libpfs/colorspace/lcms.h>
#include <Libpfs/colorspace/gamma.h>
#include <Libpfs/fixedstrideiterator.h>
#include <Libpfs/frame.h>
#include <Libpfs/utils/resourcehandlerlcms.h>
Expand All @@ -35,6 +36,8 @@
#include <cassert>
#include <iostream>

#undef NDEBUG

using namespace pfs;

#ifndef NDEBUG
Expand Down Expand Up @@ -392,14 +395,16 @@ void JpegReader::read(Frame &frame, const Params &params) {
switch (m_data->cinfo()->jpeg_color_space) {
case JCS_RGB:
case JCS_YCbCr: {
if (xform) {
PRINT_DEBUG("Use LCMS RGB");
/* TODO */
/* if (xform) { */
/* PRINT_DEBUG("Use LCMS RGB"); */
/* read3Components(m_data->cinfo(), tempFrame, */
/* colorspace::Convert3LCMS3(xform.data())); */
/* } else { */
PRINT_DEBUG("NO COLOR PROFILE");
read3Components(m_data->cinfo(), tempFrame,
colorspace::Convert3LCMS3(xform.data()));
} else {
read3Components(m_data->cinfo(), tempFrame,
colorspace::Copy());
}
colorspace::Gamma<colorspace::Inv_Gamma2_2>());
/* } */
} break;
case JCS_CMYK:
case JCS_YCCK: {
Expand Down
110 changes: 79 additions & 31 deletions src/Libpfs/io/rawreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,14 @@

#include <Libpfs/colorspace/copy.h>
#include <Libpfs/colorspace/gamma.h>
#include <Libpfs/colorspace/normalizer.h>
#include <Libpfs/fixedstrideiterator.h>
#include <Libpfs/frame.h>
#include <Libpfs/io/rawreader.h>
#include <Libpfs/utils/transform.h>
#include "sleef.c"
#include "opthelper.h"


#define ABS(a) ((a)<0?-(a):(a))

bool callback(double a) { return false; }

using namespace pfs;
Expand Down Expand Up @@ -109,8 +107,8 @@ static void temperatureToRGB(double T, double RGB[3]) {

struct RAWReaderParams {
RAWReaderParams()
: gamma0_(1 / 2.4),
gamma1_(12.92),
: gamma0_(1),
gamma1_(1),
fourColorRGB_(0),
useFujiRotate_(-1),
userQuality_(10),
Expand Down Expand Up @@ -470,6 +468,8 @@ void RAWReader::read(Frame &frame, const Params &params) {
OUT.no_interpolation = 0;
}

p.wbMethod_ = 3;

if (m_processor.dcraw_process() != LIBRAW_SUCCESS) {
m_processor.recycle();
throw pfs::io::ReadException("Error Processing RAW File");
Expand Down Expand Up @@ -517,6 +517,21 @@ void RAWReader::read(Frame &frame, const Params &params) {
PRINT_DEBUG("Data size: " << image->data_size << " " << W * H * 3 * sizeof(uint16_t));
PRINT_DEBUG("W: " << W << " H: " << H);

float rCamMul = m_processor.imgdata.color.cam_mul[0];
float gCamMul = m_processor.imgdata.color.cam_mul[1];
float bCamMul = m_processor.imgdata.color.cam_mul[2];
float minMult = min(min(rCamMul, gCamMul), bCamMul);
rCamMul /= minMult;
gCamMul /= minMult;
bCamMul /= minMult;
float rPreMul = m_processor.imgdata.color.pre_mul[0];
float gPreMul = m_processor.imgdata.color.pre_mul[1];
float bPreMul = m_processor.imgdata.color.pre_mul[2];
minMult = min(min(rPreMul, gPreMul), bPreMul);
rPreMul /= minMult;
gPreMul /= minMult;
bPreMul /= minMult;

unsigned cf_array[2][2];
if ( isBayer() ) {
PRINT_DEBUG("Bayer");
Expand Down Expand Up @@ -546,6 +561,7 @@ void RAWReader::read(Frame &frame, const Params &params) {
}

if ( isBayer() ) {
const float mult = 1.0f / 65535.f;
#ifdef _OPENMP
#pragma omp parallel for
#endif
Expand All @@ -554,12 +570,13 @@ void RAWReader::read(Frame &frame, const Params &params) {
for(unsigned j = 0; j < W; j++) {
unsigned c = cf_array[i%2][j%2];
unsigned pos = k + i*W*3;
rawdata[i][j] = raw_data[pos + c] / 65535.f;
rawdata[i][j] = raw_data[pos + c] * mult;
k += 3;
}
}
}
else if ( isXtrans() ) {
const float mult = 1.0f / 65535.f;
#ifdef _OPENMP
#pragma omp parallel for
#endif
Expand All @@ -568,7 +585,7 @@ void RAWReader::read(Frame &frame, const Params &params) {
for(unsigned j = 0; j < W; j++) {
unsigned c = xtrans[(i) % 6][(j) % 6];
unsigned pos = k + i*W*3;
rawdata[i][j] = raw_data[pos + c] / 65535.f;
rawdata[i][j] = raw_data[pos + c] * mult;
k += 3;
}
}
Expand All @@ -584,15 +601,21 @@ void RAWReader::read(Frame &frame, const Params &params) {
r = (float **) malloc(H * sizeof(float *));
g = (float **) malloc(H * sizeof(float *));
b = (float **) malloc(H * sizeof(float *));
r[0] = (float *)malloc(W*H * sizeof(float));
g[0] = (float *)malloc(W*H * sizeof(float));
b[0] = (float *)malloc(W*H * sizeof(float));
r[0] = Xc->data();
g[0] = Yc->data();
b[0] = Zc->data();
for(unsigned i = 1; i < H; i++) {
r[i] = r[i-1] + W;
g[i] = g[i-1] + W;
b[i] = b[i-1] + W;
}

if (p.chromaAberation_) {
PRINT_DEBUG("CA_correct");
double fitparams[2][2][16];
CA_correct(0, 0, W, H, true, 1, 0.0, 0.0, true, rawdata, rawdata, cf_array, callback, fitparams, false);
}

try {
if ( isBayer() ) {
switch (p.userQuality_) {
Expand Down Expand Up @@ -637,39 +660,64 @@ void RAWReader::read(Frame &frame, const Params &params) {
}
catch(...) {
PRINT_DEBUG("DEMOSAICING FAILED");
free ( b );
free ( g );
free ( r );
free ( rawdata[0] );
free ( rawdata );
throw pfs::io::ReadException("DEMOSICING FAILED");
}

//HLRecovery_inpaint(W, H, r, g, b, chmax, clmax, callback);
if (p.highlightsMethod_ >= 3) {
PRINT_DEBUG("HL_recovery");
auto minmaxR = std::minmax_element(Xc->begin(), Xc->end());
auto minmaxG = std::minmax_element(Yc->begin(), Yc->end());
auto minmaxB = std::minmax_element(Zc->begin(), Zc->end());

#ifdef _OPENMP
#pragma omp parallel for
#endif
for (unsigned i = 0; i < H; ++i) {
unsigned j = 0;
#ifdef __SSE2__
for (; j < W - 3; j += 4) {
STVFU((*Xc)(j, i), LVFU(r[i][j]));
STVFU((*Yc)(j, i), LVFU(g[i][j]));
STVFU((*Zc)(j, i), LVFU(b[i][j]));
}
#endif
for (; j < W; ++j) {
(*Xc)(j, i) = r[i][j];
(*Yc)(j, i) = g[i][j];
(*Zc)(j, i) = b[i][j];
}
PRINT_DEBUG("maxR: " << *minmaxR.second);
PRINT_DEBUG("minR: " << *minmaxR.first);
PRINT_DEBUG("maxG: " << *minmaxG.second);
PRINT_DEBUG("minG: " << *minmaxG.first);
PRINT_DEBUG("maxB: " << *minmaxB.second);
PRINT_DEBUG("minB: " << *minmaxB.first);

const float chmax[3] = {*minmaxR.second, *minmaxG.second, *minmaxB.second};
//Max clip point:
const float clmax[3] = {rCamMul, gCamMul, bCamMul};
HLRecovery_inpaint(W, H, r, g, b, chmax, clmax, callback);
}

free ( b[0] );
free ( b );
free ( g[0] );
free ( g );
free ( r[0] );
free ( r );
free ( rawdata[0] );
free ( rawdata );

Array2Df *Ch[3] = {Xc, Yc, Zc};
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t k = 0; k < W*H; k++) {
float r = (*Ch[0])(k);
float g = (*Ch[1])(k);
float b = (*Ch[2])(k);
if(!std::isnormal(r) || !std::isnormal(g) || !std::isnormal(b)) {
(*Ch[0])(k) = 0.f;
(*Ch[1])(k) = 0.f;
(*Ch[2])(k) = 0.f;
}
if ( (r < 0.f) || (g < 0.f) || (b < 0.f)) {
(*Ch[0])(k) = 0.f;
(*Ch[1])(k) = 0.f;
(*Ch[2])(k) = 0.f;
}
if ( (r > 1.f) || (g > 1.f) || (b > 1.f)) {
(*Ch[0])(k) = 1.f;
(*Ch[1])(k) = 1.f;
(*Ch[2])(k) = 1.f;
}
}

FrameReader::read(tempFrame, params);
frame.swap(tempFrame);
}
Expand Down
Loading

0 comments on commit 92f8d98

Please sign in to comment.