c++ - 有效地计算像素到它们对应的对极线的距离

标签 c++ performance opencv computer-vision

我正在尝试计算立体相机设置中两个对应像素与其各自对极线的距离。我为此目的实现的代码如下所示:

#include <iostream>
#include <vector>
#include <opencv2/calib3d/calib3d.hpp>

float calculateDistanceToEpiLineSum(const cv::Mat2f& left_candidate, const cv::Mat2f& right_candidate, const cv::Matx33f& fundamental_mat) {

  // Calculate epipolar lines
  cv::Mat epiLineRight=cv::Mat(1,3,CV_32FC1);
  cv::Mat epiLineLeft=cv::Mat(1,3,CV_32FC1);
  cv::computeCorrespondEpilines(left_candidate,2,fundamental_mat,epiLineRight);
  cv::computeCorrespondEpilines(right_candidate,1,fundamental_mat,epiLineLeft);

  // Calculate distances of the image points to their corresponding epipolar line
  float distance_left_im=std::abs(epiLineLeft.at<float>(0)*left_candidate[0][0][0]+
                                   epiLineLeft.at<float>(1)*left_candidate[0][0][1]+
                                   epiLineLeft.at<float>(2))/
      std::sqrt(std::pow(epiLineLeft.at<float>(0),2.f)+std::pow(epiLineLeft.at<float>(1),2.f));

  float distance_right_im=std::abs(epiLineRight.at<float>(0)*right_candidate[0][0][0]+
                                   epiLineRight.at<float>(1)*right_candidate[0][0][1]+
                                   epiLineRight.at<float>(2))/
      std::sqrt(std::pow(epiLineRight.at<float>(0),2.f)+std::pow(epiLineRight.at<float>(1),2.f));

  return distance_left_im+distance_right_im;
}

int main()
{
  cv::Matx33f fundamental_mat=cv::Matx33f{-0.000000234008931f,-0.000013193232976f, 0.010025275471910f,
                                          -0.000017896532640f, 0.000009948056751f, 0.414125924093639f,
                                           0.006296743991557f,-0.411007947095269f,-4.695511356888332f};

  cv::Vec2f left_candidate_vec(135.,289.);
  cv::Vec2f right_candidate_vec(205.,311.);
  cv::Mat2f left_candidate(left_candidate_vec);
  cv::Mat2f right_candidate(right_candidate_vec);

  float distance_sum=calculateDistanceToEpiLineSum(left_candidate,right_candidate,fundamental_mat);

  std::cout<<"The sum of the distances equals "<<distance_sum<<" pixels\n";

  return 0;
}

我面临的问题是我可能必须每秒执行此操作数千次。我知道 cv::computeCorrespondEpilines 的第一个输入可以是一个像素 vector ,它允许使用更向量化的方法并且可能会稍微加快速度。问题是,我无法使用它,因为我使用的不是传统相机,而是 event-based sensors因此我将异步接收像素(而不是接收帧)。
现在我想知道以下内容:

  1. calculateDistanceToEpiLineSum 是否存在重大缺陷 以不好的方式影响功能的性能?在这里不使用 OpenCV 函数,而是自己实现 computeCorrespondEpilines 可能是个好主意吗?
  2. 之前我考虑过“离线”计算对极线 节省处理时间。问题是,我不知道我会怎样 有效地计算和保护对极线。我想过 计算每个图像的每个像素的极线和 根据ax+by+c=0将线参数存储在三元组中, 但假设每台摄像机的分辨率为 480x360, 我有两个 480x360x3 的矩阵,这是相当大的。这样做可行吗 无论如何,还是有更好的方法?

最佳答案

如果不知道您的计算约束是什么,就无法回答时间性能问题,因此以下是一个非常粗略的估计。

在底部,计算候选匹配像素对的一个点与其关联的对极线成本的距离粗略:

  • 一个矩阵乘法 = 9 mult, 6 adds = 15 flops
  • 归一化 = 2 mult, 1 add, 1 square root =~ 10 flops
  • 带线系数的点积:3 mult,2 add = 5 flops
  • 分区 =~ 4 次失败

所以这对大约有 70 个翻牌。

这一切在几秒钟内意味着什么,至少取决于您的处理器时钟周期。 Skylake IA64 可以执行 16 个 DP 矢量化触发器/周期,因此称它为 5 个周期。在 3 GHz 时,耗时不到 2 ns。考虑到这一点,我们称其为总共 10 ns。

您说您必须每秒执行“数千次”此计算。以每对 10ns 的速度,您每秒可以完成 1 亿

鉴于上述情况,您确定此特定操作将成为瓶颈,而不是例如来自相机的 I/O(包括图像解码)吗?

忠告:学习使用良好的微基准测试框架来获取硬件的实际性能数据。我推荐好老Google Benchmark .

关于c++ - 有效地计算像素到它们对应的对极线的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58912902/

相关文章:

c++ - 使用 mex : No supported compiler or SDK was found 时出错

c++ - 函数类型的模板对象

c++ - 如果内存占用不是问题,我应该为一个短暂的程序释放内存吗?

opencv - 在 Raspberry Pi 上编译支持 CUDA 的 OpenCV 需要什么包?

python - 如何检测图表区域并从研究论文的图像中提取(裁剪)它

c++ - 来自 C++11 中 C99 的 fenv.h

c++ - 可组合的 C++ 函数装饰器

c# - 如何仅对字符串的一部分进行字符串替换?

performance - 影响 RSA 加密/解密时间的因素

python-2.7 - opencv python2.7实现中的自适应双边滤波器