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