2012-03-13 3 views
12

내 목표는 그 안에 개별 모양이 많은 그림을 추적하고 이러한 모양을 개별 이미지로 분할하는 것입니다. 흰색 바탕에 검은 색입니다. 나는 NumPy와, OpenCV의 & 공동 아주 새로운 해요 -하지만 여기에 내 현재 생각입니다 : 검은 색 픽셀numpy/scipy (아마도 유역)로 형상 인식

  • 검사는
  • 블랙 픽셀 발견 ->
  • 은 (다각형 경로로) 유역 경계를 찾을 유역
  • 이 검색을 계속하지만, 이미 발견 경계 나는 사물의 이러한 종류의에서 아주 좋은 아니에요

내에서 점을 무시하고, 더 나은 방법은 무엇입니까?

먼저 I (이 예는 더 많거나 적은 콜라주) 유역 결과 직사각형 바운딩 박스를 찾으려고 :

from numpy import * 
import numpy as np 
from scipy import ndimage 

np.set_printoptions(threshold=np.nan) 

a = np.zeros((512, 512)).astype(np.uint8) #unsigned integer type needed by watershed 
y, x = np.ogrid[0:512, 0:512] 
m1 = ((y-200)**2 + (x-100)**2 < 30**2) 
m2 = ((y-350)**2 + (x-400)**2 < 20**2) 
m3 = ((y-260)**2 + (x-200)**2 < 20**2) 
a[m1+m2+m3]=1 

markers = np.zeros_like(a).astype(int16) 
markers[0, 0] = 1 
markers[200, 100] = 2 
markers[350, 400] = 3 
markers[260, 200] = 4 

res = ndimage.watershed_ift(a.astype(uint8), markers) 
unique(res) 

B = argwhere(res.astype(uint8)) 
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1 
tr = a[ystart:ystop, xstart:xstop] 

print tr 

, I는 원의 배열을 사용하는 경우 (a) argwhere가 작동하는 것처럼 보이지만, 유역 (res) 이후에는 완전한 배열을 다시 출력합니다.

다음 단계는 도형 주위의 다각형 경로를 찾는 것이지만 경계 상자는 지금 당장 좋습니다!

도와주세요!

답변

14

@Hooked 이미 귀하의 질문에 대부분의 대답했지만, 나는 그가 대답 때를 작성하는 중간에, 그래서 내가 그것을 게시합니다 그것이 여전히 유용하다는 희망 ...

당신은 너무 많은 농구를 뛰어 넘기 위해 노력하고 있습니다. watershed_ift은 필요하지 않습니다.

scipy.ndimage.label을 사용하면 부울 배열의 개별 객체를 구별하고 scipy.ndimage.find_objects을 사용하여 각 객체의 경계 상자를 찾을 수 있습니다.

조금 더 자세히 해봅시다.

enter image description here enter image description here

import numpy as np 
from scipy import ndimage 
import matplotlib.pyplot as plt 

def draw_circle(grid, x0, y0, radius): 
    ny, nx = grid.shape 
    y, x = np.ogrid[:ny, :nx] 
    dist = np.hypot(x - x0, y - y0) 
    grid[dist < radius] = True 
    return grid 

# Generate 3 circles... 
a = np.zeros((512, 512), dtype=np.bool) 
draw_circle(a, 100, 200, 30) 
draw_circle(a, 400, 350, 20) 
draw_circle(a, 200, 260, 20) 

# Label the objects in the array. 
labels, numobjects = ndimage.label(a) 

# Now find their bounding boxes (This will be a tuple of slice objects) 
# You can use each one to directly index your data. 
# E.g. a[slices[0]] gives you the original data within the bounding box of the 
# first object. 
slices = ndimage.find_objects(labels) 

#-- Plotting... ------------------------------------- 
fig, ax = plt.subplots() 
ax.imshow(a) 
ax.set_title('Original Data') 

fig, ax = plt.subplots() 
ax.imshow(labels) 
ax.set_title('Labeled objects') 

fig, axes = plt.subplots(ncols=numobjects) 
for ax, sli in zip(axes.flat, slices): 
    ax.imshow(labels[sli], vmin=0, vmax=numobjects) 
    tpl = 'BBox:\nymin:{0.start}, ymax:{0.stop}\nxmin:{1.start}, xmax:{1.stop}' 
    ax.set_title(tpl.format(*sli)) 
fig.suptitle('Individual Objects') 

plt.show() 

enter image description here

이 조금 더 명확 객체의 경계 상자를 찾는 방법을 만드는 희망.

+0

답장을 보내 주셔서 감사합니다. 내가 할 수있는 한 초짜 numpy 질문 하나만 : 다른 셰이프를 '엿보기'때문에 나는 경계 사각형의 영역을 저장할 수 없습니다. 그래서 내 계획은 이미지 영역에 거꾸로 된 라벨 배열을 곱하는 것입니다 (따라서 현재 모양 바깥의 모든 것이 검은 색이됩니다). 그런 다음 이미지 영역을 ndimage로 저장하십시오. 이 일을 어떻게 올바른 방향으로 가르쳐 주시겠습니까?나는 내가 곧 신중하게 rtfm 할 시간이있는 것을 안다! – user978250

+1

나는'label == num'을 원한다고 생각한다.'num'은'label'에있는 객체의 번호입니다. 이와 같은 연산은 숫자가 적은 배열에서 벡터화되므로 문자 그대로 위의 구문과 동일합니다. "object"내부에는'True'의 불리언 값 배열이 있고, 바깥에는'False' 배열이 있습니다. –

5

scipy의 ndimage 라이브러리를 사용하십시오.함수는 임계 값 내에있는 각 픽셀 블록에 고유 한 태그를 배치합니다. 고유 한 클러스터 (모양)를 식별합니다. a의 당신의 정의를 시작으로 :

from scipy import ndimage 

image_threshold = .5 
label_array, n_features = ndimage.label(a>image_threshold) 

# Plot the resulting shapes 
import pylab as plt 
plt.subplot(121) 
plt.imshow(a) 
plt.subplot(122) 
plt.imshow(label_array) 
plt.show() 

enter image description here

관련 문제