Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non monotonic HDR bracketing pattern support #1832

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 199 additions & 24 deletions src/aliceVision/hdr/brackets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,8 @@
return targetIndex;
}

std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<LuminanceInfo> & luminanceInfos)
std::vector<LuminanceInfo> correctPaths(const std::vector<LuminanceInfo> & luminanceInfos)
{
std::vector<std::vector<LuminanceInfo>> splitted;

if (luminanceInfos.size() == 0)
{
return splitted;
}

//Ignore non existing files
//Remove relative paths
//Remove symlinks
Expand All @@ -210,6 +203,19 @@

correctedPaths.push_back(corrected);
}
return correctedPaths;
}

std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<LuminanceInfo> & luminanceInfos)
{
std::vector<std::vector<LuminanceInfo>> splitted;

if (luminanceInfos.size() == 0)
{
return splitted;
}

std::vector<LuminanceInfo> correctedPaths = correctPaths(luminanceInfos);

//Sort luminanceinfos by names
std::sort(correctedPaths.begin(),
Expand Down Expand Up @@ -244,72 +250,135 @@
return splitted;
}

std::vector<std::vector<LuminanceInfo>> splitMonotonics(const std::vector<LuminanceInfo> & luminanceInfos)
{
std::vector<std::vector<LuminanceInfo>> splitted;

if (luminanceInfos.size() == 0)
{
return splitted;
}

// Check the specific case of 2 items per group without outlier
if (luminanceInfos.size() % 2 == 0)
{
float exp0 = luminanceInfos[0].mexposure;
float exp1 = luminanceInfos[1].mexposure;
if (exp0 != exp1)
{
int idx = 2;
bool ok = true;
while (ok && idx < luminanceInfos.size())
{
ok = ok && luminanceInfos[idx].mexposure == exp0 && luminanceInfos[idx+1].mexposure == exp1;
idx += 2;
}
if (idx == luminanceInfos.size())
{
std::vector<LuminanceInfo> current;
for (int i = 0; i < luminanceInfos.size(); i++)
{
current.push_back(luminanceInfos[i]);
if (i % 2 == 1)
{
splitted.push_back(current);
current.clear();
}
}
return splitted;
}
}
}

// Check the corner case of 3 items per group ordered with middle exposure first and without outlier
if (luminanceInfos.size() % 3 == 0)
{
float exp0 = luminanceInfos[0].mexposure;
float exp1 = luminanceInfos[1].mexposure;
float exp2 = luminanceInfos[2].mexposure;
if (exp0 > exp1 && exp0 < exp2 || exp0 < exp1 && exp0 > exp2)
{
int idx = 3;
bool ok = true;
while (ok && idx < luminanceInfos.size())
{
ok = ok && luminanceInfos[idx].mexposure == exp0 && luminanceInfos[idx+1].mexposure == exp1 && luminanceInfos[idx+2].mexposure == exp2;
idx += 3;
}
if (idx == luminanceInfos.size())
{
std::vector<LuminanceInfo> current;
for (int i = 0; i < luminanceInfos.size(); i++)
{
current.push_back(luminanceInfos[i]);
if (i % 3 == 2)
{
splitted.push_back(current);
current.clear();
}
}
return splitted;
}
}
}

//Split the luminanceInfos into groups which have monotonic values
//(either increasing or decreasing)
std::vector<LuminanceInfo> current;
current.push_back(luminanceInfos[0]);
for (int index = 1; index < luminanceInfos.size(); index++)
{
float val = luminanceInfos[index].mexposure;
float prev = luminanceInfos[index - 1].mexposure;


if (val == prev)
{
splitted.push_back(current);

current.clear();
current.push_back(luminanceInfos[index]);
continue;
}

if (index + 1 == luminanceInfos.size())
{
current.push_back(luminanceInfos[index]);
continue;
}

float next = luminanceInfos[index + 1].mexposure;

//If sign is negative, then the function is not locally monotonic
float sign = (next - val) * (val - prev);

if (sign < 0)
{
current.push_back(luminanceInfos[index]);
splitted.push_back(current);
current.clear();
//Extremity is added on both groups
current.push_back(luminanceInfos[index]);
}
else
{
current.push_back(luminanceInfos[index]);
}
}

//Close the last group
splitted.push_back(current);

return splitted;
}

/**
* @brief assume ref is smaller than larger
* Try to find a subpart of larger which has the same set of exposures that smaller
* @param smaller the set to compare
* @param larger the set where the subpart should be
* @return the index of the subpart or -1 if not found
*/

Check notice on line 381 in src/aliceVision/hdr/brackets.cpp

View check run for this annotation

codefactor.io / CodeFactor

src/aliceVision/hdr/brackets.cpp#L253-L381

Complex Method
int extractIndex(const std::vector<LuminanceInfo> & smaller, const std::vector<LuminanceInfo> & larger)
{
int largerSize = larger.size();
Expand All @@ -317,7 +386,7 @@
int diff = largerSize - smallerSize;

//For all continuous subparts of the erased sequence
for (int indexStart = 0; indexStart < diff; indexStart++)
for (int indexStart = 0; indexStart <= diff; indexStart++)
{
//Check that the subpart is the same set of exposures
bool allCorrect = true;
Expand Down Expand Up @@ -450,27 +519,133 @@
}
}

//check coherency
bool coherency = true;
for (int idref = 1; idref < monotonics.size(); ++idref)
// In some cases (some Nikon cameras for instance) the medium exposure is at the first position of the ldr images group.
// Check that case and try to insert the resulting luminanceInfos seen as outliers at the mid index in the correponding groups.
if ((luminanceInfos.size() - monotonics.size() * monotonics[0].size() >= monotonics.size()) && // at least as many remaining outliers as groups
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

monotonics[0].size() <--> bestBracketCount ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same think because above in the code, all groups with different size from bestBracketCount are removed.

(monotonics[0].size() % 2 == 0)) // Even number of ldr images in a group
{
const int idprev = idref - 1;
for (int idExposure = 0; idExposure < monotonics[idref].size(); ++idExposure)

//Sort luminanceinfos by names
std::vector<LuminanceInfo> LumInfoCorrectPath = correctPaths(luminanceInfos);
std::sort(LumInfoCorrectPath.begin(),
LumInfoCorrectPath.end(),
[](const LuminanceInfo& a, const LuminanceInfo& b) -> bool {
return (a.mpath < b.mpath);
});

// Extract remaining outliers (all the images in the original list that don't belong to a group)
std::vector<LuminanceInfo> outliers;
for (const auto & li: LumInfoCorrectPath)
{
bool notInMonotonics = true;
int idx = 0;
while (notInMonotonics && idx < monotonics.size())
{
int idxl = 0;
while (notInMonotonics && idxl < monotonics[idx].size())
{
notInMonotonics = !(monotonics[idx][idxl].mpath == li.mpath);
idxl++;
}
idx++;
}
if (notInMonotonics)
{
outliers.push_back(li);
}
}

// Check if for all groups we can find an outlier located just before the first item of the group in the global list
// sorted by name and with a mexposure in between the two middle items of the group

std::vector<int> firstGroupItemPositions;
for (int idxg = 0; idxg < monotonics.size(); ++idxg)
{
if (!(monotonics[idref][idExposure].mexposure == monotonics[idprev][idExposure].mexposure))
int pos = 0;
while (LumInfoCorrectPath[pos].mpath != monotonics[idxg][0].mpath && pos < LumInfoCorrectPath.size())
{
ALICEVISION_LOG_WARNING("Non consistent exposures between poses have been detected.\
Most likely the dataset has been captured with an automatic exposure mode enabled.\
Final result can be impacted.");
coherency = false;

break;
pos++;
}
firstGroupItemPositions.push_back(pos);
}
// The nth item of firstGroupItemPositions is the position in the global list sorted by name of the first element of the nth group


if (!coherency)
LuminanceInfo emptyLumInfo(0, "", 0.0);
std::vector<LuminanceInfo> lumInfosToBeAdded(monotonics.size(), emptyLumInfo);

for (const auto & item: outliers)
{
break;
int pos = 0;
while (LumInfoCorrectPath[pos].mpath != item.mpath && pos < LumInfoCorrectPath.size())
{
pos++;
}
int idx = 0;
while (firstGroupItemPositions[idx] != pos + 1 && idx < firstGroupItemPositions.size())
{
idx++;
}
if (idx < firstGroupItemPositions.size())
{
lumInfosToBeAdded[idx] = item;
}
}

// Check that all candidate have the same mexposure value in the right range
const float mexpRef = lumInfosToBeAdded[0].mexposure;
const int groupSize = monotonics[0].size();
const float mexpMin = monotonics[0][groupSize/2 - 1].mexposure;
const float mexpMax = monotonics[0][groupSize/2].mexposure;
bool lumInfosToBeAddedIsValid = mexpMin < mexpRef && mexpRef < mexpMax;
if (lumInfosToBeAddedIsValid)
{
for (int idx = 1; idx < lumInfosToBeAdded.size(); ++idx)
{
lumInfosToBeAddedIsValid = lumInfosToBeAddedIsValid && lumInfosToBeAdded[idx].mexposure == mexpRef;
}
if (lumInfosToBeAddedIsValid)
{
// Add candidate outliers at the mid position of the corresponding group
for (int idx = 0; idx < lumInfosToBeAdded.size(); ++idx)
{
std::vector<LuminanceInfo>::iterator mid = monotonics[idx].begin() + groupSize / 2;
monotonics[idx].insert(mid, lumInfosToBeAdded[idx]);
}
}
}
}

//check coherency
bool coherency = monotonics.size() * monotonics[0].size() <= luminanceInfos.size();
if (!coherency)
{
ALICEVISION_LOG_WARNING("Non coherent number of ldr images per group.\
Most likely the original ldr image set was split incorrectly.\
Final result can be impacted.");
}
else
{
for (int idref = 1; idref < monotonics.size(); ++idref)
{
const int idprev = idref - 1;
for (int idExposure = 0; idExposure < monotonics[idref].size(); ++idExposure)
{
if (!(monotonics[idref][idExposure].mexposure == monotonics[idprev][idExposure].mexposure))
{
ALICEVISION_LOG_WARNING("Non consistent exposures between poses have been detected.\
Most likely the dataset has been captured with an automatic exposure mode enabled.\
Final result can be impacted.");
coherency = false;

break;
}
}

if (!coherency)
{
break;
}
}
}

Expand All @@ -484,7 +659,7 @@
groups.push_back(group);
}

ALICEVISION_LOG_INFO("Groups found : " << monotonics.size());
ALICEVISION_LOG_INFO(monotonics.size() << " group(s) of " << monotonics[0].size() << " bracket(s) found");

return groups;
}
Expand Down
Loading