3

画像内のサブウィンドウのエントロピー機能を計算しようとしています。ここに私が書いたコードがあります:

  def genHist(img):
    hist = np.histogram(img, np.arange(0, 256), normed=True)
    return hist[0]

  def calcEntropy(hist):
    logs = np.nan_to_num(np.log2(hist))
    hist_loghist = hist * logs
    entropy = -1 * hist_loghist.sum()
    return entropy  

   img = cv2.imread("lena.jpg", 0)
   result = np.zeros(img.shape, dtype=np.float16)
   h, w = img.shape
   subwin_size = 5
   for y in xrange(subwin_size, h-subwin_size):
       for x in xrange(subwin_size, w-subwin_size):
           subwin = img[y-subwin_size:y+subwin_size, x-subwin_size:x+subwin_size]
           hist = genHist(subwin)         # Generate histogram
           entropy = calcEntropy(hist)    # Calculate entropy
           result[y, x] = entropy

実際、それは機能します。しかし、問題は速度が遅すぎることです。速くするアイデアはありますか?

4

2 に答える 2

2

いくつかの変更を加えて、より高速にすることができます。

あなたのコードは私のラップトップで次の時間がかかります:

IPython CPU timings (estimated):
  User   :      50.92 s.
  System :       0.01 s.
Wall time:      51.20 s.

次の変更を加えました:

1 - 関数を削除し、genHist内部に実装しましたcalcEntropy()。保存されます。1 秒か 2 秒かもしれません。

2 - の代わりにlogs = np.nan_to_num(np.log2(hist))、log を見つける前に hist に小さな値 0.00001 を追加しただけです。logs = np.log2(hist+0.00001). 保存され3-4 secondsますが、出力がわずかに変わります。2 つの結果間の最大誤差は です0.0039062。(だから、これを望むかどうかはあなた次第です)

3 -np.histogramに変更cv2.calcHist()以上の節約になり25 secondsます。

さて、私のラップトップではコードに次の時間がかかります:

IPython CPU timings (estimated):
  User   :      13.38 s.
  System :       0.00 s.
Wall time:      13.41 s.

3倍以上の高速化です。

コード :

def calcEntropy(img):
    #hist,_ = np.histogram(img, np.arange(0, 256), normed=True)
    hist = cv2.calcHist([img],[0],None,[256],[0,256])
    hist = hist.ravel()/hist.sum()
    #logs = np.nan_to_num(np.log2(hist))
    logs = np.log2(hist+0.00001)
    #hist_loghist = hist * logs
    entropy = -1 * (hist*logs).sum()
    return entropy  

img = cv2.imread("lena.jpg", 0)
result2 = np.zeros(img.shape, dtype=np.float16)
h, w = img.shape
subwin_size = 5
for y in xrange(subwin_size, h-subwin_size):
   for x in xrange(subwin_size, w-subwin_size):
       subwin = img[y-subwin_size:y+subwin_size, x-subwin_size:x+subwin_size]
       #hist = genHist(subwin)         # Generate histogram
       entropy = calcEntropy(subwin)    # Calculate entropy
       result2.itemset(y,x,entropy)

今、主な問題はtwo for loops. これは実装に最適な候補でCythonあり、非常に良い結果が得られると思います。

于 2013-05-20T13:23:05.737 に答える
-1

math.log最初のステップとして、対応する関数の代わりに使用してみてくださいnumpy。これは非常に遅いです。

import numpy as np
import math

x=abs(randn(1000000))

#unsing numpy
start = time.time()
for i in x:
    np.log2(i)
print "Runtime: %f s" % (time.time()-start)
>>> Runtime: 3.653858 s

#using math.log
start = time.time()
for i in x:
    math.log(i,2)        # use log with base 2
print "Runtime: %f s" % (time.time()-start)
>>> Runtime: 0.692702 s

これに関する問題は、遭遇math.logするたびにエラーが発生することです。ヒストグラム出力から0すべてを削除することで、この問題を回避できます。0そして、それにはいくつかの利点があります: 1) 数学。ログは失敗しません。2) イメージによっては、math.log呼び出される回数が少なくなり、コードが高速になります。値を返す場合でもに0*log(0)なるため、ゼロを削除できます。したがって、積はエントロピーの合計に加算されません。0log(0)

私も行ったいくつかのオーディオ処理で同じ問題に直面しています。残念ながら、上記以上に改善することはできませんでした。より良い解決策を見つけた場合は、ここに投稿していただければ幸いです。

于 2013-05-20T13:23:12.190 に答える