如何减少用于直方图匹配的Python脚本的执行时间?

如何减少用于直方图匹配的Python脚本的执行时间?,python,algorithm,image-processing,histogram,Python,Algorithm,Image Processing,Histogram,我用Python实现了一个算法,用于减少图像中闪烁的强度变化。该算法首先计算图像每行的累积直方图。然后,它使用高斯核在垂直方向上过滤跨列的累积行累积直方图,从而减少行累积直方图之间的差异。最后,将原始图像的每一行累积直方图与相应的高斯滤波行累积直方图进行匹配。因此,对每行执行直方图匹配操作,并重建所需的行。自然地,最终通过简单地将所有行垂直堆叠在彼此的顶部来重建图像 在我的代码中,最后一部分,每行和每行内部有两个for循环,每个强度级别迭代[0255]需要很多时间,因此使用该算法不再可行。对于单

我用Python实现了一个算法,用于减少图像中闪烁的强度变化。该算法首先计算图像每行的累积直方图。然后,它使用高斯核在垂直方向上过滤跨列的累积行累积直方图,从而减少行累积直方图之间的差异。最后,将原始图像的每一行累积直方图与相应的高斯滤波行累积直方图进行匹配。因此,对每行执行直方图匹配操作,并重建所需的行。自然地,最终通过简单地将所有行垂直堆叠在彼此的顶部来重建图像

在我的代码中,最后一部分,每行和每行内部有两个for循环,每个强度级别迭代[0255]需要很多时间,因此使用该算法不再可行。对于单个4592x3448 16MP映像,在我的计算机上执行时间超过10分钟。当然,对3448行中的每一行进行256个强度值的迭代应该会大大降低算法的速度,但是由于算法的性质,我看不到任何其他方法可以避免这些循环

我对Python非常陌生,所以我可能在编程方面犯下了严重的罪行。我将感谢任何提示和代码审查。您可以在此链接下找到示例图像:


我不打算使用timeit,但它值得一做。我先不谈第一部分,最后一部分也不谈

### This part takes too much time ###### START ######################
# Perform histogram matching (for each row) to either 'Hz1' or 'Hz2'
img_match = np.copy(img)
for r in xrange(rows):  #no need to tell range to start from 0. and you should use xrange
    row = img[r,:]
    rowlength = len(row) #so you don't have to keep recalculating later.
    Hy = cdf_hist[r,:]       # Original row histogram
    Hz1 = Gauss1_cdf[r,:]    # Histogram 1 to be matched
    Hz2 = Gauss2_cdf[r,:]    # Histogram 2 to be matched
    Hz1Dict = {}
    Hz2dict = {}
    for index, item in enumerate(reversed(Hz1)):
        Hz1Dict[math.ceil(item)] = index
        Hz1Dict[math.floor(item)] = index
    for index, item in enumerate(reversed(Hz2)):
        Hz2Dict[math.ceil(item)] = index
        Hz2Dict[math.floor(item)] = index
    row_match = img_match[r,:]
    for i in xrange(255):      # for each intensity value
        # Find the indices of the pixels in the row whose intensity = i
        ind = [m for m in xrange(rowlength) if row[m]==i]
        j = Hy[i]
        while True:
            # use the appropriate CDF (Hz1 or Hz2) according to the bin number
            if i<T:
                if j in Hz1dict:
                    row_match[ind] = Hz1dict[j]
                    break
            else:
                if j in Hz2dict:
                    row_match[ind] = Hz2dict[j]
                    break
            else:
                j = j+1
###################### END ####################################    
显然,你应该仔细检查,我根本没有改变逻辑


编辑我现在所做的是为每个频率存储一个dict,为每个j记录j-1和j+1之间的第一个数字的索引,注意枚举中的相反情况。现在我只检查dict是否有对应的j作为键。如果是这样,我将k row_match[ind]设置为该值。

这将是一个更好的提问地点:在这里提出问题的一个问题是,人们普遍希望该问题有一个单一的答案。你的问题不够清楚,只有一个答案。我可能会看到一个错误。其他人可能会看到另一个…我假设时间。时间是用来衡量计算需要多长时间的?一个更好的方法是使用timeit,而不是如果lenk>0:,如果k:,则可以这样做,但无论如何都不应该定义k。请参阅下一条注释。它如下所示:k=[m代表m,如果val>j-1,则枚举Hz2中的val和valIm将给出一个解决方案-但如果我理解ind是什么,那就好了。它看起来像一个列表,但也被用作索引?我定义ind的方法可能不是最优的。看看流行的观点是什么。谢谢你的快速回答。我想你忘了o删除最后一行,否?行匹配[ind]=k[0].还有一个问题:索引对np数组有效吗?这段代码的问题是我实际上在搜索j可以在哪个范围内,因为直方图Hy和Hz1或Hz2都不完全包含匹配值,所以随着代码的增加,j一直在增加。更精确地说,Hy包含[2.0,6.0,8.0,10.0…]而Hz1或Hz2包含的值类似于[7.1、9.4、11.7、13.8…].那么,如果Hz1中的j或Hz2中的elif j永远都不会成为真的。因此我正在研究如何修改这部分。您希望代码中的循环通常在第一个j之后退出,还是希望它循环多次?我认为是后者,在这种情况下,我想我知道该怎么做,但直到以后才有机会进行修改。我认为修改后的代码可以工作。这仍然会在行和i上循环,但是内部循环现在应该是O1。
### This part takes too much time ###### START ######################
# Perform histogram matching (for each row) to either 'Hz1' or 'Hz2'
img_match = np.copy(img)
for r in xrange(rows):  #no need to tell range to start from 0. and you should use xrange
    row = img[r,:]
    rowlength = len(row) #so you don't have to keep recalculating later.
    Hy = cdf_hist[r,:]       # Original row histogram
    Hz1 = Gauss1_cdf[r,:]    # Histogram 1 to be matched
    Hz2 = Gauss2_cdf[r,:]    # Histogram 2 to be matched
    Hz1Dict = {}
    Hz2dict = {}
    for index, item in enumerate(reversed(Hz1)):
        Hz1Dict[math.ceil(item)] = index
        Hz1Dict[math.floor(item)] = index
    for index, item in enumerate(reversed(Hz2)):
        Hz2Dict[math.ceil(item)] = index
        Hz2Dict[math.floor(item)] = index
    row_match = img_match[r,:]
    for i in xrange(255):      # for each intensity value
        # Find the indices of the pixels in the row whose intensity = i
        ind = [m for m in xrange(rowlength) if row[m]==i]
        j = Hy[i]
        while True:
            # use the appropriate CDF (Hz1 or Hz2) according to the bin number
            if i<T:
                if j in Hz1dict:
                    row_match[ind] = Hz1dict[j]
                    break
            else:
                if j in Hz2dict:
                    row_match[ind] = Hz2dict[j]
                    break
            else:
                j = j+1
###################### END ####################################