Как увеличить числовой массив с ближайшим соседом, не сохраняя повторяющиеся значения? - PullRequest
0 голосов
/ 01 апреля 2019

Допустим, у меня есть массив 3x3 a, и я хотел бы увеличить его до массива 30x30 b с интерполяцией ближайшего соседа.

Можно ли использовать технику, которая на самом деле не хранит повторяющиеся значения? Что-то похожее на то, как broadcasting работает в numpy.

например. Я хотел бы иметь такой объект, чтобы при вызове b[x, x] с 0 < x < 10 я получал a[0, 0].

Ответы [ 2 ]

1 голос
/ 01 апреля 2019

Вы можете достичь объекта, подобного тому, который вы описываете, создав класс, который оборачивает пустой массив и реализует пользовательский метод __getitem__. Это может выглядеть примерно так, как показано ниже, где factor - это фактор, с которым вы хотите повысить частоту.

class UpSampled:
    __slots__ = ('arr', 'factor')

    def __init__(self, arr, factor):
        self.arr = arr
        self.factor = factor

    def __getitem__(self, key):
        return self.arr[key // self.factor]

Затем вы бы использовали его, как показано ниже:

o = UpSampled(np.array([
    UpSampled(np.array([0, 1, 2]), 10),
    UpSampled(np.array([3, 4, 5]), 10),
    UpSampled(np.array([6, 7, 8]), 10),
]), 10)

print(o[23][13])  # prints 7

Если вам нужно, чтобы объект был итеративным, вы бы также реализовали __next__ и __iter__:

class UpSampled:
    __slots__ = ('arr', 'factor', '__index')

    def __init__(self, arr, factor):
        self.arr = arr
        self.factor = factor
        self.__index = 0

    def __getitem__(self, key):
        return self.arr[key // self.factor]

    def __iter__(self):
        self.__index = 0
        return self

    def __next__(self):
        try:
            result = self[self.__index]
        except IndexError:
            raise StopIteration
        self.__index += 1
        return result

Хотя я не уверен, что это будет хорошо работать с библиотеками, которые специально ожидают массив numpy.

1 голос
/ 01 апреля 2019

Я не верю, что есть какой-то способ сделать это, используя numpy. Вещание работает в «numpy» так, что у каждой оси есть параметр «шага», который контролирует, как рассчитать следующий элемент вдоль оси. Так, например:

In [1]: a = np.arange(10)

In [2]: a
Out[2]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [3]: b = a[::2]

In [4]: b
Out[4]: array([0, 2, 4, 6, 8])

In [5]: b.strides
Out[5]: (16,)

In [6]: a.strides
Out[6]: (8,)

В этом случае вы можете видеть, что b - это просто представление полученного путем удвоения шага по первому измерению. Поэтому при доступе к b[1] смещение вычисляется как b.__array_interface__['data'][0] + b.strides[0].

В вашем случае вам нужен нелинейный шаг, который не поддерживается.

Конечно, вы могли бы добиться этого самостоятельно, рассчитав индексы самостоятельно, т. Е .:

a[x//10,x//10]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...