IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenCV Discussion :

Double seuillage (seuillage par hystérésis)


Sujet :

OpenCV

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 8
    Points : 6
    Points
    6
    Par défaut Double seuillage (seuillage par hystérésis)
    Bonjour à tous,

    Ma question est simple : à votre connaissance, existe-t-il une méthode opencv permettant d'effectuer un double seuillage (aussi connu sous le doux nom de seuillage par hystérésis) ?
    Je n'ai rien trouvé de tel en parcourant la doc, et j'en suis un peu étonné...

    D'avance, merci !

    Philou

  2. #2
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Salut,

    Je ne me rappelle pas qu'il y ait une fonction avec double seuil. Par contre, il est facile d'en faire une avec CV_THRESH_TRUNC ou CV_THRESH_TOZERO. Ca fait deux opérations de seuillage ce qui n'est peut-être pas le plus rapide mais si le temps de calcul n'est pas un critère trop important, ça devrait passer.

    A+,

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    Salut,

    Arf, j'avais un petit espoir d'avoir mal cherché... Bon, tant pis.
    Ce qui risque de m'embêter si je le fais moi-même, c'est le fait de savoir si un pixel est connecté ou non à un autre pixel accepté par le seuil haut... Mais bon, je vais googler un peu pour trouver un bon algo.

    Merci de ta réponse !

  4. #4
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Salut,

    Je te propose de faire comme suit

    cvThreshold(src, temp, seuilhaut, valeurarbitraire, CV_THRESH_TRUNC );
    cvThreshold(temp, dst, seuilbas, valeurarbitraire, CV_THRESH_TOZERO_INV );
    Après tu parcours ton image pour trouver les pixels dont la valeur est différente de 0 et "seuilhaut" et tu regardes dans leurs voisins, s'il y en a à "seuilhaut", tu mets alors les pixels considérés à "seuilhaut" sinon à 2
    Tu finis en mettant les pixels à "seuilhaut" à 1.

    Bon, c'est un exemple de code, ça doit pouvoir s'optimiser et sous reserve que je ne me plante pas pour le seuillage hystérésis.

    A+

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    Salut, et merci de ta réponse,

    Pour moi, le seuillage hystérésis, c'est :

    1. Accepter tous les pixels au dessus du seuil haut.
    2. Rejeter tous les pixels en dessous du seuil bas.
    3. Un pixel intermédiaire sera toujours rejeté, sauf s'il existe un chemin (constitué de pixels intermédiaires) le reliant à un pixel au dessus du seuil haut.

    Je pense qu'on était d'accord sur la définition, par contre, sous réserve que j'ai bien compris ce que tu as dit, je ne suis pas sûr de la validité de l'implémentation que tu propose : le seuil avec CV_THRESH_TRUNC permet de trouver les pixels au dessus du seuil haut (situation 1), en revanche, si on applique derrière CV_THRESH_TOZERO_INV, tous les pixels au dessus du seuil bas vont être mis à zéro, ce qui inclut les pixels hauts, et les pixels intermédiaires...

    Mais bon, ce n'est qu'un détail, car la difficulté de l'affaire réside dans le fait, pour un pixel intermédiaire donné, de savoir si oui ou non il est relié à un pixel haut. Une manière que je vois de faire ça (qui me paraît monstrueusement lente, c'est un peu pour ça que j'espérais qu'une méthode opencv plus efficace existait), serait de faire, de façon itérative :
    1. Repérer tous les pixels hauts, et les mettre au statut "accepté".
    2. Regarder tous les voisins des pixels acceptés, s'ils sont intermédiaire, les mettre au statut "accepté" (sinon, les mettre au statut "rejeté").
    3. Itérer l'étape 2, jusqu'à ce qu'elle ne change plus rien.
    4. S'il reste des pixels non traités, les mettre au statut rejeté.

    Comme ça risque d'être très lent pour mes images 1024 x 768, je vais essayer de trouver plus efficace quelque part... Si je trouve, je viendrai en faire part.

    @+ mister Zoldik, et merci de ton aide ;-)

  6. #6
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Salut,

    Oups... ce n'était pas CV_THRESH_TOZERO_INV mais CV_THRESH_TOZERO (cf. mon 1er post)... Là, tu mets les pixels sous le seuil à 0 et tu copies les pixels si au dessus du seuil. Ainsi tu as tes "acceptés" et "rejetés" par rapport aux seuils. Pour le traitement des "intermédiaires", je n'ai pas de solution miracle à part itérer... à voir du côté de la morpho math genre dilatation géodésique (limitation de la progression aux "intermédiaires"), tu dois pouvoir trouver des algorithmes optimisés.

    A+

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    Bonjour à tous,

    Après quelques infructueuses investigations visant à trouver une implémentation simple et efficace du double seuillage, j'ai fait avec les moyens du bord (outils OpenCV). C'est très lent, mais comme c'est mieux que rien, je poste pour l'hypothétique cas où ça servirait à quelqu'un :

    Etape 1 : à partir de l'image originale I_originale, seuiller deux fois : une première fois avec un seuil large, qui conduit à I_large, et une deuxième fois avec un seuil étroit, qui conduit à I_étroit.
    Etape 2 : Détecter les composantes connexes sur I_large et sur I_etroit. Pour cela, utiliser les méthodes OpenCV correspondantes (notamment cvFindContours).
    Etape 3 : Parcourir toutes les composantes connexes de I_large. Pour la composante courante, calculer le recouvrement avec les composantes de I_étroit. Si ce recouvrement est nul, la composante courante de I_large doit être filtrée. Si le recouvrement est non nul, la composante courante peut-être conservée sur l'image seuillée finale.

    On retrouve bien sur l'image seuillée finale ce qui caractérise le résultat d'un double seuillage : toutes les zones de l'image I_originale supérieure au seuil étroit sont sur l'image finale (car elles étaient à la fois sur I_étroit, et sur I_large), et seules les zones de l'image I_originale qui étaient connexes à ces zones sont conservées.

    Cette méthode est très lente, (N², voire peut-être plus, je ne sais pas comment fonctionne cvFindContours), mais bon, c'est mieux que rien, et ça évite d'utiliser une librairie externe.

    N'hésitez pas à poster si vous trouvez une façon plus efficace de l'implémenter.

    @+

  8. #8
    Membre habitué
    Inscrit en
    Juin 2003
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Juin 2003
    Messages : 223
    Points : 145
    Points
    145
    Par défaut
    Si c'est pour utiliser avec des edges il y a le filtre canny qui fait exactement ca!
    void cvCanny( const CvArr* image, CvArr* edges, double threshold1,
    double threshold2, int aperture_size=3 );

    Sinon utiliser les contours c'est de la folie niveau processing, il faut plutot utiliser un mask 5x5 qui regarde les valeurs des voisins pour eliminer ou non les valeur entre threshold 1 et threshold 2. Si ce pixel n'est pas eliminé ils passent donc a la valeur de threshold 2.

    C'est un algo qui va te donner un resultat un peu moins precis que celui que tu propose (certains pixels en haut a gauche peuvent etre elimés), mais cet algo est 30x plus rapide et donne quasi le meme resultat.
    Bonne chance

Discussions similaires

  1. Double Numérotation factures par client
    Par Hbenne01 dans le forum Access
    Réponses: 1
    Dernier message: 26/10/2009, 23h09
  2. tester si un double se termine par .00000
    Par gletare dans le forum C++
    Réponses: 11
    Dernier message: 21/12/2006, 13h26
  3. Seuillage par hysteresis
    Par Flo. dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 18/07/2006, 10h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo