OpenCV的Python或C++编码的性能是否不同?

ero*_*gol 62 c++ python performance opencv

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

Abi*_*n K 140

如前面的答案中所提到的,与C++或C相比,Python速度较慢.Python的构建原因在于其简单性,可移植性以及创造性,用户只需要担心算法,而不是编程问题.

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

因此,当您从Python调用OpenCV中的函数时,实际运行的是底层C/C++源代码.因此,性能上没有太大差异.(我记得我在某处看过性能损失<1%,不记得在哪里.对OpenCV中一些基本功能的粗略估计显示了最坏情况下的惩罚<4%.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的性能比较


sdf*_*off 9

openCV的所有google结果都是相同的:python只会稍微慢一点.但是,我没有看过任何关于此的分析.所以我决定做一些并发现:

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

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

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

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

Python代码:

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
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

可能的基准限制:

  • 相机帧率
  • 定时器测量精度
  • 花在打印格式上的时间

  • 您的测试用例恰好是显示 Python 和 C++ 之间最大差异的测试用例。所以可能不太现实。更好的测试是查看视频帧,并可能尝试计算自动驾驶汽车的目标。这与 C++ 或 Python 的运行时间几乎相同。无新闻案例显示加载帧缓冲区需要多长时间,而不是进行任何实际工作。SO 帧加载占主导地位。如果做实际工作,那么帧缓冲只是总数的 2%,而不是总数的 100%。 (2认同)
  • 帧速率从 50 提高到 65 不是会提高 30%(而不是 25%)吗? (2认同)

Pau*_*ing 6

sdfgeoff答案忽略了您可以在 Python 中重用数组的事实。预先分配它们并传入它们,它们将被使用。所以:

    image = numpy.zeros(shape=(height, width, 3), dtype=numpy.uint8)
    #....
    retval, _ = cv.VideoCapture.read(image)
Run Code Online (Sandbox Code Playgroud)

  • 不知道你为什么这么说。这是 filter2d 的文档:https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#ga27c049795ce870216ddfb366086b5a04 注意 Python 中的第四个参数是“dst”,它是目标数组。我没有到处检查,但标准是,如果 C++ 中有目标 arg,那么它在 Python 中就存在 (2认同)
  • 是的,自从我从事此工作以来已经有一段时间了,我不记得我是否测量了与预分配直接相关的任何内容。然而,这种代码通常每个相机帧运行一次,因此最低为 30FPS,较新的相机为 120FPS 或更快,并且图像可能是 6MB 数据(对于 1K 彩色图像)。即使分配非常快(但我不相信微秒),您正在谈论分配和释放 700MB/秒。这确实会影响内存分配和垃圾收集器。 (2认同)

Cal*_*ean 5

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

如果你想全面讨论 Python 编码风格与 C++ 编码风格,这不是最好的地方,试着找一篇文章。

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

  • 是的,python 是解释型的。但几乎所有的工作都是在 openCV 内部完成的。假设有 20/80 的分配。openCV 内部完成的 80% 工作是用编译后的 C 语言编写的。我们谈论的是剩余 20% 代码的运行速度。即使 Python 慢了 4 倍,它也只会增加 30% 的执行时间。许多 openCV 应用程序都是 5/95 分割,因此 Python 几乎没有区别 (2认同)