简体   繁体   English

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

[英]python 2D list with average of surrounding cells in original 2D list

I need to write a function blur(l) that replaces each cell in a 2D matrix (ie a 2D list that is rectangular) with the average of its neighbors and itself. 我需要编写一个函数blur(l),用其邻居及其自身的平均值替换2D矩阵(即矩形的2D列表)中的每个单元。 Each cell has at most 8 neighbors, hence the average is computed over at most 9 cells. 每个像元最多具有8个邻居,因此,平均值最多要计算9个像元。 The only thing you may assume about the given list is that it is rectangular, and that it only contains integers. 对于给定的列表,您可能唯一想到的是它是矩形的,并且只包含整数。

! this has to be done without numpy ! 这必须在没有numpy的情况下完成!

I tried using this code: 我尝试使用此代码:

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

but for some reason it only returns the original list, can someone explain me why and how to fix this? 但由于某种原因,它仅返回原始列表,有人可以向我解释原因以及如何解决此问题吗?

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

This should give you all the values of the neighboring cells in lst with respect to the point point (which should be a tuple of the form (column, row) ). 这应该给你的相邻小区的所有值lst相对于点point (这应该是形式的元组(column, row) )。 From there you should be able to iterate through your list and replace that element with sum(result)/len(result) . 从那里,您应该能够遍历列表,并将该元素替换为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)

You could even blur the results a bit more by changing your get_neighbors function to accept a parameter for how wide an offset to search and how strong a weight to give to each offset. 您甚至可以通过更改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

This expects that weights is a dict of dicts that defines how much weight should be given to an offset x and y, such as: 这期望权重是指决定应该为偏移量x和y赋予多少权重的命令的命令,例如:

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

Any missing keys are assumed to have full weight, so this would give half weight to the squares marked as X below 假定所有丢失的键都具有完全权重,因此这将使下面标记为X的方块的权重为一半

X O X
O O O
X O X

There might be a nicer implementation but I can't think of one off-hand :) 可能会有更好的实现,但我想不到一个副手:)

get_value() is supposed to check whether the indexes you are feeding the function are valid for the list. 应该使用get_value()检查为函数提供索引的列表是否有效。 If they indexes are not valid, get_neighbor_sum() should not add them, In the corners, the average value could only be between four values. 如果它们的索引无效,则get_neighbor_sum()不应将它们相加。在角落,平均值只能在四个值之间。 This is difficult to do with two functions, because we have to return a value for get_value() that is invalid (a float maybe), have the get_neighbor_sum() notice this and not add it... 这很难用两个函数来完成,因为我们必须为无效的get_value()返回一个值(可能是浮点数),让get_neighbor_sum()注意这一点,而不是添加它。

I think that you don't need the function get_value() at all, and can make it easier by making a get_neighbor_average function: 我认为您根本不需要函数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

This gives you an average of all the neighbors, but is safe because it checks whether the list element we are trying to access is valid or not. 这为您提供了所有邻居的平均值,但是很安全,因为它会检查我们尝试访问的list元素是否有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM