Problèmes et contre-mesures pour le débordement de la binarisation d'Otsu en Python

introduction

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.

code

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

problème

J'ai reçu un avertissement de débordement lorsque j'ai polarisé les photos ci-dessous.

img5.jpg

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.

Cause

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).

Contre-mesures

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. otsu.jpg

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.

en conclusion

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.

URL de référence

[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

Problèmes et contre-mesures pour le débordement de la binarisation d'Otsu en Python
Problèmes et solutions à la demande de MySQL db dans Python 3
Combiner des problèmes en Python
Janken Poi en Python pour les débutants (réponses et explications)
Problèmes et contre-mesures dans le développement de jeux d'applications pour smartphone Partie 1
Préférences pour jouer à Wave dans Python PyAudio et PortAudio
Recherche récursive de fichiers et de répertoires en Python et sortie
Problèmes et contre-mesures dans le développement de jeux d'applications pour smartphone Partie 2
Techniques de tri en Python
Pile et file d'attente en Python
Unittest et CI en Python
Résoudre les problèmes d'optimisation avec Python
À propos de "for _ in range ():" de python
Liste des informations sur les arguments de méthode pour les classes et les modules en Python
Conseils pour coder courts et faciles à lire en Python
Astuces utiles liées à la liste et aux instructions en Python
[Astuces] Problèmes et solutions dans le développement de python + kivy
Rechercher les fuites de mémoire dans Python
Paquets qui gèrent le MIDI avec Python midi et pretty_midi
Différence entre list () et [] en Python
Rechercher des commandes externes avec python
Différence entre == et est en python
Afficher les photos en Python et html
Algorithme de tri et implémentation en Python
Manipuler des fichiers et des dossiers en Python
À propos de Python et Cython dtype
Affectations et modifications des objets Python
Vérifiez et déplacez le répertoire en Python
Chiffrement avec Python: IND-CCA2 et RSA-OAEP
Hashing de données en R et Python
Synthèse de fonctions et application en Python
Exporter et exporter des fichiers en Python
Exécutez unittest en Python (pour les débutants)
Inverser le pseudonyme plat et le katakana en Python2.7
Lire et écrire du texte en Python
[GUI en Python] Menu PyQt5 et barre d'outils-
Créer et lire des paquets de messages en Python
python> array> Déterminer le nombre et initialiser> mylist = [idx pour idx dans la plage (10)] / mylist = [0 pour idx dans la plage (10)] >> mylist = [0] * 10
Construisez un serveur léger en Python et écoutez les extensions HTTP de Scratch 2
Chevauchement d'expressions régulières en Python et Java
Différence d'authenticité entre Python et JavaScript
Notes utilisant cChardet et python3-chardet dans Python 3.3.1.
Différences entre Ruby et Python dans la portée
Modulation et démodulation AM avec Python Partie 2
différence entre les instructions (instructions) et les expressions (expressions) en Python
Valeurs authentiques et vecteurs propres: Algèbre linéaire en Python <7>
Note de nfc.ContactlessFrontend () de nfcpy de python
Inject est recommandé pour DDD en Python
Graphique à lignes pliées et ligne d'échelle en python
Implémenter le filtre FIR en langage Python et C
Différences entre la syntaxe Python et Java
Vérifier et recevoir le port série en Python (vérification du port)
Conseils pour gérer les binaires en Python
Rechercher et lire des vidéos YouTube avec Python
Résumé de diverses instructions for en Python
Tapez les annotations pour Python2 dans les fichiers stub!
Différence entre @classmethod et @staticmethod en Python
Différence entre append et + = dans la liste Python