Problemas durante la esqueletización de la imagen para extraer contornos.

Encontré este código para obtener una imagen esqueletizada. Tengo una imagen circular ( https://docs.google.com/file/d/0ByS6Z5WRz-h2RXdzVGtXUTlPSGc/edit?usp=sharing ).

img = cv2.imread(nomeimg,0) size = np.size(img) skel = np.zeros(img.shape,np.uint8) ret,img = cv2.threshold(img,127,255,0) element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3)) done = False while( not done): eroded = cv2.erode(img,element) temp = cv2.dilate(eroded,element) temp = cv2.subtract(img,temp) skel = cv2.bitwise_or(skel,temp) img = eroded.copy() zeros = size - cv2.countNonZero(img) if zeros==size: done = True print("skel") print(skel) cv2.imshow("skel",skel) cv2.waitKey(0) 

El problema es que el resultado de la imagen no es un “esqueleto” sino un conjunto de puntos. Mi propósito era extraer el perímetro del contorno después de haber esqueletizado la imagen. ¿Cómo puedo editar mi código para resolverlo? ¿Es correcto usar cv2.findContours para encontrar el círculo esqueleto?

cv2.dilate revertir blanco y negro, y rellenar todos los orificios llamando primero a cv2.dilate :

 import numpy as np import cv2 img = cv2.imread("e_5.jpg",0) size = np.size(img) skel = np.zeros(img.shape,np.uint8) ret,img = cv2.threshold(img,127,255,0) element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3)) img = 255 - img img = cv2.dilate(img, element, iterations=3) done = False while( not done): eroded = cv2.erode(img,element) temp = cv2.dilate(eroded,element) temp = cv2.subtract(img,temp) skel = cv2.bitwise_or(skel,temp) img = eroded.copy() zeros = size - cv2.countNonZero(img) if zeros==size: done = True 

Aquí está el resultado:

introduzca la descripción de la imagen aquí

Pero, el resultado no es bueno, porque hay muchas lagunas. El siguiente algoritmo es mejor, usa funciones en scipy.ndimage.morphology :

 import scipy.ndimage.morphology as m import numpy as np import cv2 def skeletonize(img): h1 = np.array([[0, 0, 0],[0, 1, 0],[1, 1, 1]]) m1 = np.array([[1, 1, 1],[0, 0, 0],[0, 0, 0]]) h2 = np.array([[0, 0, 0],[1, 1, 0],[0, 1, 0]]) m2 = np.array([[0, 1, 1],[0, 0, 1],[0, 0, 0]]) hit_list = [] miss_list = [] for k in range(4): hit_list.append(np.rot90(h1, k)) hit_list.append(np.rot90(h2, k)) miss_list.append(np.rot90(m1, k)) miss_list.append(np.rot90(m2, k)) img = img.copy() while True: last = img for hit, miss in zip(hit_list, miss_list): hm = m.binary_hit_or_miss(img, hit, miss) img = np.logical_and(img, np.logical_not(hm)) if np.all(img == last): break return img img = cv2.imread("e_5.jpg",0) ret,img = cv2.threshold(img,127,255,0) element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3)) img = 255 - img img = cv2.dilate(img, element, iterations=3) skel = skeletonize(img) imshow(skel, cmap="gray", interpolation="nearest") 

El resultado es:

introduzca la descripción de la imagen aquí

Su algoritmo de esqueletización calcula el esqueleto de un área blanca:

  • Desviación: establece el “píxel bajo prueba” en el mínimo de todos los píxeles dentro del elemento estructurante, negro
  • Dilatar: al lado de erosionar, establece el “píxel a prueba” en el valor máximo de todos los píxeles dentro del elemento estructurante, blanco> negro

Para corregir su código, puede cambiar los parámetros para su función de umbral:

 ret,img = cv2.threshold(img,240,255,1) 

Los parámetros se describen aquí .