我正在尝试计算图像中子窗口的熵特征。这是我写的代码:
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
实际上,它有效。但问题是它的速度太慢了。 你有什么想法让它快速吗?
答案 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)
。因此,产品不会增加熵的总和。
我也遇到了同样的问题,我也做了一些音频处理。不幸的是,除了上述内容,我无法改进它。如果您找到了更好的解决方案,如果您将其发布在此处,我将非常高兴。