Salut, je suis Ramu. Nous allons implémenter la binarisation d'Otsu (méthode d'analyse de discrimination), qui est une méthode pour déterminer automatiquement le seuil utilisé pour la binarisation.
La binarisation est le processus de conversion d'une image en une image monochrome avec seulement deux couleurs, noir et blanc. Après avoir déterminé le seuil, remplacez les valeurs de pixels inférieures au seuil par du blanc et les pixels par des valeurs de pixels supérieures au seuil par du noir. Jusqu'à présent, je l'ai expliqué dans la binarisation précédente. Cette fois, nous traiterons de la méthode de détermination automatique de ce seuil.
Dans la binarisation d'Otsu, la classe est divisée en deux selon le seuil. Le seuil lorsque le degré de séparation est maximum dans ces deux classes est le seuil lors de la binarisation. Les paramètres nécessaires pour calculer le degré de séparation peuvent être calculés par la formule suivante.
Séparation: $ X = \ dfrac {\ sigma _ {b} ^ {2}} {\ sigma _ {w} ^ {2}} $
Distribution en classe: $ \ sigma _ {b} ^ {2} = \ dfrac {\ omega _ {0} \ omega _ {1}} {(\ omega _ {0} + \ omega _ {1}) ^ 2 } (M _ {0} + M _ {1}) ^ 2 $
Distribution interclasse: $ \ sigma _ {b} ^ {2} = \ omega _ {0} \ sigma _ {0} ^ {2} + \ omega _ {1} \ sigma _ {1} ^ {2} $
Nombre de pixels appartenant à la classe 0,1: $ \ omega _0, \ omega _1 $
Distribution des valeurs de pixels appartenant aux classes 0,1: $ \ sigma _0, \ sigma _1 $
Moyenne des valeurs de pixel appartenant à la classe 0,1: $ M_0, M_1 $
Valeur moyenne des pixels de l'image entière: M $
Somme des valeurs de pixel appartenant à la classe 0,1: $ P_0, P_1 $
En résumé, lorsque le seuil est compris entre 0 et 255, le degré de séparation doit être calculé 256 fois pour trouver le seuil qui maximise le degré de séparation.
otsuBinarization.py
import numpy as np
import cv2
import matplotlib.pyplot as plt
# from statistics import variance
import statistics as st
plt.gray()
def otsuBinarization(img):
  #Copie d'image
  dst = img.copy()
  #Échelle de gris
  gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
  w,h = gray.shape
  Max = 0
  #Valeur de pixel moyenne de l'image entière
  M = np.mean(gray)
  #S'applique aux 256 valeurs de seuil
  for th in range(256):
    #Classification
    g0,g1 = gray[gray<th],gray[gray>=th]
    #Nombre de pixels
    w0,w1 = len(g0),len(g1)
    #Distribution de la valeur des pixels
    s0_2,s1_2 = g0.var(),g1.var()
    #Valeur moyenne des pixels
    m0,m1 = g0.mean(),g1.mean()
    #Valeur totale des pixels
    p0,p1 = g0.sum(),g1.sum()
    #Distribution en classe
    sw_2 = w0*s0_2 + w1*s1_2
    #Distribution interclasse
    sb_2 = ((w0*w1) / ((w0+w1)*(w0+w1))) * ((m0-m1)*(m0-m1))
    #Séparation
    if (sb_2 != 0):
      X = sb_2 / sw_2
    else:
      X = 0
    if (Max < X):
      Max = X
      t = th
  #Binarisation
  idx = np.where(gray < t)
  gray[idx] = 0
  idx = np.where(gray >= t)
  gray[idx] = 255
  return gray
#Lecture d'image
img = cv2.imread('image.jpg')
#Binarisation d'Otsu
mono = otsuBinarization(img)
#Enregistrer l'image
cv2.imwrite('result.jpg', mono)
#Affichage de l'image
plt.imshow(mono)
plt.show()
 
 
Le côté gauche de l'image est l'image d'entrée, le centre de l'image est l'image de sortie lorsque le seuil est réglé manuellement sur 128, et le côté droit de l'image est l'image de sortie cette fois. Même si le seuil est automatiquement déterminé et binarisé, l'image est sortie sans trop d'inconfort. En passant, ma mise en œuvre n'utilise pas la valeur de pixel moyenne M pour toute l'image.
Si vous avez des questions, n'hésitez pas à nous contacter. [Github] d'imori_imori (https://github.com/yoyoyo-yo/Gasyori100knock/blob/master/Question_01_10/answers_py/answer_2.py) a la réponse officielle, veuillez donc vérifier cela également. .. De plus, puisque python est un débutant, veuillez surveiller et commenter toute erreur.
Recommended Posts