2015-04-15 3 views
1

Я хочу применить круговую операцию окрестности в массиве 2D numpy, где каждое значение пикселя заменяется минимумом в пределах круговой окрестности (радиус = x).Циркулярное соседство - минимальное число

Я могу применить generic_filter, основанный на ядре, и получить минимум, но операция занимает квадратную окрестность, что дает неправильный вывод.

Я попытался использовать цикл for и выполнить операцию с использованием таблицы поиска радиуса, которая в основном представляет собой массив, который дает расстояние от первого пикселя и использует, если условия для получения минимума. Что-то вроде этого:

import numpy as np 

radiusGrid = np.random.randint(6, size=100).reshape(10,10) 
radiusLUT = np.ones((6,6)) 

print radiusGrid 

for i in xrange(6): 
    for j in xrange(6): 
     radiusLUT[i][j] = max(i,j) + (min(i,j)/2) 

radius = 3 

for y in xrange(10): 
    intermediateGridRow = intermediateGrid[y] 
    centerRadiusGridRow = radiusGrid[y] 
    for x in xrange(10): 
     startRow = max(y - radius,0) 
     startCol = max(x - radius,0) 
     endRow = min(y + radius +1, 10) 
     endCol = min(x + radius +1, 10) 
     minRadius = centerRadiusGridRow[x] 
     for row in xrange(startRow,endRow): 
      radiusGridRow = radiusGrid[row] 
      radiusLUTRow = radiusLUT[abs(y-row)] 
      for col in xrange(startCol,endCol): 
       if radiusLUTRow[abs(x-col)] < radius and radiusGridRow[col] < minRadius: 
        minRadius = radiusGridRow[col] 
     intermediateGridRow[x] = minRadius 
    intermediateGrid[y] = intermediateGridRow 

print intermediateGrid 

Выше был построен должен был получить минимум в пределах радиуса 3.

для реализации петли делает работу, но медленно для больших массивов. Я не склонен использовать Cython или f2py. Есть ли способ оптимизировать это?

+0

Запрашивать другие библиотеки не по теме для stackoverflow, но если вы включите свой код и попросите помочь улучшить его производительность, то у вас будет гораздо больше шансов получить некоторую помощь. – TheBlackCat

ответ

2
import numpy as np 
from scipy.ndimage.filters import generic_filter as gf 

kernel = np.zeros((2*radius+1, 2*radius+1)) 
y,x = np.ogrid[-radius:radius+1, -radius:radius+1] 
mask = x**2 + y**2 <= radius**2 
kernel[mask] = 1 
#calculate 
circular_min = gf(data, np.min, footprint=kernel) 
+2

Вместо 'generic_filter' вы можете использовать' scipy.ndimage.filters.minimum_filter'. –

+1

Согласно [docs] (http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.filters.generic_filter.html), 'footprint' является логическим массивом, поэтому вы должны быть способны передать 'mask' напрямую, не используя его для назначения массиву с плавающей запятой' kernel'. – Jaime

+0

@jaime хорошее наблюдение – valentin