19

私はこのようなnumpy配列を持っています:

x = np.array([[1,2,3],[4,5,6],[7,8,9]])

次の入力パラメーターを使用して、関数を「ネイバー」と呼びましょう。

  • x:ずんぐりした2次元配列
  • (i、j):2次元配列内の要素のインデックス
  • d:近傍半径

i,j出力として、指定された距離のセルの近傍を取得したいと思いdます。だから私が走れば

neighbors(im, i, j, d=1) with i = 1 and j = 1 (element value = 5) 

次の値のインデックスを取得する必要があります[1,2,3,4,6,7,8,9]。はっきりさせておきたい。これを扱うscipyのようなライブラリはありますか?

私は何かうまくいくことをしましたが、それは大まかな解決策です。

def pixel_neighbours(self, p):

    rows, cols = self.im.shape

    i, j = p[0], p[1]

    rmin = i - 1 if i - 1 >= 0 else 0
    rmax = i + 1 if i + 1 < rows else i

    cmin = j - 1 if j - 1 >= 0 else 0
    cmax = j + 1 if j + 1 < cols else j

    neighbours = []

    for x in xrange(rmin, rmax + 1):
        for y in xrange(cmin, cmax + 1):
            neighbours.append([x, y])
    neighbours.remove([p[0], p[1]])

    return neighbours

どうすればこれを改善できますか?

4

7 に答える 7

29

をご覧くださいscipy.ndimage.generic_filter

例として:

import numpy as np
import scipy.ndimage as ndimage

def test_func(values):
    print(values)
    return values.sum()


x = np.array([[1,2,3],[4,5,6],[7,8,9]])

footprint = np.array([[1,1,1],
                      [1,0,1],
                      [1,1,1]])

results = ndimage.generic_filter(x, test_func, footprint=footprint)

デフォルトでは、境界の値を「反映」します。modeこれは、キーワード引数を使用して制御できます。

ただし、このようなことをしたい場合は、問題をある種の畳み込みとして表現できる可能性があります。もしそうなら、それを畳み込みステップに分解し、より最適化された関数(例えばのほとんどscipy.ndimage)を使用する方がはるかに高速になります。

于 2012-06-12T13:46:47.553 に答える
9

編集:ああ、私の答えはただ書いているim[i-d:i+d+1, j-d:j+d+1].flatten()だけですが、理解できない方法で書かれています:)


ここでは、古き良きスライディング ウィンドウのトリックが役立ちます。

import numpy as np
from numpy.lib.stride_tricks import as_strided

def sliding_window(arr, window_size):
    """ Construct a sliding window view of the array"""
    arr = np.asarray(arr)
    window_size = int(window_size)
    if arr.ndim != 2:
        raise ValueError("need 2-D input")
    if not (window_size > 0):
        raise ValueError("need a positive window size")
    shape = (arr.shape[0] - window_size + 1,
             arr.shape[1] - window_size + 1,
             window_size, window_size)
    if shape[0] <= 0:
        shape = (1, shape[1], arr.shape[0], shape[3])
    if shape[1] <= 0:
        shape = (shape[0], 1, shape[2], arr.shape[1])
    strides = (arr.shape[1]*arr.itemsize, arr.itemsize,
               arr.shape[1]*arr.itemsize, arr.itemsize)
    return as_strided(arr, shape=shape, strides=strides)

def cell_neighbors(arr, i, j, d):
    """Return d-th neighbors of cell (i, j)"""
    w = sliding_window(arr, 2*d+1)

    ix = np.clip(i - d, 0, w.shape[0]-1)
    jx = np.clip(j - d, 0, w.shape[1]-1)

    i0 = max(0, i - d - ix)
    j0 = max(0, j - d - jx)
    i1 = w.shape[2] - max(0, d - i + ix)
    j1 = w.shape[3] - max(0, d - j + jx)

    return w[ix, jx][i0:i1,j0:j1].ravel()

x = np.arange(8*8).reshape(8, 8)
print x

for d in [1, 2]:
    for p in [(0,0), (0,1), (6,6), (8,8)]:
        print "-- d=%d, %r" % (d, p)
        print cell_neighbors(x, p[0], p[1], d=d)

ここではタイミングを取りませんでしたが、このバージョンのパフォーマンスは妥当である可能性があります。

詳細については、「ローリング ウィンドウ numpy」または「スライディング ウィンドウ numpy」という語句でネットを検索してください。

于 2012-06-12T15:48:33.847 に答える
4

このためのライブラリ関数については知りませんが、numpy の優れたスライス機能を使用して、このようなものを自分で簡単に作成できます。

import numpy as np
def neighbors(im, i, j, d=1):
    n = im[i-d:i+d+1, j-d:j+d+1].flatten()
    # remove the element (i,j)
    n = np.hstack((b[:len(b)//2],b[len(b)//2+1:] ))
    return n

もちろん、範囲外のアクセスを避けるために、いくつかの範囲チェックを行う必要があります。

于 2012-06-12T12:51:28.403 に答える
2

足跡に追加するだけで、ジョー・キングトンの応答に同意します

import numpy as np
from scipy.ndimage import generate_binary_structure
from scipy.ndimage import iterate_structure
foot = np.array(generate_binary_structure(2, 1),dtype=int)

またはexのより大きな/異なるフットプリントの場合。

np.array(iterate_structure(foot , 2),dtype=int)
于 2017-01-16T09:32:46.560 に答える
-1

おそらくSciPyでKDTreeを使用しますか?

于 2012-06-12T12:55:07.833 に答える