我旨在一点一点地启动opencv,但首先我需要确定OpenCV的哪个API更有用。我预测与本地C ++实现相比,Python实现会更短,但运行时间会更密集,更慢。有没有人可以评论这两种观点之间的性能和编码差异?
Answers:
如先前的回答所述,Python比C ++或C慢。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
要比使用双循环快很多倍。
例如,您可以查看以下文章:
所有针对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
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;
}
}
}
可能的基准限制:
dst = cv2.filter2D(img, -1, kernel)
则计算机将创建的副本img
并将其返回为dst
。如果您不使用,img
则GC会清理旧图像。openCV python API无法解决此问题。在C / C ++中,您可以轻松创建正确大小的静态图像缓冲区,而不会在每一帧都被创建/销毁。内存分配和释放的时间不为零。
没错,Python几乎总是比C ++慢得多,因为它需要解释器,而C ++则不需要。但是,这确实需要对C ++进行强类型化,从而留出了很小的错误余量。有些人喜欢严格地编写代码,而另一些人则喜欢Python固有的宽大处理。
如果您想全面了解Python编码风格与C ++编码风格,这不是最好的选择,请尝试查找文章。
编辑:由于Python是一种解释性语言,而C ++被编译为机器代码,通常来说,您可以使用C ++获得性能优势。但是,关于使用OpenCV,核心OpenCV库已经被编译为机器代码,因此围绕OpenCV库的Python包装程序正在执行编译后的代码。换句话说,当涉及到从Python执行计算量大的OpenCV算法时,由于它们已经针对您正在使用的特定体系结构进行了编译,因此不会对性能造成太大影响。
C
无论如何,大多数实际工作都是通过OpenCV代码在幕后完成的,因此,只要您自己的代码不太复杂,差异就不会像您天真地期望的那么大。