Code source de mlstatpy.image.detection_segment.detection_nfa

# -*- coding: utf-8 -*-
"""
Ce module determine si un segment est significatif, c'est à dire
si le nombre de fausses alarmes n'est pas trop élevé.


:githublink:`%|py|7`
"""
from .geometrie import Segment


[docs]class SegmentNFA(Segment): """ Un segment + un nombre de fausses alarmes, servira a memoriser les segments significatifs. :githublink:`%|py|14` """ # voir la classe Point pour __slots__ __slots__ = ("nfa",)
[docs] def __init__(self, p1, p2, nfa): """ segment + nombre de fausses alarmes :githublink:`%|py|20` """ Segment.__init__(self, p1, p2) self.nfa = nfa
[docs] def __str__(self): """ permet d'afficher ce segment :githublink:`%|py|25` """ s = Segment.__str__(self) s += " nfa = " + str(self.nfa) return s
[docs] def __lt__(self, o): return self.nfa < o.nfa
[docs]class InformationPoint: """ Pour retenir toutes les informations relatives a un segment, une position (pos), la norme du gradient (norme), une information permettant de savoir si le gradient est proche du vecteur normal au segment (aligne) :githublink:`%|py|40` """ # voir la classe Point pour __slots__ __slots__ = "pos", "aligne", "norme"
[docs] def __init__(self, pos, aligne, norme): """ constructeur, initialisation :githublink:`%|py|46` """ self.pos, self.aligne, self.norme = pos, aligne, norme
[docs] def __str__(self): """ permet d'afficher cette classe :githublink:`%|py|50` """ s = "aligne " + str(self.aligne) s += " pix " + str(self.pos) s += " gnor " + str(self.norme) return s
[docs]class LigneGradient: """ Stocke toutes les informations relatives à un segment de l'image reliant deux points du contour, reçoit les informations de la methode :meth:`decoupe_gradient <mlstatpy.image.detection_segment.detection_segment_bord.SegmentBord_Commun.decoupe_gradient>`. A partir de là, un segment significatif a deux extrémités dont le gradient est dans le bon sens, on parcourt donc tous les couples d'extrémités possibles, d'abord la première (méthode :meth:`premier_chemin <mlstatpy.image.detection_segment.detection_nfa.LigneGradient.premier_chemin>`), puis les suivant (méthode :meth:`next_chemin <mlstatpy.image.detection_segment.detection_nfa.LigneGradient.next_chemin>`) jusqu'au dernier couple. :githublink:`%|py|69` """
[docs] def __init__(self, info_ligne, seuil_norme, seuil_nfa): """ constructeur :githublink:`%|py|72` """ self.info_ligne = info_ligne # informations self.nb = len(info_ligne) # nombre de pixels self.seuil_norme = seuil_norme self.seuil_nfa = seuil_nfa
[docs] def __len__(self): """ Retourne le nombre de pixels dans le segment, peut etre different de la liste ``self.info_ligne``, ``self.nb`` est déterminé par :meth:`decoupe_gradient <mlstatpy.image.detection_segment.detection_segment_bord.SegmentBord_Commun.decoupe_gradient>`. :githublink:`%|py|83` """ return self.nb
[docs] def has_aligned_point(self): """ Dit s'il existe des points alignés sur le segment. :githublink:`%|py|89` """ return any(filter(lambda _: _.aligne, self.info_ligne))
[docs] def extremite(self): """ Comptabilise les indices des extremites possibles, les pixels choisis ont un gradient de la bonne orientation. :githublink:`%|py|96` """ ext = [] if self.has_aligned_point(): for i in range(0, len(self)): if self.info_ligne[i].aligne and \ (i == 0 or i == len(self) - 1 or not self.info_ligne[i - 1].aligne or not self.info_ligne[i + 1].aligne): ext.append(i) return ext
[docs] def premier_chemin(self, ext): """ Retourne la premiere d'extremite possible. :githublink:`%|py|107` """ return (0, 1)
[docs] def next_chemin(self, ext, ij): """ Retourne le couple suivant d'extrémités possibles, None, dans le cas contraire. :githublink:`%|py|112` """ if ij[1] < len(ext) - 1: return (ij[0], ij[1] + 1) elif ij[0] < len(ext) - 2: return (ij[0] + 1, ij[0] + 2) else: return None
[docs] def calcule_NFA(self, ext, ij, binomiale, nb_seg): """ ``ext[ij[0]]``: premier indice du segment, ``ext[ij[1]]``: dernier indice du segment, calcule le nombre de NFA de ce segment (nombre de fausses alarmes). :githublink:`%|py|126` """ ln = 0 n = 0 for i in range(ext[ij[0]], ext[ij[1]] + 1): if self.info_ligne[i].norme < self.seuil_norme: # on evite les petits gradients continue ln += 1 if self.info_ligne[i].aligne: # on calcule un gradient dans le bon sens n += 1 # on determine ensuite la probabilite d'un tel agencement # de fausses alarmes nfa = binomiale[(ln, n)] nfa *= nb_seg return nfa
[docs] def segments_significatifs(self, binomiale, nb_seg): """ Comptabilise le nombre de segments significatifs sur une ligne et les mémorise. :githublink:`%|py|148` """ # on recense les extrémités possibles ext = self.extremite() if len(ext) < 2: # s'il n'y a qu'une extrémité possible, # ce n'est pas suffisant pour faire un segment return [] # premier couple d'extrémités ij = self.premier_chemin(ext) res = [] # pour memoriser les segments significatifs while ij is not None: # tant qu'il reste un couple d'extremite # probabilite de fausses alarmes pour ce segment nfa = self.calcule_NFA(ext, ij, binomiale, nb_seg) if nfa < self.seuil_nfa: # si cette proba est suffisamment faible, # l'agencement est un cas rare (non aleatoire), # il est significatif seg = SegmentNFA(self.info_ligne[ext[ij[0]]].pos, self.info_ligne[ext[ij[1]]].pos, nfa) # on l'ajoute a la liste res.append(seg) # on passe au segment suivant ij = self.next_chemin(ext, ij) # fin return res