#python #arrays #image-processing #lambda #scikit-image
#питон #массивы #обработка изображений #лямбда #scikit-изображение
Вопрос:
У меня есть массив:
import numpy as np
arr = np.random.randint(0,10,size=[8,8])
arr
является:
array([[9, 1, 8, 2, 0, 4],
[0, 7, 6, 9, 7, 5],
[0, 7, 1, 6, 6, 2],
[3, 6, 3, 3, 8, 1]])
Я хочу уменьшить размер этого массива с помощью skimage.measure.block_reduce
. Я так и делаю
from skimage import measure as sm
reduced_arr = sm.block_reduce(arr, block_size=(4,6), func=np.max)
reduced_arr
является:
array([[6, 7],
[9, 7]])
Я пытаюсь добиться того же самого, используя лямбда-функцию:
reduced_arr = sm.block_reduce(arr, block_size=(2,4), func= lambda block: np.max(block))
Затем я получаю сообщение об ошибке:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-115-a11dc12d3db0> in <module>()
----> 1 reduced_arr = sm.block_reduce(arr, block_size=(2,4), func= lambda block: np.max(block))
/usr/local/lib/python3.7/dist-packages/skimage/measure/block.py in block_reduce(image, block_size, func, cval, func_kwargs)
85
86 return func(blocked, axis=tuple(range(image.ndim, blocked.ndim)),
---> 87 **func_kwargs)
TypeError: <lambda>() got an unexpected keyword argument 'axis'
Как использовать block_reduce
с лямбда-функциями?
Мой вариант использования в реальном мире сложнее, чем просто готовая функция numpy, вот почему мне это нужно.
Ответ №1:
Не уверен, что на этот вопрос все еще нужен ответ, но я видел другой, так что давайте попробуем.
Следуя документу skimage, указано, что функция, указанная в аргументе, должна «реализовывать параметр оси». Быстро ищем np.mean
в документе numpy, и вы видите, что он действительно реализует параметр оси.
Поэтому в источнике самого сокращения блока параметр axis вызывается func
:
def block_reduce(image, block_size=2, func=np.sum, cval=0, func_kwargs=None):
...
return func(blocked, axis=tuple(range(image.ndim, blocked.ndim)),
**func_kwargs)
При этом ваша пользовательская функция должна затем реализовать такое поведение. С быстрым исправлением ваш пример теперь будет работать правильно :
import numpy as np
arr = np.random.randint(0,10,size=[8,8])
arr
Out[53]:
array([[3, 3, 2, 8, 0, 4, 2, 6],
[8, 9, 8, 5, 1, 6, 1, 0],
[9, 2, 6, 9, 7, 9, 1, 6],
[3, 6, 8, 2, 8, 2, 1, 3],
[8, 0, 3, 3, 9, 6, 5, 4],
[5, 2, 9, 3, 8, 5, 9, 8],
[2, 9, 0, 7, 0, 0, 5, 8],
[6, 4, 7, 1, 9, 9, 6, 9]])
from skimage import measure as sm
reduced_arr = sm.block_reduce(arr, block_size=(4,6), func=np.max)
reduced_arr
Out[55]:
array([[9, 6],
[9, 9]])
reduced_arr_with_lambda = sm.block_reduce(arr, block_size=(4,6),
func= lambda block, axis: np.max(block, axis))
reduced_arr_with_lambda
Out[57]:
array([[9, 6],
[9, 9]])
np.testing.assert_array_equal(reduced_arr, reduced_arr_with_lambda)
Наконец, для более острой функции вам нужно понять, как работает ось кортежей, а для функции, отличной от numpy, реализовать способ использования axis. Честно говоря, это утомительно, поэтому мой совет — придерживаться функции numpy.