Проверка и заполнение центрального пикселя в режиме соседства 8 пикселей в большом массиве в Python - PullRequest
0 голосов
/ 05 августа 2020

У меня есть большой двоичный массив (500 x 700), в котором я хочу проверить 'NaNs' и заполнить центральный пиксель режимом восьми окружающих пикселей (если более 4 окружающих пикселей имеют 0 или 1). Это больше похоже на поиск в скользящем окне 3x3. Есть ли какие-либо инструменты / функции для этого в xarray или scipy.ndimage или даже numpy?

Например,

arr = np.asarray([0,  1,  1,  1,  0,  1, 1, np.nan, 0,  1,  0,  1, 1,  1,  0,  1,  1, np.nan]).reshape(3,6)

arr[1,1] = 1 
arr[-1,-1] = 1 (only 3 neighbours)

Любая помощь будет принята с благодарностью ..

Заранее спасибо.

1 Ответ

0 голосов
/ 05 августа 2020

Вы можете реализовать свою идею напрямую, используя numpy и scipy.stats.mode.

Во-первых, найдите расположение значений nan, сравнивая массив с самим собой, потому что число с плавающей запятой NaN не равно самому себе по определению. Функция np.where вернет все местоположения, выполняемые этим условием, в двух кортежах индексов, один для строк, а другой для столбцов.

Затем для каждого местоположения, в котором найдено NaN, добавьте 8 дельт к чтобы получить окружающие его пиксели. Это можно эффективно сделать с помощью дельта-массива, в котором перечислены все возможные смещения для индекса строки и столбца для каждого соседа.

Наконец, выполните внутреннюю проверку и запустите функцию mode на выбранном , допустимые соседи и заполните это значение в ячейке NaN.

Вот код, следующий за моим описанием выше:

import numpy as np
import scipy.stats

arr = np.asarray([
    0,  1,  1,  1,  0,  1,
    1, np.nan, 0,  1,  0,  1,
    1,  1,  0,  1,  1, np.nan
]).reshape(3, 6)

delta_rows = np.array([-1, -1, -1, 0, 0, 1, 1, 1])
delta_cols = np.array([-1, 0, 1, -1, 1, -1, 0, 1])
nan_rows, nan_cols = np.where(arr != arr)
for nan_row, nan_col in zip(nan_rows, nan_cols):
    neighbour_rows = nan_row + delta_rows
    neighbour_cols = nan_col + delta_cols
    within_boundary = (
        (0 <= neighbour_rows) & (neighbour_rows < arr.shape[0]) & 
        (0 <= neighbour_cols) & (neighbour_cols < arr.shape[1])
    )
    neighbour_rows = neighbour_rows[within_boundary]
    neighbour_cols = neighbour_cols[within_boundary]
    arr[nan_row, nan_col] = scipy.stats.mode(arr[neighbour_rows, neighbour_cols]).mode

После этого мы видим, что каждое значение NaN в arr правильно заполнен режимом окружающих его ячеек:

>>> print(arr)
[[0. 1. 1. 1. 0. 1.]
 [1. 1. 0. 1. 0. 1.]
 [1. 1. 0. 1. 1. 1.]]
...