90

我的目标是一点一点地启动 opencv,但首先我需要确定 OpenCV 的哪个 API 更有用。我预测 Python 实现会更短,但与原生 C++ 实现相比,运行时间会更密集且更慢。有没有人知道可以评论这两个角度之间的性能和编码差异?

4

5 回答 5

178

正如前面的答案中提到的,与 C++ 或 C 相比,Python 速度较慢。Python 的构建是为了它的简单性、可移植性以及创造性,用户只需担心他们的算法,而不是编程问题。

但是在 OpenCV 中,有些不同。Python-OpenCV 只是原始 C/C++ 代码的包装器。它通常用于结合两种语言的最佳特性,C/C++ 的性能和 Python 的简单性

因此,当您从 Python 调用 OpenCV 中的函数时,实际运行的是底层 C/C++ 源代码。所以性能不会有太大差异。(我记得我在某处读到性能损失<1%,不记得在哪里。对OpenCV中一些基本功能的粗略估计显示最坏情况下的损失为<4%.ie penalty = [maximum time taken in Python - minimum time taken in C++]/minimum time taken in C++) .

当您的代码有很多本机 python 代码时,就会出现问题。例如,如果您正在制作自己的函数,而这些函数在 OpenCV 中不可用,那么情况会变得更糟。此类代码在 Python 中本地运行,这大大降低了性能。

但是新的 OpenCV-Python 接口完全支持 Numpy。Numpy 是 Python 中用于科学计算的包。它也是原生 C 代码的包装器。它是一个高度优化的库,支持多种矩阵运算,非常适合图像处理。因此,如果您可以正确组合 OpenCV 函数和 Numpy 函数,您将获得非常高速的代码。

要记住的是,始终尽量避免 Python 中的循环和迭代。相反,使用 Numpy(和 OpenCV)中可用的数组操作工具。简单地添加两个 numpy 数组使用C = A+B比使用双循环快很多倍。

例如,您可以查看这些文章:

  1. Python 中的快速数组操作
  2. OpenCV-Python接口、cv和cv2的性能比较
于 2012-11-17T18:12:23.120 回答
20

openCV 的所有谷歌结果都是一样的:python 只会稍微慢一点。但我一次也没有看到任何关于此的分析。所以我决定做一些并发现:

Python 比使用 opencv 的 C++ 慢得多,即使对于琐碎的程序也是如此。

我能想到的最简单的例子是在屏幕上显示网络摄像头的输出并显示每秒的帧数。使用 python,我达到了 50FPS(在 Intel atom 上)。使用 C++,我得到了 65FPS,增加了 25%。在这两种情况下,CPU 使用率都使用单核,据我所知,受 CPU 性能的限制。此外,这个测试用例与我在过去从一个移植到另一个的项目中看到的一致。

这种差异从何而来?在 python 中,所有的 openCV 函数都返回图像矩阵的新副本。每当您捕获图像或调整图像大小时 - 在 C++ 中,您都可以重用现有内存。在python中你不能。我怀疑这次分配内存所花费的时间是主要区别,因为正如其他人所说:openCV 的底层代码是 C++。

在你把 python 扔出窗外之前:python 的开发速度要快得多,如果你没有遇到硬件限制,或者如果开发速度比性能更重要,那么使用 python。在我使用openCV 完成的许多应用程序中,我从python 开始,后来只将计算机视觉组件转换为C++(例如,使用python 的ctype 模块并将CV 代码编译到共享库中)。

蟒蛇代码:

import cv2
import time

FPS_SMOOTHING = 0.9

cap = cv2.VideoCapture(2)
fps = 0.0
prev = time.time()
while True:
    now = time.time()
    fps = (fps*FPS_SMOOTHING + (1/(now - prev))*(1.0 - FPS_SMOOTHING))
    prev = now

    print("fps: {:.1f}".format(fps))

    got, frame = cap.read()
    if got:
        cv2.imshow("asdf", frame)
    if (cv2.waitKey(2) == 27):
        break

C++ 代码:

#include <opencv2/opencv.hpp>
#include <stdint.h>

using namespace std;
using namespace cv;

#define FPS_SMOOTHING 0.9

int main(int argc, char** argv){
    VideoCapture cap(2);
    Mat frame;

    float fps = 0.0;
    double prev = clock(); 
    while (true){
        double now = (clock()/(double)CLOCKS_PER_SEC);
        fps = (fps*FPS_SMOOTHING + (1/(now - prev))*(1.0 - FPS_SMOOTHING));
        prev = now;

        printf("fps: %.1f\n", fps);

        if (cap.isOpened()){
            cap.read(frame);
        }
        imshow("asdf", frame);
        if (waitKey(2) == 27){
            break;
        }
    }
}

可能的基准限制:

  • 相机帧率
  • 定时器测量精度
  • 花在打印格式上的时间
于 2018-07-08T18:46:28.713 回答
6

你是对的,Python 几乎总是比 C++ 慢得多,因为它需要一个解释器,而 C++ 不需要。但是,这确实需要 C++ 是强类型的,这会留下更小的错误余地。有些人喜欢被要求严格编码,而另一些人则喜欢 Python 与生俱来的宽容。

如果您想全面了解 Python 编码风格与 C++ 编码风格,这不是最好的地方,请尝试查找一篇文章。

编辑:因为 Python 是一种解释性语言,而 C++ 被编译为机器代码,一般来说,使用 C++ 可以获得性能优势。但是,关于使用 OpenCV,核心 OpenCV 库已经编译为机器代码,因此 OpenCV 库周围的 Python 包装器正在执行编译后的代码。换句话说,当涉及到从 Python 执行计算成本高昂的 OpenCV 算法时,您不会看到太多的性能损失,因为它们已经针对您正在使用的特定架构进行了编译。

于 2012-11-17T17:18:20.037 回答
6

sdfgeoff的答案是缺少可以在 Python 中重用数组的事实。预先分配它们并传递它们,它们就会被使用。所以:

    image = numpy.zeros(shape=(height, width, 3), dtype=numpy.uint8)
    #....
    retval, _ = cv.VideoCapture.read(image)
于 2018-11-29T13:59:08.400 回答
3

为什么选择?如果您同时知道Pythonand C++,请使用Python用于研究Jupyter Notebooks,然后C++用于实现。的Python堆栈JupyterOpenCV (cv2)Numpy提供快速原型设计。将代码移植到C++通常非常简单。

于 2021-04-05T15:29:10.483 回答