【问题标题】:How to optimize these nested loops?如何优化这些嵌套循环?
【发布时间】:2018-09-16 18:12:21
【问题描述】:

我正在尝试计算颜色(或与 17 种颜色中的一种颜色最接近的颜色)出现在图像像素中的次数(以 300x300x3 np 数组的形式给出,浮点值 [0,1])。我已经写了这个,但它似乎效率极低:

for w in range(300):
    for h in range(300):
        colordistance = float('inf')
        colorindex = 0
        for c in range(17):
            r1 = color[c, 0]
            g1 = color[c, 1]
            b1 = color[c, 2]
            r2 = img[w, h, 0]
            g2 = img[w, h, 1]
            b2 = img[w, h, 2]
            distance = math.sqrt(
                ((r2-r1)*0.3)**2 + ((g2-g1)*0.59)**2 + ((b2-b1)*0.11)**2)
            if distance < colordistance:
                colordistance = distance
                colorindex = c
        colorcounters[colorindex] = colorcounters[colorindex] + 1

有什么方法可以提高这个位的效率吗?我已经在外部循环中使用多处理。

【问题讨论】:

  • 在您的第 5 行中,您缺少范围的值。我猜是3?另外,您是否考虑过使用生成器?如果您以前没有听说过,我可以详细说明
  • numba 可能会大大加快这个循环,看看吧。
  • @HarisNadeem 是 17 - 检查每种颜色。图片是从 h5 文件中获取的——只是这个循环需要很长时间。
  • 您可以通过首先检查是否完全匹配if all([a==b for a, b in [(r1, r2), (g1, g2), (b1, b2)]]): colorcounters[c] += 1; continue来短路内部for循环
  • @thebjorn 这些图像是真实世界的照片,我只检查 17 种网络颜色,因此我要计算距离。它们将完全相等的情况非常有限。

标签: python performance for-loop processing-efficiency


【解决方案1】:

您提到您正在使用 numpy,因此您应该尽可能避免迭代。我的矢量化实现快了大约 40 倍。我对您的代码进行了一些更改,以便他们可以使用相同的数组,以便我可以验证正确性。这可能会影响速度。

import numpy as np
import time
import math

num_images = 1
hw = 300 # height and width
nc = 17  # number of colors
img = np.random.random((num_images, hw, hw, 1, 3))
colors = np.random.random((1, 1, 1, nc, 3))

## NUMPY IMPLEMENTATION
t = time.time()

dist_sq = np.sum(((img - colors) * [0.3, 0.59, 0.11]) ** 2, axis=4)  # calculate (distance * coefficients) ** 2
largest_color = np.argmin(dist_sq, axis=3)  # find the minimum
color_counters = np.unique(largest_color, return_counts=True) # count
print(color_counters)
# should return an object like [[1, 2, 3, ... 17], [count1, count2, count3, ...]]

print("took {} s".format(time.time() - t))

## REFERENCE IMPLEMENTATION
t = time.time()
colorcounters = [0 for i in range(nc)]
for i in range(num_images):
    for h in range(hw):
        for w in range(hw):
            colordistance = float('inf')
            colorindex = 0
            for c in range(nc):
                r1 = colors[0, 0, 0, c, 0]
                g1 = colors[0, 0, 0, c, 1]
                b1 = colors[0, 0, 0, c, 2]
                r2 = img[i, w, h, 0, 0]
                g2 = img[i, w, h, 0, 1]
                b2 = img[i, w, h, 0, 2]

                # dist_sq
                distance = math.sqrt(((r2-r1)*0.3)**2 + ((g2-g1)*0.59)**2 + ((b2-b1)*0.11)**2)  # not using sqrt gives a 14% improvement

                # largest_color
                if distance < colordistance:
                    colordistance = distance
                    colorindex = c
            # color_counters
            colorcounters[colorindex] = colorcounters[colorindex] + 1
print(colorcounters)
print("took {} s".format(time.time() - t))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-06
    • 2021-01-21
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多