La binarisation d'Otsu est un algorithme qui détermine automatiquement le seuil de binarisation d'une image. Il a déjà été implémenté dans des bibliothèques telles qu'OpenCV, mais j'ai trouvé une implémentation en Python, alors je l'ai touché. Il y a un problème avec le titre, mais je pense que c'est probablement dû à mon mauvais environnement d'exécution.
Le code lui-même n'a pas été écrit par moi, mais tiré d'un blog [1] dessiné par d'autres. est.
ots.py
#Binarisation d'Otsu (l'argument gris est une image en échelle de gris)
def threshold_otsu(gray, min_value=0, max_value=255):
#Calcul de l'histogramme
hist = [np.sum(gray == i) for i in range(256)]
s_max = (0,-10)
for th in range(256):
#Calculez le nombre de pixels en classe 1 et classe 2
n1 = sum(hist[:th])
n2 = sum(hist[th:])
#Calculer la moyenne des valeurs de pixel de classe 1 et de classe 2
if n1 == 0 : mu1 = 0
else : mu1 = sum([i * hist[i] for i in range(0,th)]) / n1
if n2 == 0 : mu2 = 0
else : mu2 = sum([i * hist[i] for i in range(th, 256)]) / n2
#Calculer la molécule de dispersion interclasse
s = n1 * n2 * (mu1 - mu2) ** 2
#Enregistrer la molécule de dispersion interclasse et le seuil lorsque la molécule de dispersion interclasse est maximale
if s > s_max[1]:
s_max = (th, s)
#Obtenez le seuil lorsque la distribution interclasse est maximale
t = s_max[0]
#Traitement de binarisation avec le seuil calculé
gray[gray < t] = min_value
gray[gray >= t] = max_value
return gray
J'ai reçu un avertissement de débordement lorsque j'ai polarisé les photos ci-dessous.
RuntimeWarning: overflow encountered in long_scalars
s = n1 * n2 * ((mu1 - mu2) ** 2)
A ce moment, le seuil devient 137, ce qui est loin du 78 obtenu lorsque Otsu est binarisé avec OpenCV.
L'exécution de type (n1) et type (n2) pour n1 et n2 a abouti à \ <class'numpy.int32 '>. Par conséquent, on considère que la cause est que le résultat du calcul dépasse la plage de type int32 (-2147483648 à 2147483647) [[2]](https://jakevdp.github.io/PythonDataScienceHandbook/02.01- Understanding-data-types.html).
J'ai pensé à deux mesures. La première consiste à faire flotter les types de n1 et n2. En ajoutant une ligne comme indiqué ci-dessous, le type d'hist change et, par conséquent, les types de n1 et n2 changent également.
python
#Calcul de l'histogramme
hist = [np.sum(gray == i) for i in range(256)]
hist = np.array(hist, dtype=np.float64)
La seconde consiste à utiliser le journal. Puisque la taille relative de s est plus importante que la valeur elle-même, le journal est pris des deux côtés de s et le côté droit est décomposé (le résultat de la prise du journal est de type float). Sauf si le contenu est 1 et moins, l'ordre ne change pas même si vous prenez le journal.
python
import math
...
#Calculer la molécule de dispersion interclasse
#s = float(n1 * n2 * ((mu1 - mu2) ** 2))
if n1 == 0 or n2 == 0:
continue
if mu2 >= mu1:
s = math.log(n1)+math.log(n2)+2*math.log(mu2-mu1)
elif mu1 < mu2:
s = math.log(n1)+math.log(n2)+2*math.log(mu1-mu2)
...
J'ai pu le résoudre en toute sécurité. L'image ci-dessous est le résultat de l'exécution du programme.
De plus, la valeur seuil était de 79 (OpenCV est en dessous du seuil, et ce programme est binarisé en dessous du seuil), confirmant que la programmation fonctionne normalement. Enfin, dans le premier et le second, le premier est extrêmement plus facile, mais comme il semblait intéressant, j'ai également posté le second.
On pense que la cause du problème est que le moule est déformé. C'était une bonne étude car je souffre souvent de taper lors du traitement d'image avec Python.
Merci d'avoir regardé jusqu'à la fin. Si vous avez des commentaires ou des suggestions, n'hésitez pas à nous contacter.
[1]https://algorithm.joho.info/programming/python/opencv-otsu-thresholding-py/ [2]https://jakevdp.github.io/PythonDataScienceHandbook/02.01-understanding-data-types.html
Recommended Posts