opencv中文文档

opencv中文文档


性能评估和改进技术

<h1>目标</h1> <p>在图像处理中,由于每秒要处理大量的操作,所以必须让代码不仅提供正确的解决方案,而且以最快的方式提供正确的解决方案。所以在这一章中,你会学到</p> <ul> <li>来度量代码的性能。</li> <li>提高代码性能的一些技巧。</li> <li>你会看到这些函数:cv.getTickCount, cv.getTickFrequency 等等。 除了OpenCV, Python还提供了一个模块时间,这有助于度量执行时间。另一个模块概要文件有助于获得关于代码的详细报告,比如代码中每个函数花费了多少时间,调用了多少次函数等等。但是,如果您正在使用IPython,那么所有这些功能都是以用户友好的方式集成的。我们将看到一些重要的链接,有关更多细节,请查看附加参考资料部分中的链接。</li> </ul> <h2>使用OpenCV测量性能</h2> <p>cv.getTickCount函数返回一个引用事件(比如打开机器的时刻)之后到调用该函数的时刻的时钟周期数。如果在函数执行之前和之后调用它,就会得到用于执行函数的时钟周期数。</p> <p>cv.getTickFrequency函数返回时钟周期的频率,或每秒时钟周期的数量。因此,要计算以秒为单位的执行时间,可以执行以下操作:</p> <pre><code class="language-python">e1 = cv.getTickCount() # your code execution e2 = cv.getTickCount() time = (e2 - e1)/ cv.getTickFrequency()</code></pre> <p>我们将通过以下示例进行演示。下面的示例应用中值滤波,其内核大小为奇数,范围从5到49。(不要担心结果会怎样,这不是我们的目标):</p> <pre><code class="language-python">img1 = cv.imread('messi5.jpg') e1 = cv.getTickCount() for i in xrange(5,49,2): img1 = cv.medianBlur(img1,i) e2 = cv.getTickCount() t = (e2 - e1)/cv.getTickFrequency() print( t ) # Result I got is 0.521107655 seconds</code></pre> <h4>注意</h4> <pre><code>你也可以用python内置的时间模块做到, 替代cv.getTickCount, 使用time.time()函数, 然后取两次时间的差</code></pre> <h2>OpenCV中的默认优化</h2> <p>许多OpenCV函数都是使用SSE2、AVX等进行优化的。它还包含未加密的代码。因此,如果我们的系统支持这些特性,我们就应该利用它们(几乎所有现代处理器都支持它们)。编译时默认启用它。因此,如果OpenCV启用了优化代码,它将运行优化后的代码,否则它将运行未经优化的代码。可以使用cv.useoptimization()检查是否启用/禁用了它,并使用cv.setuseoptimization()启用/禁用它。让我们看一个简单的例子。</p> <pre><code class="language-python"># check if optimization is enabled In [5]: cv.useOptimized() Out[5]: True In [6]: %timeit res = cv.medianBlur(img,49) 10 loops, best of 3: 34.9 ms per loop # Disable it In [7]: cv.setUseOptimized(False) In [8]: cv.useOptimized() Out[8]: False In [9]: %timeit res = cv.medianBlur(img,49) 10 loops, best of 3: 64.1 ms per loop</code></pre> <p>优化的中值滤波比未优化的版本快2倍。如果您检查它的源代码,您可以看到中值滤波是SIMD优化的。因此,可以使用它在代码顶部启用优化(请记住,默认情况下启用了优化)。</p> <h2>在IPython中度量性能</h2> <p>有时您可能需要比较两个类似操作的性能。IPython提供了一个神奇的命令timeit来执行此操作。它运行代码几次以获得更精确的结果。同样,它们也适用于测量单行代码。</p> <pre><code>例如,你知道下面哪个加法运算更好吗,x = 5;y = x**2, x = 5;y = x*x, x = np.uint8([5]);y = x*x还是y = np.square(x) ?我们将在IPython shell中使用timeit找到它。</code></pre> <pre><code class="language-python">In [10]: x = 5 In [11]: %timeit y=x**2 10000000 loops, best of 3: 73 ns per loop In [12]: %timeit y=x*x 10000000 loops, best of 3: 58.3 ns per loop In [15]: z = np.uint8([5]) In [17]: %timeit y=z*z 1000000 loops, best of 3: 1.25 us per loop In [19]: %timeit y=np.square(z) 1000000 loops, best of 3: 1.16 us per loop </code></pre> <pre><code>可以看到,x = 5;y = x*x是最快的,与Numpy相比大约快20倍。如果您也考虑数组的创建,它可能会更快达到100倍。很酷,对吧?*(Numpy开发人员正在处理这个问题)*</code></pre> <p>Python标量操作比Numpy标量操作快。因此,对于包含一两个元素的操作,Python标量优于Numpy数组。当数组的大小稍微大一点时,Numpy就会发挥作用。</p> <p>我们再试一个例子。这一次,我们将比较相同图像的cv.countNonZero()和np.count_nonzero()的性能。</p> <pre><code class="language-python">In [35]: %timeit z = cv.countNonZero(img) 100000 loops, best of 3: 15.8 us per loop In [36]: %timeit z = np.count_nonzero(img) 1000 loops, best of 3: 370 us per loop</code></pre> <p>看, OpenCV函数比Numpy函数快25倍。</p> <h4>注意</h4> <pre><code>通常,OpenCV函数比Numpy函数更快。因此,对于相同的操作,OpenCV函数是首选的。但是,也有例外,特别是当Numpy使用视图而不是副本时。</code></pre> <h2>更多IPython的神奇命令</h2> <p>还有其他一些神奇的命令可以测量性能、概要、行概要、内存度量等。它们都有很好的记录。这里只提供到这些文档的链接。有兴趣的读者可以尝试一下。</p> <h2>性能优化技术</h2> <p>有几种技术和编码方法可以利用Python和Numpy的最大性能。这里只提到了相关的内容,并给出了重要来源的链接。这里要注意的主要事情是,首先尝试以一种简单的方式实现算法。一旦它开始工作,分析它,找到瓶颈并优化它们。 尽量避免在Python中使用循环,特别是双/三重循环等。他们天生迟钝。 将算法/代码向量化到最大程度,因为Numpy和OpenCV是针对向量操作优化的。 利用缓存一致性。 除非需要,否则不要复制数组。尝试使用视图。数组复制是一项代价高昂的操作。 即使在完成所有这些操作之后,如果您的代码仍然很慢,或者不可避免地要使用大型循环,那么可以使用额外的库(如Cython)来提高速度。</p> <h1>其它资源</h1> <p><a href="http://wiki.python.org/moin/PythonSpeed/PerformanceTips" title="Python优化技术">Python优化技术</a> <a href="http://scipy-lectures.github.io/advanced/advanced_numpy/index.html#advanced-numpy" title="Scipy讲义-高级Numpy">Scipy讲义-高级Numpy</a> <a href="http://pynash.org/2013/03/06/timing-and-profiling/" title="IPython中的计时和分析">IPython中的计时和分析</a></p>

页面列表

ITEM_HTML