2012-03-13 15 views
12

Amacım, içinde çok fazla ayrı şekil bulunan çizimleri izlemek ve bu şekilleri ayrı görüntülere ayırmaktır. Beyaz üzerine siyah. Ben Numpy, opencv & eş için oldukça yeni - ama burada benim şimdiki düşünce: siyah pikseller içinNumpy/scipy ile şekil tanıma (belki de havlama)

  • tarama
  • siyah piksel bulundu ->
  • (çokgen yolu gibi) havza sınırına bulmak havza
  • Aramaya devam, ama zaten bulunan sınırların Ben bu tür şeyler çok iyi değilim

içindeki noktaları göz ardı daha iyi bir yolu var mı?

İlk (bu örnekler daha fazla veya daha az bir kolaj) havza sonuçlarının dikdörtgen sınırlayıcı kutu bulmaya çalıştık:

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 
şekilde

, orijinal dizi kullanımı (a) o zaman argwhere işe yarıyor gibi görünüyor, ama havzadan sonra (res) sadece diziyi tekrar çıktı.

Sonraki adım, şekil etrafında çokgen yolunu bulmak olabilir, ancak sınırlayıcı kutu şu an için harika olurdu!

Lütfen yardım edin!

cevap

14

@Hooked zaten sorunuzun cevaplamıştır ama telefonu açınca bu kadar yazma ortasında oldu, bu yüzden onu göndeririz Umarım hala yararlıdır ...

Çok fazla sayıda çemberden atlamaya çalışıyorsunuz. watershed_ift'a ihtiyacınız yok.

Her bir nesnenin sınırlayıcı kutusunu bulmak için, bir boole dizisindeki ayrı nesneleri ve scipy.ndimage.find_objects ayırt etmek için scipy.ndimage.label kullanın.

Bazı şeyleri biraz bozalım.

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

biraz daha net nesnelerin sınırlayıcı kutularını bulmak için nasıl yapar Umarım.

+0

Yanıtlarınız için ikinize de çok teşekkür ederim, bence bu öyle. Sadece bir tane yeni bir soru: eğer olabilirse: Sınırlayıcı rektlerin alanını kaydedemiyorum, çünkü diğer şekiller 'göz atıyor'. Bu yüzden planım, tersine çevrilmiş etiket dizisi ile görüntü alanını çarpmaktır (böylece mevcut şeklin dışındaki her şey siyah olur) ve ardından görüntü alanını ndimage ile kaydeder. Bunu nasıl yapacağımı doğru yöne yönlendirebilir misin?Biliyorum, vaktim olduğu anda dikkatlice rtfm yapacağım! – user978250

+1

Sadece 'label' (labeled array) içindeki 'number' nesnesinin numarası olan 'label == num' olduğunu istediğinizi düşünüyorum. Bu gibi işlemler numpy dizilerinde vektör edilir, bu yüzden kelimenin tam anlamıyla yukarıdaki ifadedir. "Nesne" nin içinde "Doğru" bir boole dizisi ve "Yanlış" ifadesini alırsınız. –

5

ndimage kitaplığını scipy'den kullanın. label işlevi, eşikteki piksellerin her bir blokuna benzersiz bir etiket yerleştirir. Bu, benzersiz kümeleri (şekilleri) tanımlar. a tanımına ile başlayan:

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

İlgili konular