Skip to content

Commit

Permalink
[HDR] merging algorithm: remove noise param and code cleaning
Browse files Browse the repository at this point in the history
  • Loading branch information
demoulinv committed Jun 28, 2023
1 parent cd21f4c commit 90104f6
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 211 deletions.
284 changes: 107 additions & 177 deletions src/aliceVision/hdr/hdrMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,12 @@ void hdrMerge::process(const std::vector< image::Image<image::RGBfColor> > &imag
rgbCurve weightLongestExposure = weight;
weightLongestExposure.freezeFirstPartValues();

//const std::string mergeInfoFilename = "C:/Temp/mergeInfo.csv";
//std::ofstream file(mergeInfoFilename);

const std::vector<double> v_minValue = {mergingParams.minSignificantValue * response(1.0, 0),
mergingParams.minSignificantValue * response(1.0, 1),
mergingParams.minSignificantValue * response(1.0, 2)};
const std::vector<double> v_maxValue = {mergingParams.maxSignificantValue * response(1.0, 0),
mergingParams.maxSignificantValue * response(1.0, 1),
mergingParams.maxSignificantValue * response(1.0, 2)};
const std::vector<double> v_minValue = {response(mergingParams.minSignificantValue, 0),
response(mergingParams.minSignificantValue, 1),
response(mergingParams.minSignificantValue, 2)};
const std::vector<double> v_maxValue = {response(mergingParams.maxSignificantValue, 0),
response(mergingParams.maxSignificantValue, 1),
response(mergingParams.maxSignificantValue, 2)};

highLight.resize(width, height, true, image::RGBfColor(0.f, 0.f, 0.f));
lowLight.resize(width, height, true, image::RGBfColor(0.f, 0.f, 0.f));
Expand All @@ -94,174 +91,107 @@ void hdrMerge::process(const std::vector< image::Image<image::RGBfColor> > &imag
{
for(int x = 0; x < width; ++x)
{
//for each pixels
image::RGBfColor& radianceColor = radiance(y, x);
image::RGBfColor& highLightColor = highLight(y, x);
image::RGBfColor& lowLightColor = lowLight(y, x);
image::RGBfColor& noMidLightColor = noMidLight(y, x);

//if ((x%1000 == 650) && (y%1000 == 850))
//{
// if(!file)
// {
// ALICEVISION_LOG_WARNING("Unable to create file " << mergeInfoFilename << " for storing merging info.");
// }
// else
// {
// file << x << "," << y << std::endl;
// file << "time,R,resp(R),coeff,resp(R)/time,G,resp(G),coeff,resp(G)/time,B,resp(B),coeff,resp(B)/time," << std::endl;
// for(std::size_t i = 0; i < images.size(); i++)
// {
// const double time = times[i];
// file << time << ",";
// for(std::size_t channel = 0; channel < 3; ++channel)
// {
// const double value = images[i](y, x)(channel);
// const double r = response(value, channel);
// double w = std::max(0.001f, (i == 0) ? weightShortestExposure(value, channel)
// : (i == (images.size() - 1) ? weightLongestExposure(value, channel)
// : weight(value, channel)));

// file << value << ",";
// file << r << ",";
// file << w << ",";
// file << r/time << ",";
// }
// file << std::endl;
// }

// }
//}

const double meanValueHighExp = (images[images.size() - 1](y, x)(0) + images[images.size() - 1](y, x)(1) +
images[images.size() - 1](y, x)(2)) /
3.0;

if(meanValueHighExp < mergingParams.noiseThreshold) // Noise case
{
for(std::size_t channel = 0; channel < 3; ++channel)
{
radianceColor(channel) = mergingParams.targetCameraExposure * response(meanValueHighExp, channel) / times[images.size() - 1];
highLightColor(channel) = 0.0;
lowLightColor(channel) = 1.0;
noMidLightColor(channel) = 0.0;
}
}
else
{
std::vector<std::vector<double>> vv_coeff;
std::vector<std::vector<double>> vv_value;
std::vector<std::vector<double>> vv_normalizedValue;

// Compute merging range
std::vector<int> v_firstIndex;
std::vector<int> v_lastIndex;
for(std::size_t channel = 0; channel < 3; ++channel)
{
int firstIndex = mergingParams.refImageIndex;
while(firstIndex > 0 && (response(images[firstIndex](y, x)(channel), channel) > v_minValue[channel] ||
firstIndex == images.size() - 1))
{
firstIndex--;
}
v_firstIndex.push_back(firstIndex);

int lastIndex = v_firstIndex[channel] + 1;
while(lastIndex < images.size() - 1 && response(images[lastIndex](y, x)(channel), channel) < v_maxValue[channel])
{
lastIndex++;
}
v_lastIndex.push_back(lastIndex);
}

// Compute merging coeffs and values to be merged
for(std::size_t channel = 0; channel < 3; ++channel)
{
std::vector<double> v_coeff;
std::vector<double> v_normalizedValue;
std::vector<double> v_value;

{
const double value = response(images[0](y, x)(channel), channel);
const double normalizedValue = value / times[0];
double coeff = std::max(0.001f, weightShortestExposure(value, channel));

v_value.push_back(value);
v_normalizedValue.push_back(normalizedValue);
v_coeff.push_back(coeff);
}

for(std::size_t e = 1; e < images.size() - 1; e++)
{
const double value = response(images[e](y, x)(channel), channel);
const double normalizedValue = value / times[e];
double coeff = std::max(0.001f, weight(value, channel));

v_value.push_back(value);
v_normalizedValue.push_back(normalizedValue);
v_coeff.push_back(coeff);
}

{
const double value = response(images[images.size() - 1](y, x)(channel), channel);
const double normalizedValue = value / times[images.size() - 1];
double coeff = std::max(0.001f, weightLongestExposure(value, channel));

v_value.push_back(value);
v_normalizedValue.push_back(normalizedValue);
v_coeff.push_back(coeff);
}

vv_coeff.push_back(v_coeff);
vv_normalizedValue.push_back(v_normalizedValue);
vv_value.push_back(v_value);
}

// Compute light masks if required (monitoring and debug purposes)
if(mergingParams.computeLightMasks)
{
for(std::size_t channel = 0; channel < 3; ++channel)
{
int idxMaxValue = 0;
int idxMinValue = 0;
double maxValue = 0.0;
double minValue = 10000.0;
bool jump = true;
for(std::size_t e = 0; e < images.size(); ++e)
{
if(vv_value[channel][e] > maxValue)
{
maxValue = vv_value[channel][e];
idxMaxValue = e;
}
if(vv_value[channel][e] < minValue)
{
minValue = vv_value[channel][e];
idxMinValue = e;
}
jump = jump && ((vv_value[channel][e] < 0.1 && e < images.size() - 1) ||
(vv_value[channel][e] > 0.9 && e > 0));
}
highLightColor(channel) = minValue > 0.9 ? 1.0 : 0.0;
lowLightColor(channel) = maxValue < 0.1 ? 1.0 : 0.0;
noMidLightColor(channel) = jump ? 1.0 : 0.0;
}
}

// Compute the final result and adjust the exposure to the reference one.
for(std::size_t channel = 0; channel < 3; ++channel)
{
double v = 0.0;
double sumCoeff = 0.0;
for(std::size_t i = v_firstIndex[channel]; i <= v_lastIndex[channel]; ++i)
{
v += vv_coeff[channel][i] * vv_normalizedValue[channel][i];
sumCoeff += vv_coeff[channel][i];
}
radianceColor(channel) = mergingParams.targetCameraExposure *
(sumCoeff != 0.0 ? v / sumCoeff : vv_normalizedValue[channel][mergingParams.refImageIndex]);
}
}
//for each pixels
image::RGBfColor& radianceColor = radiance(y, x);
image::RGBfColor& highLightColor = highLight(y, x);
image::RGBfColor& lowLightColor = lowLight(y, x);
image::RGBfColor& noMidLightColor = noMidLight(y, x);

std::vector<std::vector<double>> vv_coeff;
std::vector<std::vector<double>> vv_value;
std::vector<std::vector<double>> vv_normalizedValue;

// Compute merging range
std::vector<int> v_firstIndex;
std::vector<int> v_lastIndex;
for(std::size_t channel = 0; channel < 3; ++channel)
{
int firstIndex = mergingParams.refImageIndex;
while(firstIndex > 0 && (response(images[firstIndex](y, x)(channel), channel) > v_minValue[channel] ||
firstIndex == images.size() - 1))
{
firstIndex--;
}
v_firstIndex.push_back(firstIndex);

int lastIndex = v_firstIndex[channel] + 1;
while(lastIndex < images.size() - 1 && response(images[lastIndex](y, x)(channel), channel) < v_maxValue[channel])
{
lastIndex++;
}
v_lastIndex.push_back(lastIndex);
}

// Compute merging coeffs and values to be merged
for(std::size_t channel = 0; channel < 3; ++channel)
{
std::vector<double> v_coeff;
std::vector<double> v_normalizedValue;
std::vector<double> v_value;

for(std::size_t e = 0; e < images.size(); ++e)
{
const double value = images[e](y, x)(channel);
const double resp = response(value, channel);
const double normalizedValue = resp / times[e];
double coeff = std::max(0.001f, e == 0 ? weightShortestExposure(value, channel) :
(e == images.size() - 1 ? weightLongestExposure(value, channel) :
weight(value, channel)));

v_value.push_back(value);
v_normalizedValue.push_back(normalizedValue);
v_coeff.push_back(coeff);
}

vv_coeff.push_back(v_coeff);
vv_normalizedValue.push_back(v_normalizedValue);
vv_value.push_back(v_value);
}

// Compute light masks if required (monitoring and debug purposes)
if(mergingParams.computeLightMasks)
{
for(std::size_t channel = 0; channel < 3; ++channel)
{
int idxMaxValue = 0;
int idxMinValue = 0;
double maxValue = 0.0;
double minValue = 10000.0;
bool jump = true;
for(std::size_t e = 0; e < images.size(); ++e)
{
if(vv_value[channel][e] > maxValue)
{
maxValue = vv_value[channel][e];
idxMaxValue = e;
}
if(vv_value[channel][e] < minValue)
{
minValue = vv_value[channel][e];
idxMinValue = e;
}
jump = jump && ((vv_value[channel][e] < mergingParams.minSignificantValue && e < images.size() - 1) ||
(vv_value[channel][e] > mergingParams.maxSignificantValue && e > 0));
}
highLightColor(channel) = minValue > mergingParams.maxSignificantValue ? 1.0 : 0.0;
lowLightColor(channel) = maxValue < mergingParams.minSignificantValue ? 1.0 : 0.0;
noMidLightColor(channel) = jump ? 1.0 : 0.0;
}
}

// Compute the final result and adjust the exposure to the reference one.
for(std::size_t channel = 0; channel < 3; ++channel)
{
double v = 0.0;
double sumCoeff = 0.0;
for(std::size_t i = v_firstIndex[channel]; i <= v_lastIndex[channel]; ++i)
{
v += vv_coeff[channel][i] * vv_normalizedValue[channel][i];
sumCoeff += vv_coeff[channel][i];
}
radianceColor(channel) = mergingParams.targetCameraExposure *
(sumCoeff != 0.0 ? v / sumCoeff : vv_normalizedValue[channel][mergingParams.refImageIndex]);
}
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/aliceVision/hdr/hdrMerge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ struct MergingParams
{
double minSignificantValue = 0.05;
double maxSignificantValue = 0.995;
double noiseThreshold = 0.1;
float targetCameraExposure;
int refImageIndex;
bool computeLightMasks = false;
Expand Down
33 changes: 0 additions & 33 deletions src/software/pipeline/main_LdrToHdrMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ int aliceVision_main(int argc, char** argv)
int channelQuantizationPower = 10;
int offsetRefBracketIndex = 1000; // By default, use the automatic selection
double meanTargetedLumaForMerging = 0.4;
double noiseThreshold = 0.1;
double minSignificantValue = 0.05;
double maxSignificantValue = 0.995;
bool computeLightMasks = false;
Expand Down Expand Up @@ -122,8 +121,6 @@ int aliceVision_main(int argc, char** argv)
"Zero to use the center bracket. +N to use a more exposed bracket or -N to use a less exposed backet.")
("meanTargetedLumaForMerging", po::value<double>(&meanTargetedLumaForMerging)->default_value(meanTargetedLumaForMerging),
"Mean expected luminance after merging step when input LDR images are decoded in sRGB color space. Must be in the range [0, 1].")
("noiseThreshold", po::value<double>(&noiseThreshold)->default_value(noiseThreshold),
"Value under which input channel value is considered as noise. Used in advanced pixelwise merging.")
("minSignificantValue", po::value<double>(&minSignificantValue)->default_value(minSignificantValue),
"Minimum channel input value to be considered in advanced pixelwise merging. Used in advanced pixelwise merging.")
("maxSignificantValue", po::value<double>(&maxSignificantValue)->default_value(maxSignificantValue),
Expand Down Expand Up @@ -377,7 +374,6 @@ int aliceVision_main(int argc, char** argv)
hdr::MergingParams mergingParams;
mergingParams.targetCameraExposure = targetCameraSetting.getExposure();
mergingParams.refImageIndex = estimatedTargetIndex;
mergingParams.noiseThreshold = noiseThreshold;
mergingParams.minSignificantValue = minSignificantValue;
mergingParams.maxSignificantValue = maxSignificantValue;
mergingParams.computeLightMasks = computeLightMasks;
Expand All @@ -394,35 +390,6 @@ int aliceVision_main(int argc, char** argv)
HDRimage = images[0];
}

//for (int x = 252; x < 7000; x += 1000)
//{
// for (int y = 750; y < 4000; y += 1000)
// {
// for(int l = x - 10; l <= x + 11; l++)
// {
// image::RGBfColor& pix1 = HDRimage(y - 10, l);
// pix1[0] = 1.f;
// pix1[1] = 0.f;
// pix1[2] = 0.f;
// image::RGBfColor& pix2 = HDRimage(y + 11, l);
// pix2[0] = 1.f;
// pix2[1] = 0.f;
// pix2[2] = 0.f;
// }
// for(int c = y - 10; c <= y + 11; c++)
// {
// image::RGBfColor& pix1 = HDRimage(c, x - 10);
// pix1[0] = 1.f;
// pix1[1] = 0.f;
// pix1[2] = 0.f;
// image::RGBfColor& pix2 = HDRimage(c, x + 11);
// pix2[0] = 1.f;
// pix2[1] = 0.f;
// pix2[2] = 0.f;
// }
// }
//}

boost::filesystem::path p(targetView->getImagePath());
const std::string hdrImagePath = getHdrImagePath(outputPath, g, keepSourceImageName ? p.stem().string() : "");

Expand Down

0 comments on commit 90104f6

Please sign in to comment.