gpt4 book ai didi

opencv - 为什么 SIFT 花费更多的时间和更少的倍频程层?

转载 作者:行者123 更新时间:2023-12-04 07:40:34 25 4
gpt4 key购买 nike

我在 OpenCV 4.5.2 中使用 SIFT 特征检测器.通过调整 nOctaveLayers cv::SIFT::create() 中的参数, 我从 detectAndCompute() 得到这些结果:


无 Octave 层
关键点
时间成本(毫秒)


1
1026
63.41

2
1795
45.07

3
2043
45.74

4
2173
47.83

5
2224
51.86


据我所知, Octave 层数应该更少,但是为什么 SIFT 在只有 1 个倍频程层时要花费更多的时间 ?
我也测试过 detect()compute()分别,当 nOctaveLayers 时,它们都花费更多时间是 1,这让我很困惑。
测试图片为here (来自 TUM 开放数据集)。提前感谢您的帮助。

[为@Micka 编辑] 我的测试代码:

const int test_num = 100;
const int layers = 5;
cout << "layers: " << layers << endl;

auto sift = SIFT::create(0, layers);
vector<KeyPoint> kps;
Mat descs;

auto t1 = chrono::high_resolution_clock::now();
for (int i = 0; i < test_num; ++i)
sift->detectAndCompute(img_src, noArray(), kps, descs);
auto t2 = chrono::high_resolution_clock::now();
cout << "num of kps: " << kps.size() << endl;
cout << "avg time cost: " << chrono::duration<double>(t2 - t1).count() * 1e3 / test_num << endl;
每个 nOctaveLayers配置,我改 layers代码中的值,重新编译并运行并记录结果。

最佳答案

经过几个小时的分析,我终于找到了原因:GaussianBlur .
SIFT算法的流程是:

  • 创建初始图像:将源图像的数据类型转换为 float ,将分辨率加倍,然后执行 GaussianBlur (sigma=1.56)
  • 构建高斯金字塔
  • 寻找关键点:构建DoG金字塔并找到尺度空间极值
  • 计算描述符

  • Octave 音阶的数量是根据图像分辨率计算的(请参阅 here )。和 nOctaveLayers控制每个 Octave 音阶中的层数(高斯金字塔的 nOctaveLayers + 3)。
    确实,当 nOctaveLayers增加,层数和关键点数都增加。结果,步骤 3 和 4 的时间成本增加。但是,在并行计算中,这个时间增量并不是很显着(几毫秒)。
    相比之下, 第2步花费了总时间的一半以上 .当 nOctaveLayers 时花费 25.27 毫秒(43.49 毫秒)为 3,当 nOctaveLayers 时为 51.16 毫秒(63.10 毫秒)是 1. 那么,为什么会发生这种情况?
    因为西格玛为 GaussianBlur()当层数较少时增加得更快,这对GaussianBlur()消耗的时间至关重要。 .请看下面的测试:
    vector<double> sig1 = { 1.6, 2.77128, 5.54256, 11.0851 };
    vector<double> sig3 = { 1.6, 1.22627, 1.54501, 1.94659, 2.45255, 3.09002 };
    vector<double> sig5 = { 1.6, 0.9044, 1.03888, 1.19336, 1.37081, 1.57465, 1.8088, 2.07777 };

    auto blurTest = [](const vector<double>& sigs, const string& label) {
    const int test_num = 100;
    auto t1 = chrono::high_resolution_clock::now();
    for (int i = 0; i < test_num; ++i) {
    vector<Mat> pyr;
    pyr.resize(sigs.size());
    pyr[0] = Mat::zeros(960, 1280, CV_32FC1);
    for (size_t i = 1; i < sigs.size(); ++i)
    GaussianBlur(pyr[i - 1], pyr[i], Size(), sigs[i], sigs[i]);
    }
    auto t2 = chrono::high_resolution_clock::now();
    auto time = chrono::duration<double>(t2 - t1).count() * 1e3 / test_num;
    cout << label << ": " << time << " ms\n";
    };

    blurTest(sig1, "1");
    blurTest(sig3, "3");
    blurTest(sig5, "5");

    /* output:
    1: 45.3958 ms
    3: 28.5943 ms
    5: 31.4827 ms
    */
    上面的代码模拟了 buildGaussianPyramid() nOctaveLayers是 1、3 和 5。西格玛值来自 cv::SIFT计算。这解释了为什么当 nOctaveLayers 时 SIFT 花费更多时间是 1。

    关于opencv - 为什么 SIFT 花费更多的时间和更少的倍频程层?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67500512/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com