記事のディレクトリ
OpenCV-Python:コアオペレーション
11プログラムのパフォーマンステストと最適化
目標
画像処理では、毎秒多くの計算を行う必要があるため、プログラムは正しい結果を出すだけでなく、高速である必要があります。したがって、このセクションでは、次のことを学習します
。•プログラムの効率を確認する•プログラム
の効率を改善するためのいくつかのテクニック
•学習する必要のある関数は、cv2.getTickCount、cv2.getTickFrequencyなどです。OpenCVに
加えて、Pythonまた、時間と呼ばれるモジュールを提供します。これを使用して、プログラムの実行時間を測定できます。プロファイルと呼ばれる別のモジュールは、プログラムに関する詳細なレポートを取得するのに役立ちます。このレポートには、コード内の各関数の実行に必要な時間と、各関数が呼び出された回数が含まれます。IPythonを使用している場合、これらの機能はすべてユーザーフレンドリーな方法で統合されています。重要なものをいくつか学びます。より詳細な知識を学びたい場合は、より多くのリソースのリンクを開いてください。
11.1OpenCVを使用してプログラムの効率をテストする
cv2.getTickCount関数は、参照ポイントからこの関数の実行までのクロック数を返します。したがって、実行の前後に関数を呼び出すと、この関数の実行時間(クロック数)が取得されます。
cv2.getTickFrequencyは、クロック周波数、つまり1秒あたりのクロック数を返します。したがって、次の方法で関数が実行された秒数を取得できます。
e1 = cv2.getTickCount()
# your code execution
e2 = cv2.getTickCount()
time = (e2 - e1)/ cv2.getTickFrequency()
次の例を使用して説明します。次の例では、ウィンドウサイズ(5、7、9)が異なるカーネル関数を使用して中央値フィルタリングを実行します。
img1 = cv2.imread('messi5.jpg')
e1 = cv2.getTickCount()
for i in xrange(5,49,2):
img1 = cv2.medianBlur(img1,i)
e2 = cv2.getTickCount()
t = (e2 - e1)/cv2.getTickFrequency()
print t
# Result I got is 0.521107655 seconds
注:上記の関数をtimeモジュールに実装することもできます。ただし、使用する関数はcv2.getTickCountではなくtime.time()です。これら2つの結果の違いを比較してください。
11.2OpenCVのデフォルトの最適化
OpenCVの多くの機能が最適化されています(SSE2、AVXなどを使用)。また、最適化されていないコードも含まれています。システムが最適化をサポートしている場合は、1つのポイントのみを使用するようにしてください。最適化は、コンパイル時にデフォルトでオンになっています。したがって、OpenCVは最適化されたコードを実行します。最適化をオフにすると、非効率的なコードしか実行できません。関数cv2.useOptimized()を使用して最適化がオンになっているかどうかを確認し、関数cv2.setUseOptimized()を使用して最適化をオンにすることができます。
簡単な例を見てみましょう。
# check if optimization is enabled
In [5]: cv2.useOptimized()
Out[5]: True
In [6]: %timeit res = cv2.medianBlur(img,49)
10 loops, best of 3: 34.9 ms per loop
# Disable it
In [7]: cv2.setUseOptimized(False)
In [8]: cv2.useOptimized()
Out[8]: False
In [9]: %timeit res = cv2.medianBlur(img,49)
10 loops, best of 3: 64.1 ms per loop
見えますか?最適化されたメディアンフィルターは2倍高速です。ソースコードを見ると、メディアンフィルターがSIMDによって最適化されていることがわかります。したがって、コードの最初で最適化をオンにすることができます(最適化はデフォルトでオンになっていることを覚えておく必要があります)。
11.3IPythonでのプログラム効率のチェック
2つの同様の操作の効率を比較する必要がある場合は、IPythonが提供する魔法のコマンド%timeを使用できます。彼は、正確な(実行)時間を取得するために、コードを数回実行させます。また、1行のコードをテストするためにも使用できます。
たとえば、以下の同じ数学演算のコードのどの行がより速く実行されるか知っていますか?
。5= X; Y = 2 * X *
X =。5; Y = X * X
X = np.uint([。5]); X Y = X *
Y = np.squre(X)
シェルで可能IPython魔法のコマンドを使用して答えを見つけます。
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
それが最初の書き方であることが判明しました。実際にはNumpよりも20倍高速でした。アレイの構成を考えると、100倍の差に達する可能性があります。
注:Pythonのスカラー計算は、Numpのスカラー計算よりも高速です。1つまたは2つの要素のみを含む操作の場合、PythonスカラーはNumpy配列よりも高速です。ただし、配列が少し大きい場合は、Numpyが勝ちます。
さらにいくつかの例を見てみましょう。cv2.countNonZero()と
np.count_nonzero()を比較してみましょう。
In [35]: %timeit z = cv2.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
ご覧のとおり、OpenCVの機能はNumpyの25倍です。
注:一般に、OpenCV関数はNumpy関数よりも高速です。したがって、同じ操作にOpenCV関数を使用するのが最善です。もちろん、例外があります。特に、Numpyを使用してビューを操作する場合(コピーではありません)。
11.4その他のIPythonマジックコマンド
プログラム、プロファイリング、ラインプロファイリング、メモリ使用量などの効率をチェックするために使用できるいくつかの魔法のコマンドもあります。それらはすべて包括的なドキュメントを持っています。したがって、ここではハイパーリンクのみが提供されます。興味のある人は自分で学ぶことができます。
11.5効率最適化テクノロジー
いくつかのテクニックとプログラミング方法により、PythonとNumpyのパワーを最大化することができます。
ここでは関連するものだけに言及します。ハイパーリンクからより詳細な情報を見つけることができます。私たちが言いたい最も重要な点は、最初に簡単な方法でアルゴリズムを実装し(正しい結果が最も重要です)、結果が正しい場合は、上記の方法を使用してプログラムのボトルネックを見つけて最適化します。
1.本質的に非常に遅いループ、特にダブルループとトリプルループの使用は避けてください。
2. NumpyとOpenCVの両方がベクトル演算を最適化したため、アルゴリズムでは可能な限りベクトル演算を使用します。
3.キャッシュコヒーレンシを利用します。
4.必要がない場合は、アレイをコピーしないでください。コピーする代わりにビューを使用します。アレイのコピーはリソースを非常に浪費します。
上記の最適化を行っても、プログラムが非常に遅い場合、または大きな話題が避けられない場合は、Cythonなどの他のパッケージを使用してプログラムを高速化する必要があります。
詳細については、公式アカウントに注意してください。