in source/depth_estimation/Derp.cpp [263:381]
void computeBruteForceDisparity(
PyramidLevel<PixelType>& pyramidLevel,
const int dstIdx,
const float minDepthMeters,
const float maxDepthMeters,
const bool partialCoverage,
const bool useForegroundMasks,
const int numThreads) {
cv::Mat_<float>& dstDisparity = pyramidLevel.dstDisparity(dstIdx);
cv::Mat_<float>& dstCosts = pyramidLevel.dstCost(dstIdx);
cv::Mat_<float>& dstConfidences = pyramidLevel.dstConfidence(dstIdx);
LOG(INFO) << "Computing initial costs at " << pyramidLevel.sizeLevel
<< folly::sformat(" ({})", pyramidLevel.rigDst[dstIdx].id);
std::vector<float> disparities(kNumDepths);
const float minDisparity = 1.0f / maxDepthMeters;
const float maxDisparity = 1.0f / minDepthMeters;
for (int i = 0; i < kNumDepths; ++i) {
const float d = probeDisparity(i, kNumDepths, minDisparity, maxDisparity);
disparities[i] = d;
}
// Create a cost map for each possible disparity
ThreadPool threadPool(numThreads);
std::vector<cv::Mat_<float>> costs(disparities.size());
std::vector<cv::Mat_<float>> confidences(disparities.size());
for (int iDisparity = 0; iDisparity < int(disparities.size()); ++iDisparity) {
costs[iDisparity].create(pyramidLevel.sizeLevel);
costs[iDisparity].setTo(NAN);
confidences[iDisparity].create(pyramidLevel.sizeLevel);
confidences[iDisparity].setTo(NAN);
threadPool.spawn(
&computeBruteForceCosts,
std::ref(pyramidLevel),
dstIdx,
disparities[iDisparity],
std::ref(costs[iDisparity]),
std::ref(confidences[iDisparity]));
}
threadPool.join();
// Get best cost on each location
// We have one cost per disparity at each location
// Ignore margins if dst = src (won't be able to get entire patch)
const int margin = kSearchWindowRadius;
for (int y = margin; y < dstDisparity.rows - margin; ++y) {
for (int x = margin; x < dstDisparity.cols - margin; ++x) {
if (!pyramidLevel.dstFovMask(dstIdx)(y, x)) { // outside FOV
dstDisparity(y, x) = NAN;
continue;
}
// Use background value if we're outside the foreground mask
if (!pyramidLevel.dstForegroundMask(dstIdx)(y, x)) {
dstDisparity(y, x) = pyramidLevel.dstBackgroundDisparity(dstIdx)(y, x);
continue;
}
float minCost = FLT_MAX;
float minCostConfidence = 0;
int bestDisparityIdx = -1;
for (int i = 0; i < int(costs.size()); ++i) {
const float cost = costs[i](y, x);
if (cost < minCost) {
minCost = cost;
minCostConfidence = confidences[i](y, x);
bestDisparityIdx = i;
}
}
if (bestDisparityIdx == -1) {
// This can only happen if we're outside the overlapping area when we
// have partial coverage or due to noise in foreground masks
std::string warning = folly::sformat(
"Insufficient coverage at {} ({}, {}) ", pyramidLevel.rigDst[dstIdx].id, x, y);
CHECK(partialCoverage || useForegroundMasks) << warning;
const std::string partialCoverageFailure = "due to partial coverage";
const std::string foregroundMaskFailure = "due to noisy foreground masks";
warning += partialCoverage ? partialCoverageFailure : "";
warning += (partialCoverage && useForegroundMasks) ? " or " : "";
warning += useForegroundMasks ? foregroundMaskFailure : "";
LOG(WARNING) << warning;
dstDisparity(y, x) = minDisparity;
} else {
dstDisparity(y, x) = disparities[bestDisparityIdx];
}
dstCosts(y, x) = minCost;
dstConfidences(y, x) = minCostConfidence;
}
}
// Extend disparities to margin
if (margin > 0) {
for (int y = 0; y < dstDisparity.rows; ++y) {
for (int x = 0; x < dstDisparity.cols; ++x) {
if (x < margin || x >= dstDisparity.cols - margin || y < margin ||
y >= dstDisparity.rows - margin) {
// Use background value if we're outside the foreground mask
if (!pyramidLevel.dstForegroundMask(dstIdx)(y, x)) {
dstDisparity(y, x) = pyramidLevel.dstBackgroundDisparity(dstIdx)(y, x);
continue;
}
dstDisparity(y, x) = dstDisparity(
math_util::clamp(y, margin, dstDisparity.rows - margin - 1),
math_util::clamp(x, margin, dstDisparity.cols - margin - 1));
dstCosts(y, x) = dstCosts(
math_util::clamp(y, margin, dstCosts.rows - margin - 1),
math_util::clamp(x, margin, dstCosts.cols - margin - 1));
dstConfidences(y, x) = dstConfidences(
math_util::clamp(y, margin, dstConfidences.rows - margin - 1),
math_util::clamp(x, margin, dstConfidences.cols - margin - 1));
}
}
}
}
}