2013-06-07 1 views
4

2D 배열을 그려 윤곽을 그리면 cs = plt.contour(...); cs.allsegs을 통해 세그먼트 맵에 액세스 할 수 있지만 선으로 매개 변수화됩니다. segmap 부울 마스크를 사용하여 선의 내부 구조를 알려주고 싶습니다. 그렇게 말하면 윤곽선 안의 모든 것을 신속하게 합칠 수 있습니다.Matplotlib을 사용하여 윤곽선에서 이미지 마스크로 이동하는 방법

감사합니다.

+0

윤곽 플롯을 생성하는 원래 '데이터'에 액세스 할 수 없습니까? 'data> threshold'를 실행하여 원하는 부울 마스크를 생성 할 수 있어야합니다. 여기서 threshold는 등고선의 값입니다. –

+0

이것은 특정 상황에서 작동하지만, 예를 들어 데이터에 여러 개의 피크가있는 경우 동일한 값에 대해 여러 개의 등고선을 가질 수 있습니다. 임계 값을 사용하면 모든 등고선에서 데이터를 선택할 수 있습니다. –

답변

6

정말 쉬운 방법이 있다고 생각하지 않습니다. 주로 래스터와 벡터 데이터를 혼합하기를 원하기 때문입니다. Matplotlib 경로는 다행스럽게도 경로 내에 포인트가 있는지 확인하는 방법이 있습니다. 모든 픽셀에 대해 마스크를 만들 것이지만이 방법은 대형 데이터 세트의 경우 매우 느려질 수 있습니다. 등고선 습관이 가장자리를 따라 길을 기본적으로 다른 가장자리에 플롯을 '떠나'고

import matplotlib.patches as patches 
from matplotlib.nxutils import points_inside_poly 
import matplotlib.pyplot as plt 
import numpy as np 

# generate some data 
X, Y = np.meshgrid(np.arange(-3.0, 3.0, 0.025), np.arange(-3.0, 3.0, 0.025)) 
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
# difference of Gaussians 
Z = 10.0 * (Z2 - Z1) 

fig, axs = plt.subplots(1,2, figsize=(12,6), subplot_kw={'xticks': [], 'yticks': [], 'frameon': False}) 

# create a normal contour plot 
axs[0].set_title('Standard contour plot') 
im = axs[0].imshow(Z, cmap=plt.cm.Greys_r) 
cs = axs[0].contour(Z, np.arange(-3, 4, .5), linewidths=2, colors='red', linestyles='solid') 

# get the path from 1 of the contour lines 
verts = cs.collections[7].get_paths()[0] 

# highlight the selected contour with yellow 
axs[0].add_patch(patches.PathPatch(verts, facecolor='none', ec='yellow', lw=2, zorder=50)) 

# make a mask from it with the dimensions of Z 
mask = verts.contains_points(list(np.ndindex(Z.shape))) 
mask = mask.reshape(Z.shape).T 

axs[1].set_title('Mask of everything within one contour line') 
axs[1].imshow(mask, cmap=plt.cm.Greys_r, interpolation='none') 

# get the sum of everything within the contour 
# the mask is inverted because everything within the contour should not be masked 
print np.ma.MaskedArray(Z, mask=~mask).sum() 

참고. 이 줄은 몇 가지 추가 처리가 필요합니다.

+0

이것은 훌륭한 대답입니다. 대신'scipy.ndimage.measurements.label'을 사용하여 결국 필자는 필요한 컨투어 마스크를 만듭니다. 다른 패키지를 사용하는 것은 당연히 내가 원하는 것은 아니지만, 어쨌든 고맙습니다! – Chris

1

또 다른 방법은, 아마도 더 직관적 scipy.ndimage에서 binary_fill_holes 기능입니다.

import numpy as np 
import scipy 


image = np.zeros((512, 512)) 
image[contour1[:, 0], contour1[:, 1]] = 1 
masked_image = scipy.ndimage.morphology.binary_fill_holes(image) 
```