int main()

in source/conversion/ProjectEquirectsToCameras.cpp [70:133]


int main(int argc, char** argv) {
  gflags::SetUsageMessage(kUsage);
  system_util::initDep(argc, argv);

  CHECK_NE(FLAGS_rig, "");
  Camera::Rig rig = filterDestinations(Camera::loadRig(FLAGS_rig), FLAGS_cameras);

  verifyInputs(rig);
  rescaleCameras(rig);

  const int first = std::stoi(FLAGS_first);
  const int last = std::stoi(FLAGS_last);
  for (int iFrame = first; iFrame <= last; ++iFrame) {
    const std::string frameName = image_util::intToStringZeroPad(iFrame, 6);
    LOG(INFO) << folly::sformat("Frame {}: Loading equirect masks...", frameName);
    const std::vector<cv::Mat_<bool>> eqrMasks = loadImages<bool>(FLAGS_eqr_masks, rig, frameName);
    CHECK_EQ(ssize(eqrMasks), ssize(rig));

    for (ssize_t i = 0; i < ssize(rig); ++i) {
      const Camera& cam = rig[i];
      LOG(INFO) << folly::sformat("-- Frame {}: Projecting to {}...", frameName, cam.id);

      // For each pixel in the current camera find out where in equirect space we land
      ThreadPool threadPool(FLAGS_threads);
      cv::Mat_<bool> camMask(cam.resolution.y(), cam.resolution.x(), false);
      const cv::Mat_<bool>& eqrMask = eqrMasks[i];

      int h = camMask.rows;
      int w = camMask.cols;
      const int edgeX = w;
      const int edgeY = 1;
      for (int yBegin = 0; yBegin < h; yBegin += edgeY) {
        for (int xBegin = 0; xBegin < w; xBegin += edgeX) {
          const int xEnd = std::min(xBegin + edgeX, w);
          const int yEnd = std::min(yBegin + edgeY, h);
          threadPool.spawn([&, xBegin, yBegin, xEnd, yEnd] {
            for (int y = yBegin; y < yEnd; ++y) {
              for (int x = xBegin; x < xEnd; ++x) {
                const Camera::Vector3 world = cam.rig({x + 0.5, y + 0.5}, FLAGS_depth);
                const Camera::Vector2 pEqr =
                    image_util::worldToEquirect(world, eqrMask.cols, eqrMask.rows);
                if (pEqr.x() < 0 || pEqr.y() < 0 || pEqr.x() >= eqrMask.cols ||
                    pEqr.y() >= eqrMask.rows) {
                  continue; // rounding can put us at image edge. Ignore these cases
                }
                if (eqrMask(pEqr.y(), pEqr.x())) {
                  camMask(y, x) = true;
                }
              }
            }
          });
        }
      }
      threadPool.join();

      const filesystem::path filename =
          filesystem::path(FLAGS_output) / cam.id / (frameName + "." + FLAGS_file_type);
      filesystem::create_directories(filename.parent_path());
      cv_util::imwriteExceptionOnFail(filename, 255.0f * camMask);
    }
  }

  return EXIT_SUCCESS;
}