我如何在Python中计算求和面积表?

时间:2013-11-18 13:18:19

标签: python in-place

我在Python中计算求和区域表(https://en.wikipedia.org/wiki/Summed_area_table)时遇到问题。最明显的算法涉及在引用已经编写的元素时更新列表元素......但是有关就地更新的内容似乎让Python感到困惑。

以下是一些示例代码:

def compute_summed_area_table(image):
    # image is a 2-dimensional array containing ints or floats, with at least 1 element.
    height = len(image)
    width = len(image[0])
    new_image = [([0.0] * width)] * height # Create an empty summed area table
    for row in range(0, height):
        for col in range(0, width):
            if (row > 0) and (col > 0):
                new_image[row][col] = image[row][col] + \
                    new_image[row][col - 1] + new_image[row - 1][col] - \
                    new_image[row - 1][col - 1]
            elif row > 0:
                new_image[row][col] = image[row][col] + new_image[row - 1][col]
            elif col > 0:
                new_image[row][col] = image[row][col] + new_image[row][col - 1]
            else:
                new_image[row][col] = image[row][col]
    # Note that two-pass code gives the same kind of results, e.g.:
    #    for row in range(0, height):
    #        for col in range(0, width):
    #            if col > 0:
    #                new_image[row][col] = image[row][col] + new_image[row][col - 1]
    #            else:
    #                new_image[row][col] = image[row][col]
    #    for row in range(0, height):
    #        for col in range(0, height):
    #            if row > 0:
    #                new_image[row][col] += new_image[row - 1][col]
    return new_image


small_image = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]
small_sat = compute_summed_area_table(small_image)
print(small_sat)

基于我自己的手动计算(可能出错),此测试代码应该提供如下内容: [[1,3,6,10,15],[7,16,27,40,55],[18,39,63,90,120],[34,72,114,160,210],[ 55,115,180,250,325]]

相反,它给出: [[55,61,68,76,85],[55,61,68,76,85],[55,61,68,76,85],[55,61,68,76,85],[ 55,61,68,76,85]]

显然在每次迭代期间更新每一行,但我不确定为什么或如何。有谁知道究竟出了什么问题?还有其他方法可以进行就地更新吗?如果没有,你会怎么做?

1 个答案:

答案 0 :(得分:2)

这是因为

new_image = [([0.0] * width)] * height

您没有创建尺寸宽度和高度的二维列表,而是创建高度项列表,并且该列表中的所有元素都指向大小宽度列表(它们都指向相同的列表)。解决此问题

new_image = [[0.0] * width for _ in range(height)]

考虑这个例子,

a = [[0] * 3] * 2
a[0][0] = 1
print a

a = [[0] * 3 for _ in range(2)]
a[0][0] = 1
print a

<强>输出

[[1, 0, 0], [1, 0, 0]]
[[1, 0, 0], [0, 0, 0]]

在第一种情况下,a[0]a[1]指向同一个列表。因此,将元素更改为0,也将元素更改为1。