2015-11-08 4 views
5

Ho bisogno di ottenere una matrice con le coordinate (x, y) del contorno dell'immagine seguente con python.Ottieni coordinate (x, y) di una forma in un'immagine con pitone

enter image description here

ho provato con OpenCV rilevatore astuto e trovare contorni ma ho un sacco di contorni e non so come ottenere quello che voglio.

import numpy as np 
from matplotlib import pyplot as plt 
import cv2 
#from skimage import measure, feature, io 
#from skimage import img_as_ubyte 

x1 = 330 
xf = 690 
y1 = 0 
yf = 400 

img = cv2.imread('test.tif') 
img = img[y1:yf, x1:xf] 
edge = cv2.Canny(img, 100, 200) 

image, contours, hierarchy = cv2.findContours(edge, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 

enter image description here

Mi serve solo un array con il (x, y) coordinate del profilo. Penso che sia in uscita contorni di cv2.findContours() ma non trovo il contorno che voglio ...

Ho provato anche con la funzione matplotlib.pyplot.contour:

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 

img = cv2.imread('test.tif', 0) # read image 
img = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1] # threshold image 
img = cv2.medianBlur(img, 15) # remove noise 

# skeletonize 
size = np.size(img) # get number of pixels 
skel = np.zeros(img.shape, np.uint8) # create an array of zeros with the same shape as the image and 256 gray levels 

element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) # create a structurant element (cross) 
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 

cs = plt.contour(skel, 1) 
p = cs.collections[0].get_paths()[0] 
v = p.vertices 
x = v[:, 0] 
y = v[:, 1] 

enter image description here

Ma devo solo contorni chiusi e non il contorno aperto che va da sinistra a destra dell'immagine.

Grazie mille per le vostre risposte.

+0

Cosa intendi per "contorno"? Qual è il tuo output previsto? Sii specifico. – barny

+0

Grazie per il tuo commento @barny. Per contorno intendo una linea che va da sinistra a destra e passa attraverso i punti in cui il gradiente di intensità è massimo. E ho bisogno delle coordinate (x, y) di questa linea in una matrice. – razoool

risposta

2

Hai quasi trovato la risposta alla tua domanda. Prima di tutto, c'è una differenza tra il rilevamento del fronte e il rilevamento del contorno . Fondamentalmente, il rilevamento dei bordi dà come risultato (impropriamente) il profilo "aperto" (cioè il bordo) e il rilevamento del contorno in quello che chiamate "contorno chiuso" (cioè contorno).

Il rilevamento del bordo Canny è un algoritmo di rilevamento dei bordi più diffuso. Poiché si desidera rilevare il bordo sotto forma di un array con le coordinate (x, y) che vanno da sinistra a destra dell'immagine, il rilevamento del bordo Canny è una buona idea.

La risposta è edge che non è nel formato desiderato.

import numpy as np 
import matplotlib.pyplot as plt 
import cv2 

img = cv2.imread('test.tif') 
edge = cv2.Canny(img, 100, 200) 

ans = [] 
for y in range(0, edge.shape[0]): 
    for x in range(0, edge.shape[1]): 
     if edge[y, x] != 0: 
      ans = ans + [[x, y]] 
ans = np.array(ans) 

print(ans.shape) 
print(ans[0:10, :]) 

L'array ans (forma uguale a (n, 2)) memorizza il (x, y) -coordinate delle n pixel che compongono il bordo rilevato. Questo è il risultato che stai cercando.

Ecco un'immagine in cui ho tracciati in bianco queste n pixel:

enter image description here

Spero che questo vi aiuterà.

+0

Grazie mille per queste spiegazioni dettagliate baptiste, questo è esattamente quello che non voglio !! – razoool

+0

Prego! Buona programmazione. – Flabetvibes

Problemi correlati