Skip to content

Commit 96d18d2

Browse files
committed
Split image set using capture time at first intention
1 parent 94f67d9 commit 96d18d2

File tree

2 files changed

+106
-7
lines changed

2 files changed

+106
-7
lines changed

src/aliceVision/hdr/brackets.cpp

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ bool estimateBracketsFromSfmData(std::vector<std::vector<std::shared_ptr<sfmData
3838
fnumbers.insert(view->getImage().getMetadataFNumber());
3939
double exp = view->getImage().getCameraExposureSetting().getExposure();
4040
std::string path = view->getImage().getImagePath();
41+
int64_t timestamp = view->getImage().getMetadataDateTimestamp();
4142

42-
LuminanceInfo li(viewIt.first, path, exp);
43+
LuminanceInfo li(viewIt.first, path, exp, timestamp);
4344
luminances.push_back(li);
4445
}
4546

@@ -303,6 +304,97 @@ std::vector<std::vector<LuminanceInfo>> splitMonotonics(const std::vector<Lumina
303304
return splitted;
304305
}
305306

307+
std::vector<std::vector<LuminanceInfo>> splitTimes(const std::vector<LuminanceInfo> & luminanceInfos, int maxDeltaInABurst = 2)
308+
{
309+
std::vector<std::vector<LuminanceInfo>> splitted;
310+
311+
if (luminanceInfos.size() == 0)
312+
{
313+
return splitted;
314+
}
315+
316+
// Split the luminanceInfos into groups which have close capture time (burst detection)
317+
std::vector<LuminanceInfo> normedTimes(luminanceInfos);
318+
// Sort luminanceinfos by timestamp
319+
std::sort(normedTimes.begin(),
320+
normedTimes.end(),
321+
[](const LuminanceInfo& a, const LuminanceInfo& b) -> bool {
322+
return (a.mtimestamp < b.mtimestamp);
323+
});
324+
325+
const int histoSize = maxDeltaInABurst + 2;
326+
std::vector<int> histo(histoSize, 0);
327+
for (int i = normedTimes.size() - 1; i >= 1; i--)
328+
{
329+
normedTimes[i].mtimestamp -= normedTimes[i - 1].mtimestamp;
330+
histo[std::min(maxDeltaInABurst + 1, (int)normedTimes[i].mtimestamp)]++;
331+
}
332+
normedTimes[0].mtimestamp = 0;
333+
334+
// Check for outliers at both sides of the sequence.
335+
// At the beginning an item is an outlier if the next one has been captured more than maxDeltaInABurst seconds after.
336+
// At the end an item is an outlier if the previous one has been captured more than maxDeltaInABurst seconds before.
337+
int firstIndexValid = 0;
338+
while (normedTimes[firstIndexValid + 1].mtimestamp > maxDeltaInABurst && firstIndexValid < normedTimes.size() - 1)
339+
{
340+
firstIndexValid++;
341+
}
342+
if (firstIndexValid == normedTimes.size() - 1)
343+
{
344+
return splitted;
345+
}
346+
int LastIndexValid = normedTimes.size() - 1;
347+
while (normedTimes[LastIndexValid].mtimestamp > maxDeltaInABurst && LastIndexValid > firstIndexValid)
348+
{
349+
LastIndexValid--;
350+
}
351+
if (LastIndexValid == firstIndexValid)
352+
{
353+
return splitted;
354+
}
355+
356+
int outlierNumber = firstIndexValid + (normedTimes.size() - 1 - LastIndexValid);
357+
358+
int nbItemLow = 0;
359+
for (int i = 0; i <= maxDeltaInABurst ; i++)
360+
{
361+
nbItemLow += histo[i];
362+
}
363+
const int nbItemHigh = histo.back();
364+
365+
int nbGroup;
366+
int groupSize;
367+
if (nbItemLow % (nbItemHigh + 1 - outlierNumber) == 0)
368+
{
369+
nbGroup = nbItemHigh + 1 - outlierNumber;
370+
groupSize = (luminanceInfos.size() - outlierNumber) / nbGroup;
371+
std::vector<LuminanceInfo> group;
372+
std::map<float, int> mexposure;
373+
for (int i = firstIndexValid; i <= LastIndexValid ; i++)
374+
{
375+
group.push_back(normedTimes[i]);
376+
mexposure[normedTimes[i].mexposure] = 0;
377+
if (i % groupSize == groupSize - 1)
378+
{
379+
if (mexposure.size() == groupSize)
380+
{
381+
// All group's exposures are different from each others
382+
splitted.push_back(group);
383+
group.clear();
384+
mexposure.clear();
385+
}
386+
else
387+
{
388+
splitted.clear();
389+
break;
390+
}
391+
}
392+
}
393+
}
394+
395+
return splitted;
396+
}
397+
306398
/**
307399
* @brief assume ref is smaller than larger
308400
* Try to find a subpart of larger which has the same set of exposures that smaller
@@ -349,11 +441,15 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
349441

350442
//Split and order the items using path
351443
std::vector<std::vector<LuminanceInfo>> splitted = splitBasedir(luminanceInfos);
352-
//Create monotonic groups
444+
//Create groups
353445
std::vector<std::vector<LuminanceInfo>> monotonics;
354446
for (const auto & luminanceInfoOneDir : splitted)
355447
{
356-
std::vector<std::vector<LuminanceInfo>> lmonotonics = splitMonotonics(luminanceInfoOneDir);
448+
std::vector<std::vector<LuminanceInfo>> lmonotonics = splitTimes(luminanceInfoOneDir);
449+
if (lmonotonics.empty())
450+
{
451+
lmonotonics = splitMonotonics(luminanceInfoOneDir);
452+
}
357453
monotonics.insert(monotonics.end(), lmonotonics.begin(), lmonotonics.end());
358454
}
359455

@@ -426,7 +522,6 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
426522
continue;
427523
}
428524

429-
430525
//Compare with all valid monotonics
431526
int offset = -1;
432527
for (const auto& monotonic : monotonics)
@@ -484,7 +579,9 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
484579
groups.push_back(group);
485580
}
486581

487-
ALICEVISION_LOG_INFO("Groups found : " << monotonics.size());
582+
const int groupNumber = monotonics.size();
583+
const int outlierNumber = luminanceInfos.size() - groupNumber * bestBracketCount;
584+
ALICEVISION_LOG_INFO(groupNumber << " group(s) of " << bestBracketCount << " bracket(s) and " << outlierNumber << " outlier(s) found.");
488585

489586
return groups;
490587
}

src/aliceVision/hdr/brackets.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ struct LuminanceInfo
1717
aliceVision::IndexT mviewId;
1818
std::string mpath;
1919
float mexposure;
20+
int64_t mtimestamp;
2021

2122
LuminanceInfo() = default;
2223

23-
LuminanceInfo(aliceVision::IndexT vid, const std::string & path, float exposure):
24+
LuminanceInfo(aliceVision::IndexT vid, const std::string & path, float exposure, int64_t timestamp):
2425
mviewId(vid),
2526
mpath(path),
26-
mexposure(exposure)
27+
mexposure(exposure),
28+
mtimestamp(timestamp)
2729
{
2830

2931
}

0 commit comments

Comments
 (0)