python 2D列表,包含原始2D列表中周围单元格的平均值

时间:2015-10-21 17:08:04

标签: python matrix

我需要编写一个函数blur(l),用它的邻居和它自己的平均值替换2D矩阵中的每个单元格(即一个矩形的2D列表)。每个小区最多有8个邻居,因此平均值最多可计算9个小区。关于给定列表,您唯一可以假设的是它是矩形的,并且它只包含整数。

!这必须在没有numpy的情况下完成!

我尝试使用此代码:

def blur(l):
    result = []
    for x in range(len(l) - 1):
        tussen = []
        for y in range(len(l) - 1):
            t = get_neighbor_sum(l, x, y)
            tussen.append(t)
        result.append(tussen)
    return result

def get_value(list, i, j):
    new_i = len(list) - 1
    new_j = len(list[new_i]) - 1
    print(i, j, new_i, new_j)
    return list[new_i][new_j]


def get_neighbor_sum(list, i, j):
    sum = 0
    for offset_i in [-1, 0, 1]:
        for offset_j in [-1, 0, 1]:
            sum += get_value(list, i + offset_i, j + offset_j)
    return sum

但由于某种原因它只返回原始列表,有人可以解释我为什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

import itertools

def get_neighbors(lst, point):
    x,y = point
    neighbors = []
    for offset_x, offset_y in itertools.product([-1, 0, 1], repeat=2):
        new_x, new_y = x + offset_x, y + offset_y
        try:
            neighbors.append(lst[new_y][new_x])
        except IndexError:
            continue
    return neighbors

这应该为lst中相对于点point(应该是(column, row)形式的元组)的相邻单元格的所有值。从那里你应该能够遍历你的列表并用sum(result)/len(result)替换该元素。

for y, row in enumerate(lst):
    for x, _ in enumerate(row):
        result = get_neighbors(lst, (x, y))
        lst[y][x] = sum(result) / len(result)

您甚至可以通过更改get_neighbors函数来接受一个参数,以获取搜索偏移的宽度以及为每个偏移量赋予的权重的强度,从而使结果更加模糊。

import itertools

def get_neighbors(lst, point, n=1, weights=None):
    if weights is None:
        weights = dict()
    x, y = point
    neighbors = []
    offsets = range(-n, n+1)
    for offset_x, offset_y in itertools.product(offsets, repeat=2)):
        new_x, new_y = x + offset_x, y + offset_y
        weight = weights.get(new_y, {}).get(new_x, 1)
        # defaults to 1.
        # Same as try: weights[new_y][new_x] except KeyError: 1
        try:
            neighbors.append(lst[new_y][new_x] * weight)
        except IndexError:
            continue
    return neighbors

这要求权重是dicts的一个词,用于定义偏移量x和y的权重,例如:

{-1: {-1: 0.5,
       0: 1,
       1: 0.5},
  1: {-1: 0.5,
       0: 1,
       1: 0.5}}

假设任何丢失的钥匙都具有完全重量,因此这将给标记为X下方的正方形赋予一半的重量

X O X
O O O
X O X

可能有一个更好的实现,但我想不出一个副手:)

答案 1 :(得分:0)

get_value()应检查您为该函数提供的索引是否对该列表有效。如果它们的索引无效,则get_neighbor_sum()不应添加它们。在角落中,平均值只能在四个值之间。使用两个函数很难做到这一点,因为我们必须为get_value()返回一个无效的值(可能是浮点数),让get_neighbor_sum()注意到这个并且不添加它...

我认为您根本不需要函数get_value(),并且可以通过创建get_neighbor_average函数来简化:

def get_neighbor_average(list, i, j):
    sum = 0
    div = 0
    for offset_i in [-1, 0, 1]:
        for offset_j in [-1, 0, 1]:
            new_i = i + offset_i
            new_j = j + offset_j
            if (new_i >= 0 and new_j >= 0 and new_i < len(list) and new_j < len(list)):
                sum += list[new_i][new_j]
                div += 1
    avg = sum / div
    return avg

这为您提供了所有邻居的平均值,但它是安全的,因为它会检查我们尝试访问的列表元素是否有效。