【问题标题】:Improving image processing speed提高图像处理速度
【发布时间】:2012-01-27 20:12:21
【问题描述】:

我正在使用 C++ 和 OpenCV 实时处理从网络摄像头拍摄的一些图像,我希望从我的系统中获得最佳速度。

除了更改处理算法(暂时假设您无法更改它)。我应该做些什么来最大限度地提高处理速度?

我在想也许多线程在这里可以有所帮助,但我很惭愧地说我并不真正了解其中的来龙去脉(尽管显然我以前使用过多线程,但在 C++ 中没有使用过)。

假设我有一个 x 核处理器,将处理拆分为 x 个线程实际上会加快速度吗?...或者假设我正在寻找 20fps 的吞吐量,这些线程的管理开销是否会否定它(我假设这会影响你给出的答案,因为它应该告诉你每个线程将完成多少处理)

多线程在这里有用吗?

有没有什么技巧可以专门提高 OpenCV 的速度,或者我可能会陷入降低速度的任何陷阱。

谢谢。

【问题讨论】:

  • 将每个传入的帧扔给一组旋转的线程应该允许死简单的多线程。

标签: c++ multithreading image-processing opencv


【解决方案1】:

我认为,更简单的方法可能是流水线化框架操作。

您可以使用线程池,将帧内存缓冲区顺序分配给第一个可用线程,以便在相关帧上的算法步骤完成时释放到池中。

这实际上可以使您当前的(已调试的:)算法保持不变,但需要更多的内存来缓冲中间结果。

当然,如果没有关于你的任务的详细信息,很难说这是否合适......

【讨论】:

    【解决方案2】:

    在 OpenCV 中提高速度有一件重要的事情,与处理器或算法无关,它在处理矩阵时避免额外的复制。我会给你一个取自文档的例子:

    "...通过为另一个矩阵的一部分构造标题。它可以是 单行、单列、多行、多列、矩形 矩阵中的区域(在代数中称为次要)或对角线。这样的 操作也是 O(1),因为新标头将引用 相同的数据。您实际上可以使用此修改矩阵的一部分 特征,例如”

    // add 5-th row, multiplied by 3 to the 3rd row
    M.row(3) = M.row(3) + M.row(5)*3;
    
    // now copy 7-th column to the 1-st column
    // M.col(1) = M.col(7); // this will not work
    Mat M1 = M.col(1);
    M.col(7).copyTo(M1);
    

    也许您已经知道这个问题,但我认为在 openCV 中突出显示 headers 作为一种重要且高效的编码工具非常重要。

    【讨论】:

      【解决方案3】:

      假设我有一个 x 核处理器,将处理拆分为 x 个线程实际上会加快处理速度吗?

      是的,尽管这在很大程度上取决于所使用的特定算法,以及您编写线程代码以处理诸如同步之类的事情的技能。您确实没有提供足够的细节来做出比这更好的评估。

      一些算法非常容易并行化,例如具有以下形式的算法:

      for (i=0; i < DATA_SIZE; i++)
      {
         output[i] = f(input[i]);
      }
      

      对于某些函数 f。这些被称为embarassingly parallelizable;您可以简单地将数据拆分为 N 个块,并让 N 个线程单独处理每个块。像 OpenMP 这样的库使这种线程非常简单。

      【讨论】:

        【解决方案4】:

        除非您使用的特定算法已经针对多线程/并行平台进行了优化,否则将其扔给 x 核处理器对您毫无用处。该算法必须本质上是可线程的,才能从多个线程中受益。但如果它的设计没有考虑到这一点,它就必须改变。另一方面,许多图像处理算法是“令人尴尬的并行”,至少在概念上是这样。你能分享更多关于你想到的算法的细节吗?

        【讨论】:

        • 好吧,目前我只是使用标准的 OpenCV 算法来“填补处理的空白”。 (顺便说一句,它们是多线程/优化的吗?).....我实际上还没有决定我要使用的算法,但它可能是一个逐像素的分析,如果需要我可以分成 x 个线程并让他们都返回一个结果。
        • 算法在代码中实现。代码本质上是线程安全的,因此它取决于数据。
        • @MartinJames,代码大部分是线程安全的——你必须避免在你的代码中使用可变的静态变量。
        • 所有代码都是线程安全的,除非是自修改的。可变静态是数据。
        • @MartinJames 真的不明白你的意思。
        【解决方案5】:

        如果您的线程可以对不同的数据进行操作,那么将其线程化似乎是合理的,也许将每个帧对象排队到线程池中。您可能必须向帧对象添加序列号,以确保从池中出现的已处理帧按照它们进入的顺序传递。

        【讨论】:

          【解决方案6】:

          作为使用 OpenCV 进行多线程图像处理的示例代码,您可能需要查看我的代码:

          https://github.com/vmlaker/sherlock-cpp

          这就是我想利用 x-core CPU 来提高对象检测性能的想法。 detect 程序基本上是一种在多个线程之间分配任务的并行算法,每个任务都有一个单独的流水线线程:

          1. 分配帧内存和视频捕获。
          2. 对象检测(每个 Haar 分类器一个线程。)
          3. 使用检测结果增强输出并显示框架。
          4. 内存释放。

          通过在所有线程之间共享每个捕获帧的内存,我获得了出色的性能和 CPU 利用率。

          【讨论】:

            猜你喜欢
            • 2017-07-25
            • 1970-01-01
            • 1970-01-01
            • 2019-10-18
            • 1970-01-01
            • 2017-10-15
            • 2017-11-03
            • 2020-10-19
            • 1970-01-01
            相关资源
            最近更新 更多