in source/calibration/GeometricCalibration.cpp [407:467]
void removeOutliersFromCameras(
std::vector<Overlap>& overlaps,
const FeatureMap& featureMap,
const std::vector<Trace>& traces,
const std::vector<Camera>& cameras,
const Camera::Real outlierFactor) {
// compute reprojection errors for each camera
std::vector<std::vector<Camera::Real>> errors =
reprojectionErrors(overlaps, featureMap, traces, cameras);
// compute median for each camera
std::vector<Camera::Real> medians(ssize(errors));
for (ssize_t i = 0; i < ssize(errors); ++i) {
medians[i] = calcPercentile(errors[i]);
}
std::unordered_map<ImageId, int> outliers;
// remove matches that neither endpoint wants to keep around
std::vector<ssize_t> errorIdxs(ssize(errors), 0);
int total = 0;
int inlierTotal = 0;
for (Overlap& overlap : overlaps) {
if (!overlap.isIntraFrame()) {
continue;
}
const std::reference_wrapper<const ImageId> images[2] = {overlap.images[0], overlap.images[1]};
const int idxs[2] = {getCameraIndex(images[0]), getCameraIndex(images[1])};
// move the inliers to front of overlap.matches and resize to fit
int inliers = 0;
for (const auto& match : overlap.matches) {
bool inlier = false;
for (ssize_t i = 0; i < ssize(match); ++i) {
int cameraIndex = idxs[i];
if (errors[cameraIndex][errorIdxs[cameraIndex]++] < medians[cameraIndex] * outlierFactor) {
inlier = true;
}
}
if (inlier) {
overlap.matches[inliers++] = match;
}
}
outliers[overlap.images[0]] += ssize(overlap.matches) - inliers;
outliers[overlap.images[1]] += ssize(overlap.matches) - inliers;
total += ssize(overlap.matches);
overlap.matches.resize(inliers);
inlierTotal += inliers;
}
// sanity check that we consumed all the errors
for (ssize_t i = 0; i < ssize(errors); ++i) {
CHECK_EQ(errorIdxs[i], ssize(errors[i]));
}
if (FLAGS_log_verbose) {
for (const auto& p : outliers) {
LOG(INFO) << folly::sformat("Removed {} outliers from {}", p.second, p.first);
}
}
LOG(INFO) << folly::sformat("{} of {} matches were inliers", inlierTotal, total);
}