2017-10-03 2 views
1

Je suis en train d'implémenter l'algorithme de Canny en utilisant Tensorflow (ceci est nécessaire pour utiliser les bordures comme une métrique d'évaluation, mais c'est hors sujet). L'une des étapes consiste à calculer la "Suppression non maximale", qui consiste à mettre à zéro l'élément central dans une région 3x3, à moins que deux voisins spécifiques ne soient plus petits. Plus de détails here. Comment puis-je réaliser cette opération en utilisant Tensorflow?Valeur conditionnelle sur le tenseur par rapport aux éléments voisins

Je suis en fait en utilisant Keras, mais la solution tensorflow fonctionnera aussi bien, pour référence, mon code afin ressemble beaucoup à ceci:

def canny(img): 
    '''Canny border detection. The input should be a grayscale image.''' 
    gauss_kernel = np.array([[2, 4, 5, 4, 2], 
          [4, 9, 12, 9, 4], 
          [5, 12, 15, 12, 5], 
          [4, 9, 12, 9, 4], 
          [2, 4, 5, 4, 2]]).reshape(5, 5, 1, 1) 
    gauss_kernel = K.variable(1./159 * gauss_kernel) 

    Gx = K.variable(np.array([[-1., 0. ,1.], 
           [-2., 0., 2.], 
           [-1., 0., 1.]]).reshape(3, 3, 1, 1)) 

    Gy = K.variable(np.array([[-1., -2., -1.], 
           [ 0., 0., 0.], 
           [ 1., 2., 1.]]).reshape(3, 3, 1, 1)) 
    # Smooth image 
    smoothed = K.conv2d(img, gauss_kernel, padding='same') 
    # Derivative in x 
    Dx = K.conv2d(smoothed, Gx, padding='same') 
    # Derivative in y 
    Dy = K.conv2d(smoothed, Gy, padding='same') 
    # Take gradient strength 
    G = K.sqrt(K.square(Dx) + K.square(Dy)) 

    # TODO: Non-maximum Suppression & Hysteresis Thresholding 

    return G 

Répondre

1

Vous pouvez utiliser des filtres convolutifs pour séparer les deux pixels cibles et faire les "concentriques" avec le pixel central.

Pour comparer avec deux pixels cibles, par exemple, nous pourrions utiliser ce filtre, en forme (3, 3, 1, 2) - Un canal d'entrée, deux canaux de sortie. Chaque canal renvoie l'un des pixels cibles.

Le filtre doit avoir 1 sur les pixels cibles. Et le reste sont des zéros:

#taking two diagonal pixels 
filter = np.zeros((3,3,1,2)) 
filter[0,0,0,0] = 1 #first pixel is top/left, passed to the first channel 
filter[2,2,0,1] = 1 #second pixel is bottom/right, passed to the second channel  
    #which ones are really bottom or top, left or right depend on your preprocessing, 
    #but they should be consistent with the rest of your modeling 

filter = K.variable(filter) 

Si vous prenez haut et en bas, à gauche ou à droite, vous pouvez faire des petits filtres. Pas besoin d'être 3x3 (pas de problème non plus), mais seulement 1x3 ou 3x1:

filter1 = np.zeros((1,3,1,2)) #horizontal filter 
filter2 = np.zeros((3,1,1,2)) #vertical filter 

filter1[0,0,0,0] = 1 #left pixel - if filter is 3x3: [1,0,0,0] 
filter1[0,2,0,1] = 1 #right pixel - if filter is 3x3: [1,2,0,1] 
filter1 = K.variable(filter1) 

filter2[0,0,0,0] = 1 #top pixel - if filter is 3x3: [0,1,0,0] 
filter2[2,0,0,1] = 1 #bottom pxl - if filter is 3x3: [2,1,0,1] 
filter2 = K.variable(filter2) 

Ensuite, vous appliquez ces comme circonvolutions. Vous obtiendrez un canal pour un pixel et l'autre canal pour l'autre pixel. Vous pouvez ensuite les comparer comme si elles étaient toutes au même endroit, juste dans des canaux différents:

targetPixels = K.conv2d(originalImages, kernel=filter, padding='same') 

#two channels telling if the center pixel is greater than the pixel in the channel 
isGreater = K.greater(originalImages,targetPixels) 

#merging the two channels, considering they're 0 for false and 1 for true 
isGreater = K.cast(isGreater,K.floatx()) 
isGreater = isGreater[:,:,:,:1] * isGreater[:,:,:,1:] 

#now, the center pixel will remain if isGreater = 1 at that position: 
result = originalImages * isGreater 
+0

J'essayais avec une approche différente, mais cette idée était parfaite! Je vous remercie! –