void randomProposal()

in source/depth_estimation/Derp.cpp [749:823]


void randomProposal(
    PyramidLevel<PixelType>& pyramidLevel,
    const int dstIdx,
    const int y,
    const int numProposals,
    const float minDepthMeters,
    const float maxDepthMeters) {
  std::default_random_engine engine;
  engine.seed(y * pyramidLevel.level);
  cv::Mat_<float>& dstDisparity = pyramidLevel.dstDisparity(dstIdx);
  cv::Mat_<float>& dstCosts = pyramidLevel.dstCost(dstIdx);
  cv::Mat_<float>& dstConfidence = pyramidLevel.dstConfidence(dstIdx);
  const cv::Mat_<float>& variance = pyramidLevel.dstVariance(dstIdx);
  for (int x = kSearchWindowRadius; x < dstDisparity.cols - kSearchWindowRadius; ++x) {
    if (!pyramidLevel.dstFovMask(dstIdx)(y, x)) { // outside FOV
      // Keep value from previous frame
      continue;
    }
    float currDisp = dstDisparity(y, x); // upscaled disparity

    // 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;
    }

    // Ignore locations with low variance
    // Threshold is a little lower than our high variance threshold
    // High variance locations include:
    // - textured objects: easier to match
    // - new objects: not present at coarser levels
    // Lower than high variance locations include:
    // - weaker edges: as they appear or dissapear
    // - pixels around edges: can see what's behind
    // We can go pretty low, as long as we ignore smooth and noisy areas
    const float varHighDev = kRandomPropHighVarDeviation * pyramidLevel.varHighThresh;
    const float varHighThresh = std::max(varHighDev, pyramidLevel.varNoiseFloor);
    if (variance(y, x) < varHighThresh) {
      continue;
    }

    float currCost;
    float currConfidence;
    std::tie(currCost, currConfidence) = computeCost(pyramidLevel, dstIdx, currDisp, x, y);

    // We will refine only if we're getting much better cost
    const float costThresh = std::fmin(0.5f * currCost, kRandomPropMaxCost);

    // When using background, foreground pixels must be closer than background
    const float minDisp = pyramidLevel.hasForegroundMasks
        ? pyramidLevel.dstBackgroundDisparity(dstIdx)(y, x)
        : (1.0f / maxDepthMeters);
    const float maxDisp = 1.0f / minDepthMeters;

    float amplitude = (maxDisp - minDisp) / 2.0f;
    for (int i = 0; i < numProposals; ++i) {
      float propDisp = std::uniform_real_distribution<float>(
          std::max(float(minDisp), currDisp - amplitude),
          std::min(float(maxDisp), currDisp + amplitude))(engine);
      float propCost;
      float propConfidence;
      std::tie(propCost, propConfidence) = computeCost(pyramidLevel, dstIdx, propDisp, x, y);
      if (propCost < currCost && propCost < costThresh) {
        currCost = propCost;
        currDisp = propDisp;
        currConfidence = propConfidence;
        amplitude /= 2.0f;
      }
    }

    dstDisparity(y, x) = currDisp;
    dstCosts(y, x) = currCost;
    dstConfidence(y, x) = currConfidence;
  }
}