Я хочу создать двумерный массив в Python, и мне хотелось бы перебрать каждый элемент и взять среднее значение. Элемент i должен быть усреднен с использованием 8 окружающих элементов массива (включая элемент i).
Я сгенерировал двумерный массив с рамкой из нулей, используя Формирование рамки из нулей вокруг матрицы в Python.
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
x,y = A.shape
n = 1
B = np.zeros((x+2*n,y+2*n),dtype=int)
B[n:x+n, n:y+n] = A
print(B)
Как проще всего взять среднее значение?
🤔 А знаете ли вы, что...
В Python есть множество библиотек и фреймворков для разработки веб-приложений.
Получите каждую подматрицу и возьмите среднее значение. Сохраните результаты в отдельной матрице (иначе ранее вычисленное среднее испортит расчет следующего среднего):
Код:
import numpy as np
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
x,y = A.shape
n = 1
B = np.zeros((x+2*n,y+2*n),dtype=float)
B[n:x+n, n:y+n] = A
C = B.copy() # not doing it in-place because the math would get messed up
for i in range(x):
for j in range(y):
sub_b = B[i:i+x, j:j+y]
average = np.sum(sub_b) / 9
C[i + n, j + n] = average
print(C)
Выход:
[[0. 0. 0. 0. 0. ]
[0. 1.33333333 2.33333333 1.77777778 0. ]
[0. 3. 5. 3.66666667 0. ]
[0. 2.66666667 4.33333333 3.11111111 0. ]
[0. 0. 0. 0. 0. ]]
Чтобы вычислить среднее значение каждого элемента в 2D-массиве, включая 8 окружающих его элементов (и самого себя), вы можете использовать свертку с ядром, которое представляет окружающие элементы. Вот как вы можете это сделать:
Создайте исходный массив с кадром из нулей: у вас уже есть массив «B».
Перебрать массив и вычислить среднее значение:
Код:
import numpy as np
from scipy.ndimage import convolve
#Original 2D array
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
#Create a frame of zeros around the original array
x, y = A.shape
n = 1
B = np.zeros((x + 2*n, y + 2*n), dtype=int)
B[n:x+n, n:y+n] = A
print("Array with zero padding:")
print(B)
#Define the 3x3 kernel for averaging
kernel = np.ones((3, 3))
averaged_array = convolve(B, kernel, mode='constant', cval=0.0) / 9.0
#Remove the zero padding to get the averaged result for the original array
averaged_result = averaged_array[n:x+n, n:y+n]
print("\nAveraged array:")
print(averaged_result)
Это можно сделать относительно просто, используя ядро (фильтр) 3x3 в вашем массиве, а также правильно проверив, сколько соседей на самом деле имеет каждый элемент (например, края и углы), прежде чем делить, чтобы найти среднее значение.
from scipy.ndimage import convolve
import numpy as np
array = ...
kernel = np.array([[1,1,1],
[1,1,1],
[1,1,1]])
sum_neighbour = convolve(array, kernel, mode='constant', cval=0.0)
neighbour_count = convolve(np.ones_like(array), kernel, mode='constant', cval=0.0)
avg = sum_neighbour / neighbour_count
бывший:
матрица:
1,2,3,4
5,6,7,8
9,10,11,12,
13,14,15,16
имеет количество соседей:
4,6,6,4
6,9,9,6
6,9,9,6
4,6,6,4
сумма:
14, 24, 30, 22
33, 54, ...
среднее:
3.5, 4, 5, 5.5
5.5, 6.0, ...
Вам нужна 2D-свертка, используйте scipy.signal.convolve2d с numpy.ones, чтобы получить сумму:
from scipy.signal import convolve2d
out = convolve2d(B, np.ones((3, 3), dtype='int'), mode='same')
Выход:
array([[ 1, 3, 6, 5, 3],
[ 5, 12, 21, 16, 9],
[12, 27, 45, 33, 18],
[11, 24, 39, 28, 15],
[ 7, 15, 24, 17, 9]])
Если вам нужна небольшая матрица, не нужно дополнять ее нулями:
convolve2d(A, np.ones((3, 3), dtype='int'), mode='same')
# array([[12, 21, 16],
# [27, 45, 33],
# [24, 39, 28]])
Для получения среднего повторите ту же операцию с массивом и разделите:
kernel = np.ones((3, 3), dtype='int')
out = (convolve2d(A, kernel, mode='same')
/convolve2d(np.ones_like(A), kernel, mode='same')
)
выход:
array([[3. , 3.5, 4. ],
[4.5, 5. , 5.5],
[6. , 6.5, 7. ]])