Skip to content

Commit cbbbd5d

Browse files
demoulinvcbentejac
authored andcommitted
Add support of a specific hdr bracketing pattern
1 parent 71c98e0 commit cbbbd5d

File tree

1 file changed

+136
-24
lines changed

1 file changed

+136
-24
lines changed

src/aliceVision/hdr/brackets.cpp

Lines changed: 136 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,8 @@ int selectTargetViews(std::vector<std::shared_ptr<sfmData::View>>& targetViews,
184184
return targetIndex;
185185
}
186186

187-
std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<LuminanceInfo> & luminanceInfos)
187+
std::vector<LuminanceInfo> correctPaths(const std::vector<LuminanceInfo> & luminanceInfos)
188188
{
189-
std::vector<std::vector<LuminanceInfo>> splitted;
190-
191-
if (luminanceInfos.size() == 0)
192-
{
193-
return splitted;
194-
}
195-
196189
//Ignore non existing files
197190
//Remove relative paths
198191
//Remove symlinks
@@ -210,6 +203,19 @@ std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<Luminance
210203

211204
correctedPaths.push_back(corrected);
212205
}
206+
return correctedPaths;
207+
}
208+
209+
std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<LuminanceInfo> & luminanceInfos)
210+
{
211+
std::vector<std::vector<LuminanceInfo>> splitted;
212+
213+
if (luminanceInfos.size() == 0)
214+
{
215+
return splitted;
216+
}
217+
218+
std::vector<LuminanceInfo> correctedPaths = correctPaths(luminanceInfos);
213219

214220
//Sort luminanceinfos by names
215221
std::sort(correctedPaths.begin(),
@@ -317,7 +323,7 @@ int extractIndex(const std::vector<LuminanceInfo> & smaller, const std::vector<L
317323
int diff = largerSize - smallerSize;
318324

319325
//For all continuous subparts of the erased sequence
320-
for (int indexStart = 0; indexStart < diff; indexStart++)
326+
for (int indexStart = 0; indexStart <= diff; indexStart++)
321327
{
322328
//Check that the subpart is the same set of exposures
323329
bool allCorrect = true;
@@ -450,27 +456,133 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
450456
}
451457
}
452458

453-
//check coherency
454-
bool coherency = true;
455-
for (int idref = 1; idref < monotonics.size(); ++idref)
459+
// In some cases (some Nikon cameras for instance) the medium exposure is at the first position of the ldr images group.
460+
// Check that case and try to insert the resulting luminanceInfos seen as outliers at the mid index in the correponding groups.
461+
if ((luminanceInfos.size() - monotonics.size() * monotonics[0].size() >= monotonics.size()) && // at least as many remaining outliers as groups
462+
(monotonics[0].size() % 2 == 0)) // Even number of ldr images in a group
456463
{
457-
const int idprev = idref - 1;
458-
for (int idExposure = 0; idExposure < monotonics[idref].size(); ++idExposure)
464+
465+
//Sort luminanceinfos by names
466+
std::vector<LuminanceInfo> LumInfoCorrectPath = correctPaths(luminanceInfos);
467+
std::sort(LumInfoCorrectPath.begin(),
468+
LumInfoCorrectPath.end(),
469+
[](const LuminanceInfo& a, const LuminanceInfo& b) -> bool {
470+
return (a.mpath < b.mpath);
471+
});
472+
473+
// Extract remaining outliers (all the images in the original list that don't belong to a group)
474+
std::vector<LuminanceInfo> outliers;
475+
for (const auto & li: LumInfoCorrectPath)
476+
{
477+
bool notInMonotonics = true;
478+
int idx = 0;
479+
while (notInMonotonics && idx < monotonics.size())
480+
{
481+
int idxl = 0;
482+
while (notInMonotonics && idxl < monotonics[idx].size())
483+
{
484+
notInMonotonics = !(monotonics[idx][idxl].mpath == li.mpath);
485+
idxl++;
486+
}
487+
idx++;
488+
}
489+
if (notInMonotonics)
490+
{
491+
outliers.push_back(li);
492+
}
493+
}
494+
495+
// Check if for all groups we can find an outlier located just before the first item of the group in the global list
496+
// sorted by name and with a mexposure in between the two middle items of the group
497+
498+
std::vector<int> firstGroupItemPositions;
499+
for (int idxg = 0; idxg < monotonics.size(); ++idxg)
459500
{
460-
if (!(monotonics[idref][idExposure].mexposure == monotonics[idprev][idExposure].mexposure))
501+
int pos = 0;
502+
while (LumInfoCorrectPath[pos].mpath != monotonics[idxg][0].mpath && pos < LumInfoCorrectPath.size())
461503
{
462-
ALICEVISION_LOG_WARNING("Non consistent exposures between poses have been detected.\
463-
Most likely the dataset has been captured with an automatic exposure mode enabled.\
464-
Final result can be impacted.");
465-
coherency = false;
466-
467-
break;
504+
pos++;
468505
}
506+
firstGroupItemPositions.push_back(pos);
469507
}
508+
// The nth item of firstGroupItemPositions is the position in the global list sorted by name of the first element of the nth group
509+
470510

471-
if (!coherency)
511+
LuminanceInfo emptyLumInfo(0, "", 0.0);
512+
std::vector<LuminanceInfo> lumInfosToBeAdded(monotonics.size(), emptyLumInfo);
513+
514+
for (const auto & item: outliers)
472515
{
473-
break;
516+
int pos = 0;
517+
while (LumInfoCorrectPath[pos].mpath != item.mpath && pos < LumInfoCorrectPath.size())
518+
{
519+
pos++;
520+
}
521+
int idx = 0;
522+
while (firstGroupItemPositions[idx] != pos + 1 && idx < firstGroupItemPositions.size())
523+
{
524+
idx++;
525+
}
526+
if (idx < firstGroupItemPositions.size())
527+
{
528+
lumInfosToBeAdded[idx] = item;
529+
}
530+
}
531+
532+
// Check that all candidate have the same mexposure value in the right range
533+
const float mexpRef = lumInfosToBeAdded[0].mexposure;
534+
const int groupSize = monotonics[0].size();
535+
const float mexpMin = monotonics[0][groupSize/2 - 1].mexposure;
536+
const float mexpMax = monotonics[0][groupSize/2].mexposure;
537+
bool lumInfosToBeAddedIsValid = mexpMin < mexpRef && mexpRef < mexpMax;
538+
if (lumInfosToBeAddedIsValid)
539+
{
540+
for (int idx = 1; idx < lumInfosToBeAdded.size(); ++idx)
541+
{
542+
lumInfosToBeAddedIsValid = lumInfosToBeAddedIsValid && lumInfosToBeAdded[idx].mexposure == mexpRef;
543+
}
544+
if (lumInfosToBeAddedIsValid)
545+
{
546+
// Add candidate outliers at the mid position of the corresponding group
547+
for (int idx = 0; idx < lumInfosToBeAdded.size(); ++idx)
548+
{
549+
std::vector<LuminanceInfo>::iterator mid = monotonics[idx].begin() + groupSize / 2;
550+
monotonics[idx].insert(mid, lumInfosToBeAdded[idx]);
551+
}
552+
}
553+
}
554+
}
555+
556+
//check coherency
557+
bool coherency = monotonics.size() * monotonics[0].size() <= luminanceInfos.size();
558+
if (!coherency)
559+
{
560+
ALICEVISION_LOG_WARNING("Non coherent number of ldr images per group.\
561+
Most likely the original ldr image set was split incorrectly.\
562+
Final result can be impacted.");
563+
}
564+
else
565+
{
566+
for (int idref = 1; idref < monotonics.size(); ++idref)
567+
{
568+
const int idprev = idref - 1;
569+
for (int idExposure = 0; idExposure < monotonics[idref].size(); ++idExposure)
570+
{
571+
if (!(monotonics[idref][idExposure].mexposure == monotonics[idprev][idExposure].mexposure))
572+
{
573+
ALICEVISION_LOG_WARNING("Non consistent exposures between poses have been detected.\
574+
Most likely the dataset has been captured with an automatic exposure mode enabled.\
575+
Final result can be impacted.");
576+
coherency = false;
577+
578+
break;
579+
}
580+
}
581+
582+
if (!coherency)
583+
{
584+
break;
585+
}
474586
}
475587
}
476588

@@ -484,7 +596,7 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
484596
groups.push_back(group);
485597
}
486598

487-
ALICEVISION_LOG_INFO("Groups found : " << monotonics.size());
599+
ALICEVISION_LOG_INFO(monotonics.size() << " group(s) of " << monotonics[0].size() << " bracket(s) found");
488600

489601
return groups;
490602
}

0 commit comments

Comments
 (0)