更快速地分析图像中的每个子窗口?

时间:2013-05-20 10:07:55

标签: python performance opencv image-processing

我正在尝试计算图像中子窗口的熵特征。这是我写的代码:

  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

实际上,它有效。但问题是它的速度太慢了。 你有什么想法让它快速吗?

2 个答案:

答案 0 :(得分:2)

您可以进行一些修改,以使其更快。

您的代码需要在我的笔记本电脑中使用以下时间:

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

我做了以下修改:

1 - 删除了genHist函数并在calcEntropy()中实现了它。它会保存,可能是1或2秒。

2 - 在查找日志之前,我只是在hist中添加了一个小值0.00001而不是logs = np.nan_to_num(np.log2(hist))logs = np.log2(hist+0.00001)。它将保存3-4 seconds,但会略微改变您的输出。我在两个结果之间得到的最大误差是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实施的最佳候选者,它会产生非常好的结果。

答案 1 :(得分:-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个错误。您可以通过从histogramm输出中删除所有0来绕过此问题。这有几个好处:1)数学。日志不会失败,2)根据您的图像,math.log将被调用更少,这将导致更快的代码。即使0*log(0)返回值,您也可以删除零,因为0变为log(0)。因此,产品不会增加熵的总和。

我也遇到了同样的问题,我也做了一些音频处理。不幸的是,除了上述内容,我无法改进它。如果您找到了更好的解决方案,如果您将其发布在此处,我将非常高兴。

相关问题