6

mam wiele szkiele- obrazy takie jak ten:Jak mogę znaleźć cykle w obrazie szkieletu z bibliotekami Pythona?

enter image description here enter image description here

jaki sposób można wykryć cykl, pętla w szkielecie? Czy są w tym "specjalne" funkcje, czy powinienem to zaimplementować jako wykres?

Jeśli jest tylko opcja wykresu, czy biblioteka sieci pythonów NetworkX może mi pomóc?

+0

Implementacja prostego wykresu jest łatwa w przypadku słowników Pythona. Oto [przykład z Pythona docs] (http://www.python.org/doc/essays/graphs/). NetworkX wydaje się być przesadą, chociaż nigdy jej nie używałem. Jeśli chodzi o konwersję obrazu na wykres, nie wiem, jak to zrobić, chociaż wydaje się, że jest to ciekawy problem. Używam [opencv] (http://opencv.org/), który zapewnia wiele funkcji do manipulowania obrazami. Możesz znaleźć w nim kilka użytecznych części. – KobeJohn

Odpowiedz

3

Możesz wykorzystać topologię szkieletu. Cykl nie będzie mieć dziur, więc możemy użyć scipy.ndimage, aby znaleźć wszelkie dziury i porównać. Nie jest to najszybsza metoda, ale kodowanie jest niezwykle łatwe.

import scipy.misc, scipy.ndimage 

# Read the image 
img = scipy.misc.imread("Skel.png") 

# Retain only the skeleton 
img[img!=255] = 0 
img = img.astype(bool) 

# Fill the holes 
img2 = scipy.ndimage.binary_fill_holes(img) 

# Compare the two, an image without cycles will have no holes 
print "Cycles in image: ", ~(img == img2).all() 

# As a test break the cycles 
img3 = img.copy() 
img3[0:200, 0:200] = 0 
img4 = scipy.ndimage.binary_fill_holes(img3) 

# Compare the two, an image without cycles will have no holes 
print "Cycles in image: ", ~(img3 == img4).all() 

Użyłem twojego zdjęcia "B" jako przykładu. Pierwsze dwa obrazy to oryginalna i wypełniona wersja, która wykrywa cykl. W drugiej wersji przerwałam cykl i nic się nie wypełniło, dlatego te dwa obrazy są takie same.

enter image description here

3

Konwersja obrazu szkieletu na reprezentację wykresu nie jest banalna i nie znam żadnych narzędzi, które by to zrobiły.

Jednym ze sposobów na zrobienie tego w bitmapie byłoby użycie modelu flood fill, takiego jak wiadro z farbą w programie Photoshop. Jeśli zaczniesz wypełniać obraz, całe tło zostanie wypełnione, jeśli nie ma cykli. Jeśli wypełnienie nie dostanie całego obrazu, to znalazłeś cykl. Sprawne znalezienie wszystkich cykli może wymagać wielokrotnego napełniania.

Prawdopodobnie będzie to bardzo powolne wykonanie, ale prawdopodobnie znacznie szybsze do kodu niż technika, w której prześledzimy szkielet do struktury danych wykresu.

+1

Myślę, że to dobre rozwiązanie. Liczę liczbę pikseli szkieletu i całkowitą liczbę pikseli obrazu i obliczam różnicę, jeśli wypełnienie wypełnienia zwraca mi taką samą liczbę pikseli, że nie ma cykli, jeśli zwraca mniej, są cykle. – improc

+0

Tak, w zasadzie musisz opisać uzupełnienie szkieletów.Spowoduje to zwrócenie połączonych komponentów wyciętych przez pętle szkieletów. Jeśli liczba składników jest większa niż 1, powiedz N, masz pętle N-1. Może to również być postrzegane jako forma do przerzedzania szkieletu. – beedot

4

Najpierw zbudować wizerunek literę B z PIL:

import Image, ImageDraw, ImageFont 
image = Image.new("RGBA", (600,150), (255,255,255)) 
draw = ImageDraw.Draw(image) 
fontsize = 150 
font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", fontsize) 
txt = 'B' 
draw.text((30, 5), txt, (0,0,0), font=font) 
img = image.resize((188,45), Image.ANTIALIAS) 
print type(img) 
plt.imshow(img) 

można znaleźć lepszy sposób, aby to zrobić, szczególnie w drodze do czcionek. Ii lepiej byłoby załadować obraz zamiast go generować. W każdym razie, mamy teraz coś do pracy na: Upper B

Teraz, części rzeczywistej:

import mahotas as mh 
img = np.array(img) 
im = img[:,0:50,0] 
im = im < 128 
skel = mh.thin(im) 
noholes = mh.morph.close_holes(skel) 
plt.subplot(311) 
plt.imshow(im) 
plt.subplot(312) 
plt.imshow(skel) 
plt.subplot(313) 
cskel = np.logical_not(skel) 
choles = np.logical_not(noholes) 
holes = np.logical_and(cskel,noholes) 
lab, n = mh.label(holes) 
print 'B has %s holes'% str(n) 
plt.imshow(lab) 

Holes labelling I mamy w konsoli (ipython): B posiada 2 otwory

Powiązane problemy