@@ -184,15 +184,8 @@ int selectTargetViews(std::vector<std::shared_ptr<sfmData::View>>& targetViews,
184
184
return targetIndex;
185
185
}
186
186
187
- std::vector<std::vector< LuminanceInfo>> splitBasedir (const std::vector<LuminanceInfo> & luminanceInfos)
187
+ std::vector<LuminanceInfo> correctPaths (const std::vector<LuminanceInfo> & luminanceInfos)
188
188
{
189
- std::vector<std::vector<LuminanceInfo>> splitted;
190
-
191
- if (luminanceInfos.size () == 0 )
192
- {
193
- return splitted;
194
- }
195
-
196
189
// Ignore non existing files
197
190
// Remove relative paths
198
191
// Remove symlinks
@@ -210,6 +203,19 @@ std::vector<std::vector<LuminanceInfo>> splitBasedir(const std::vector<Luminance
210
203
211
204
correctedPaths.push_back (corrected);
212
205
}
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);
213
219
214
220
// Sort luminanceinfos by names
215
221
std::sort (correctedPaths.begin (),
@@ -317,7 +323,7 @@ int extractIndex(const std::vector<LuminanceInfo> & smaller, const std::vector<L
317
323
int diff = largerSize - smallerSize;
318
324
319
325
// For all continuous subparts of the erased sequence
320
- for (int indexStart = 0 ; indexStart < diff; indexStart++)
326
+ for (int indexStart = 0 ; indexStart <= diff; indexStart++)
321
327
{
322
328
// Check that the subpart is the same set of exposures
323
329
bool allCorrect = true ;
@@ -450,27 +456,133 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
450
456
}
451
457
}
452
458
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
456
463
{
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)
459
500
{
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 ())
461
503
{
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++;
468
505
}
506
+ firstGroupItemPositions.push_back (pos);
469
507
}
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
+
470
510
471
- if (!coherency)
511
+ LuminanceInfo emptyLumInfo (0 , " " , 0.0 );
512
+ std::vector<LuminanceInfo> lumInfosToBeAdded (monotonics.size (), emptyLumInfo);
513
+
514
+ for (const auto & item: outliers)
472
515
{
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
+ }
474
586
}
475
587
}
476
588
@@ -484,7 +596,7 @@ std::vector<std::vector<IndexT>> estimateGroups(const std::vector<LuminanceInfo>
484
596
groups.push_back (group);
485
597
}
486
598
487
- ALICEVISION_LOG_INFO (" Groups found : " << monotonics.size ());
599
+ ALICEVISION_LOG_INFO (monotonics. size () << " group(s) of " << monotonics[ 0 ] .size () << " bracket(s) found " );
488
600
489
601
return groups;
490
602
}
0 commit comments