Cliquez ici pour l'algorithme de Zhang-Suen Comme vous pouvez le voir en lisant le code lié, il est très lent car il est tourné dans une double boucle for. J'ai donc rendu possible le même traitement en utilisant uniquement la fonction universelle de Numpy.
Numpy fournit une fonction appelée fonction universelle qui renvoie un tableau des résultats de l'exécution d'opérations majeures sur chaque élément du tableau. Si vous utilisez cela, vous n'avez pas à passer par le processus d'extraction de chaque élément un par un et de le traiter. C'est rapide. Ce sera environ 20 à 30 fois plus rapide.
-Préparez une image binarisée avec le noir comme vrai et le blanc comme faux. Entourez l'extérieur avec Faux pour 1 pixel. -Pour chaque élément de la partie centrale, générer un tableau qui stocke les éléments du haut, du haut à droite, de la droite, du bas à droite, du bas, du bas à gauche, à gauche, en haut à gauche (Nommez-les respectivement P2 à P9)
#Une méthode pour remplir 1 pixel autour d'une image binaire avec False.
def padding(binary_image):
row, col = np.shape(binary_image)
result = np.zeros((row+2,col+2))
result[1:-1, 1:-1] = binary_image[:, :]
return result
def generate_mask(image):
row, col = np.shape(image)
p2 = np.zeros((row, col)).astype(bool)
p3 = np.zeros((row, col)).astype(bool)
p4 = np.zeros((row, col)).astype(bool)
p5 = np.zeros((row, col)).astype(bool)
p6 = np.zeros((row, col)).astype(bool)
p7 = np.zeros((row, col)).astype(bool)
p8 = np.zeros((row, col)).astype(bool)
p9 = np.zeros((row, col)).astype(bool)
#Vers le haut
p2[1:row-1, 1:col-1] = image[0:row-2, 1:col-1]
#En haut à droite
p3[1:row-1, 1:col-1] = image[0:row-2, 2:col]
#droite
p4[1:row-1, 1:col-1] = image[1:row-1, 2:col]
#En bas à droite
p5[1:row-1, 1:col-1] = image[2:row, 2:col]
#en dessous de
p6[1:row-1, 1:col-1] = image[2:row, 1:col-1]
#En bas à gauche
p7[1:row-1, 1:col-1] = image[2:row, 0:col-2]
#la gauche
p8[1:row-1, 1:col-1] = image[1:row-1, 0:col-2]
#en haut à gauche
p9[1:row-1, 1:col-1] = image[0:row-2, 0:col-2]
return (p2, p3, p4, p5, p6, p7, p8, p9)
** noir ** Le tableau d'origine est tel qu'il est.
condition1 = np.copy(image)
** Lorsque les pixels autour du pixel cible sont disposés dans l'ordre, il y a exactement un endroit où blanc → noir ** Cette condition signifie que lorsque vous regardez une adresse dans l'ordre P2, P3, P4, P5, P6, P7, P8, P9, P2, il y a exactement deux changements Vrai Faux.
#C'est une méthode pour juger s'il y a exactement un blanc → noir lorsque les pixels environnants sont disposés dans l'ordre.
def is_once_change(p_tuple):
number_change = np.zeros_like(p_tuple[0])
# P2~P9,Pour P2, comptez le nombre de vrais lorsque la somme logique exclusive des éléments adjacents est prise.
for i in range(len(p_tuple) - 1):
number_change = np.add(number_change, np.logical_xor(p_tuple[i], p_tuple[i+1]).astype(int))
number_change = np.add(number_change, np.logical_xor(p_tuple[7], p_tuple[0]).astype(int))
array_two = np.ones_like(p_tuple[0]) * 2
return np.equal(number_change, array_two)
condition2 = is_once_change(p_tuple)
** 2 ou plus et 6 ou moins de noir autour du pixel cible ** Cette condition signifie que le nombre de vrais de P2, P3, P4, P5, P6, P7, P8, P9 est de 2 ou plus et de 6 ou moins pour une certaine adresse.
#Cette méthode compte le nombre de pixels noirs autour d'elle et détermine si elle est de 2 ou plus et de 6 ou moins.
def is_black_pixels_appropriate(p_tuple):
number_of_black_pxels = np.zeros_like(p_tuple[0])
array_two = np.ones_like(p_tuple[0]) * 2
array_six = np.ones_like(p_tuple[0]) * 6
for p in p_tuple:
number_of_black_pxels = np.add(number_of_black_pxels, p.astype(int))
greater_two = np.greater_equal(number_of_black_pxels, array_two)
less_six = np.less_equal(number_of_black_pxels, array_six)
return np.logical_and(greater_two, less_six)
condition3 = is_black_pixels_appropriate(p_tuple)
** Au moins un des pixels en haut, en bas, à gauche et à droite du pixel cible est blanc ** Vérifiez qu'au moins une des valeurs P2, P4, P6, P8 correspondantes pour le pixel cible est False.
#Une méthode qui renvoie le produit logique pour tous les arguments donnés.
def multi_logical_and(*args):
result = np.copy(args[0])
for arg in args:
result = np.logical_and(result, arg)
return result
condition4 = np.logical_not(multi_logical_and(p_tuple[0], p_tuple[2], p_tuple[4]))
Je vais mettre le code de l'ensemble du processus.
ZhangSuen.py
import numpy as np
#Une méthode qui renvoie le produit logique pour tous les arguments donnés.
def multi_logical_and(*args):
result = np.copy(args[0])
for arg in args:
result = np.logical_and(result, arg)
return result
#Une méthode pour remplir 1 pixel autour d'une image binaire avec False.
def padding(binary_image):
row, col = np.shape(binary_image)
result = np.zeros((row+2,col+2))
result[1:-1, 1:-1] = binary_image[:, :]
return result
#Le contraire du rembourrage
def unpadding(image):
return image[1:-1, 1:-1]
#Renvoie un tableau contenant des informations sur les pixels autour de ce pixel.
def generate_mask(image):
row, col = np.shape(image)
p2 = np.zeros((row, col)).astype(bool)
p3 = np.zeros((row, col)).astype(bool)
p4 = np.zeros((row, col)).astype(bool)
p5 = np.zeros((row, col)).astype(bool)
p6 = np.zeros((row, col)).astype(bool)
p7 = np.zeros((row, col)).astype(bool)
p8 = np.zeros((row, col)).astype(bool)
p9 = np.zeros((row, col)).astype(bool)
#Vers le haut
p2[1:row-1, 1:col-1] = image[0:row-2, 1:col-1]
#En haut à droite
p3[1:row-1, 1:col-1] = image[0:row-2, 2:col]
#droite
p4[1:row-1, 1:col-1] = image[1:row-1, 2:col]
#En bas à droite
p5[1:row-1, 1:col-1] = image[2:row, 2:col]
#en dessous de
p6[1:row-1, 1:col-1] = image[2:row, 1:col-1]
#En bas à gauche
p7[1:row-1, 1:col-1] = image[2:row, 0:col-2]
#la gauche
p8[1:row-1, 1:col-1] = image[1:row-1, 0:col-2]
#en haut à gauche
p9[1:row-1, 1:col-1] = image[0:row-2, 0:col-2]
return (p2, p3, p4, p5, p6, p7, p8, p9)
#C'est une méthode pour juger s'il y a exactement un blanc → noir lorsque les pixels environnants sont disposés dans l'ordre.
def is_once_change(p_tuple):
number_change = np.zeros_like(p_tuple[0])
# P2~P9,Pour P2, comptez le nombre de vrais lorsque la somme logique exclusive des éléments adjacents est prise.
for i in range(len(p_tuple) - 1):
number_change = np.add(number_change, np.logical_xor(p_tuple[i], p_tuple[i+1]).astype(int))
number_change = np.add(number_change, np.logical_xor(p_tuple[7], p_tuple[0]).astype(int))
array_two = np.ones_like(p_tuple[0]) * 2
return np.equal(number_change, array_two)
#Cette méthode compte le nombre de pixels noirs autour d'elle et détermine si elle est de 2 ou plus et de 6 ou moins.
def is_black_pixels_appropriate(p_tuple):
number_of_black_pxels = np.zeros_like(p_tuple[0])
array_two = np.ones_like(p_tuple[0]) * 2
array_six = np.ones_like(p_tuple[0]) * 6
for p in p_tuple:
number_of_black_pxels = np.add(number_of_black_pxels, p.astype(int))
greater_two = np.greater_equal(number_of_black_pxels, array_two)
less_six = np.less_equal(number_of_black_pxels, array_six)
return np.logical_and(greater_two, less_six)
def step1(image, p_tuple):
#Condition 1
condition1 = np.copy(image)
#Condition 2
condition2 = is_once_change(p_tuple)
#Condition 3
condition3 = is_black_pixels_appropriate(p_tuple)
#Condition 4
condition4 = np.logical_not(multi_logical_and(p_tuple[0], p_tuple[2], p_tuple[4]))
#Condition 5
condition5 = np.logical_not(multi_logical_and(p_tuple[2], p_tuple[4], p_tuple[6]))
return np.logical_xor(multi_logical_and(condition1, condition2, condition3, condition4, condition5), image)
def step2(image, p_tuple):
#Condition 1
condition1 = np.copy(image)
#Condition 2
condition2 = is_once_change(p_tuple)
#Condition 3
condition3 = is_black_pixels_appropriate(p_tuple)
#Condition 4
condition4 = np.logical_not(np.logical_and(p_tuple[0], np.logical_and(p_tuple[2], p_tuple[6])))
#Condition 5
condition5 = np.logical_not(np.logical_and(p_tuple[0], np.logical_and(p_tuple[4], p_tuple[6])))
return np.logical_xor(multi_logical_and(condition1, condition2, condition3, condition4, condition5), image)
#Cette méthode renvoie une image binarisée sous forme de ligne fine.
def ZhangSuen(image):
image = padding(image)
while True:
old_image = np.copy(image)
p_tuple = generate_mask(image)
image = step1(image, p_tuple)
p_tuple = generate_mask(image)
image = step2(image, p_tuple)
if (np.array_equal(old_image, image)):
break
return unpadding(image)
Recommended Posts