Python: Numpy срезы не сравниваются / транслируются вместе. [x: y] vs [0: yx] Заявление о разных размерах - PullRequest
0 голосов
/ 05 мая 2020

Я сравниваю два фрагмента одного и того же массива. Два среза одинаковы, за исключением того, что они смещены по оси [1]. Я сравниваю эти два фрагмента и через некоторое время возвращаю их минимум l oop.

Мое ожидание: Размер массивов остается неизменным относительно друг друга, уменьшаясь на величину of «offset»

Что происходит вместо: Один из массивов уменьшается в размере относительно другого во второй итерации, уменьшаясь более чем на значение «offset»

Поскольку я использую одно и то же значение смещения для их сравнения, и поскольку (xy) - 0 = x - (0 + y), эти значения должны быть одинаковыми. Для первой итерации они одинаковы, но для второй итерации они не совпадают, как вы можете видеть из распечатанных результатов.

Я думал, что проблема может быть связана с проблемами передачи по значению , поэтому я попытался использовать copy.deepcopy, но это тоже не помогло. Я также подумал, что в индексировании индексов переполнения может быть странность, поэтому я на всякий случай установил высоту и ширину на единицу меньше, но это тоже не дало никакого эффекта. Мне интересно, возможно ли у меня фундаментальное непонимание того, как работает нарезка или расширенная индексация.

Вот распечатанный результат:

Slice 1: offset value: 1    height, width: 999 1332
Slice 2: offset value: 1    height, width: 999 1332
Slice 1: offset value: 2    height, width: 999 1331
Slice 2: offset value: 2    height, width: 999 1330

Вот ошибка, которую я получаю, она запускается вторая итерация while l oop:

    image = np.minimum(slice1, slice2)

ValueError: operands could not be broadcast together with shapes (999,1331) (999,1330)

Вот мой код:

def horizontal_smear(image, distance):

    height = len(image) - 1
    width  = len(image[0] - 1)
    offset = 1

    while offset < distance /2:

        slice1 = copy.deepcopy(image[0 : height, 0 : (width - offset)])
        print ("Slice 1: offset value:", offset, "   height, width:", len(slice1), len(slice1[0]))        
        slice2 = copy.deepcopy(image[0 : height, offset : width])
        print ("Slice 2: offset value:", offset, "   height, width:", len(slice2), len(slice2[0]))        

        image = np.minimum(slice1, slice2)
        offset *= 2

    return image

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Ваш второй фрагмент проходит от конца сжатого image массива. Проблема в том, что ваш код повторно связывает image с последовательно меньшими массивами, но ваша переменная width остается той же (на единицу меньше исходного размера). Вероятно, вам нужно обновить width внутри l oop.

# move the width line from here
offset = 1

while offset < distance /2:
    width = len(image[0] - 1)   # to here

    ...

Подробнее о том, почему ваш код завершился с точной ошибкой: когда вы отрезаете конец контейнера в Python (включая Numpy массивы, которые не всегда ведут себя так же, как другие типы), вы получаете меньший результат, чем вы могли ожидать, и без ошибок. Вот пример со списками:

a = [1, 2, 3]
b = a[0:2] # len(b) is 2
c = a[2:4] # len(c) is unexpectedly 1!

Срез для создания c приводит к одноэлементному списку, потому что после индекса 2 больше нет элементов, хотя нотация срезов могла заставить вас ожидать результат должен иметь два элемента (из индексов 2-3).

0 голосов
/ 05 мая 2020

Это устраняет ошибку кодирования, мешающую правильной работе функции. Он не объясняет основной механизм ошибки:

в то время как l oop изображение сжимается, так что каждая последующая копия slice1 и slice2 имеет меньше исходных данных для извлечения, кроме "высоты" и «ширина» остается неизменной. Поскольку срез 2 находится дальше вправо, чем срез 1, это выталкивает его из диапазона индексации. (Вероятно, это как-то связано с тем, почему его индексы сокращаются, но я не знаю, как numpy обрабатывает данные вне диапазона.)

Изменение строки image = np.minimum(slice1, slice2) на

image[0:height, 0:(width - offset)] = np.minimum(slice1, slice2) устраняет проблему.

...