2016-06-28 5 views
5

다음을 찾고 있습니다. 나는 지역으로 라벨이 매겨져있다. numpy 배열은 분할 된 이미지를 나타냅니다. 영역은 동일한 값을 갖는 인접 셀의 수입니다. 각 지역마다 고유 한 가치가 있습니다. 3 개의 영역으로 단순화 된 버전은 다음과 같을 것이다 :numpy 배열에서 인접한 영역을 결정하십시오.

x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32) 

출력 : 위 예에서

array([[1, 1, 1], 
     [1, 1, 2], 
     [2, 2, 2], 
     [3, 3, 3]]) 

우리는 별도의 영역 (3), 고유 값으로 표시된 각 (1,2,3에있을 이 경우).

내가 원하는 것은 각 개별 영역에 인접한 (이웃) 영역의 값입니다. 그래서이 경우 :

  • 지역 1 지역에 인접한 2
  • 지역 2 지역 1과 3
  • 지역에 인접한 3 지역 2

에 인접한이 될 것입니다 무엇 이것을 달성하는 가장 우아하고 빠른 방법?

감사합니다.

+0

지역별 의미를 설명해 주시겠습니까? 열을 의미합니까? –

+0

이 경우 지역 정의에 대한 몇 가지 추가 설명을 추가했습니다. – cf2

답변

4

주어진 숫자 (예 : 2)에 인접한 배열의 모든 고유 항목을 반환하는 것으로 알고 있습니다. NumPy 메서드로이 작업을 수행하는 한 가지 방법은 roll을 사용하여 주어진 영역을 위, 아래, 왼쪽 및 오른쪽으로 한 단위 씩 이동하는 것입니다. 이동 된 영역의 논리합이 취해지고이 조건과 일치하는 모든 별개의 요소가 반환됩니다. 그런 다음 자신의 이웃으로 간주되지 않으므로 영역 자체를 제거해야합니다.

roll은 반대쪽 끝 (여기서는 바람직하지 않음)에서 배열의 경계를 넘어서는 값을 다시 도입하므로이 행이나 열을 False로 바꾸는 추가 단계가 있습니다.

n = x.max() 
tmp = np.zeros((n+1, n+1), bool) 

# check the vertical adjacency 
a, b = x[:-1, :], x[1:, :] 
tmp[a[a!=b], b[a!=b]] = True 

# check the horizontal adjacency 
a, b = x[:, :-1], x[:, 1:] 
tmp[a[a!=b], b[a!=b]] = True 

# register adjacency in both directions (up, down) and (left,right) 
result = (tmp | tmp.T) 

질문의 예 어레이 : 영역이 (0에서 이상적 n에) 작은 정수로 표지하는 경우

import numpy as np 

x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32) 
region = 2 # number of region whose neighbors we want 

y = x == region # convert to Boolean 

rolled = np.roll(y, 1, axis=0)   # shift down 
rolled[0, :] = False    
z = np.logical_or(y, rolled) 

rolled = np.roll(y, -1, axis=0)   # shift up 
rolled[-1, :] = False 
z = np.logical_or(z, rolled) 

rolled = np.roll(y, 1, axis=1)   # shift right 
rolled[:, 0] = False 
z = np.logical_or(z, rolled) 

rolled = np.roll(y, -1, axis=1)   # shift left 
rolled[:, -1] = False 
z = np.logical_or(z, rolled) 

neighbors = set(np.unique(np.extract(z, x))) - set([region]) 
print(neighbors) 
+0

완벽하게 작동합니다. 나는 또한 무작위로 번호가 매겨진 지역의 대규모 데이터 세트에서이를 테스트 해 보았습니다. 많은 솔루션에 감사드립니다! – cf2

2

, 라벨이 결과 배열 인덱스로 사용할 수있다 :

In [58]: result.astype(int) 
Out[58]: 
array([[0, 0, 0, 0], 
     [0, 0, 1, 0], 
     [0, 1, 0, 1], 
     [0, 0, 1, 0]]) 

In [60]: np.column_stack(np.nonzero(result)) 
Out[60]: 
array([[1, 2], 
     [2, 1], 
     [2, 3], 
     [3, 2]]) 

In [361]: # Assuming labels start from `1` 
      [np.flatnonzero(row) for row in result[1:]] 
Out[361]: [array([2]), array([1, 3]), array([2])] 
+0

모든 지역에 대해 인덱싱 된 결과 배열을 반환하므로 솔루션을 정말 좋아합니다. 그러나 내 지역은 무작위로 번호가 매겨져 있으며 이로 인해 내 데이터 세트에서 불행히도 귀하의 솔루션이 작동하지 않습니다. 그래도 고마워! 정렬 된 영역이있는 데이터 집합이있는 경우이 솔루션을 유지할 것입니다. – cf2

관련 문제