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 :

Haartraining ou corrélation de phase (FFTW)


Sujet :

OpenCV

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut Haartraining ou corrélation de phase (FFTW)
    Bonjour à vous tous,

    Pour mon stage, je dois concevoir un programme qui détecte, sur des disques, des défauts, dont des bulles ( de taille, de forme [ parfois un peu elliptique ], d'intensité différentes ). Voilà quelques détails supplémentaires:
    Je travaille sur Visual Studio 2008 C++ avec OpenCV 2.4. Mes images sont en .tif.
    Les photos sont en niveau de gris.
    Les photos sont prises par des caméras différentes: donc l'éclairage, l'inclinaison et l'usure différent.

    J'ai déjà procédé à un découpage de l'image pour ne travailler que sur la région d'intérêt, le disque.
    [ Avant tout, je ne vous demande pas des pavés, mais un lien ou une piste de travail peut me suffire dans un premier temps ]

    Arrive maintenant la détection de ces bulles. On pourrait penser à une détection de contour et les compter grâce à findContours et à son deuxième argument ( qui est un vecteur dont on peut savoir la taille ). Cependant, le réglage du seuil des filtres à utiliser ( Sobel, Canny,... ) est associé à une caméra, qui, de plus, peut être changé.

    Solution 1: Le seuil doit donc dépendre des caractéristiques de l'image. Mais comment le choisir?

    Solution 2: utiliser le haartraining. J'ai déjà regardé beaucoup de sites ( j'applaudis celui qui m'en indique un que je ne connais pas ) et c'est alors que je me pose pleins de questions.
    1) Je pense pouvoir recueillir 100 photos cadrées serrées de mes défauts. Pourrais-je obtenir un temps de détection raisonnable ( <5min par photo )?
    2) Pourquoi un fichier XML est-il nécessaire? ( j'ai essayé de regarder ce qu'est le XML, mais je n'en vois pas l'intérêt dans mon cas )
    3) Comment est lu ce fichier XML par la fonction LoadCascadeClassifier?
    4) Avez-vous un site qui présente simplement un moyen pour obtenir un tel fichier? Je suis sur Windows et Visual Studio 2008 C++ ( Là, je suis à genoux devant vous ).

    Solution 3: utiliser la corrélation de phase. Et là, c'est fftw que je ne parviens pas à compiler la librairie sur VS2008: le compilateur cherche des .c dans un dossier codelets, qui n'existe pas.
    A ce propos, j'ai téléchargé ces trois fichiers:
    - fftw-3.2.2-vs2008.zip
    - fftw-3.3.2.tar.gz
    - fftw-3.3.2-dll32.zip
    et j'ai créé un dossier FFTW où j'ai mis tout ça.

    D'une manière générale, je suis perdu: je ne sais pas quelle piste je dois privilégier.

    Merci d'avance,
    N'hésitez pas pour les critiques!

  2. #2
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    Tu pourrais nous montrer un exemple de photo de disque ?

    Peut être une piste : HoughCircle.
    Comme tu connais la taille approximatif (min / max) de tes bulles, tu pourras affiner avec plus de précision les paramètres de HoughCircle.

    Sinon l'idée ce sera de traiter un peu ton image avant, appliquer un gradient (Sobel, Canny) ça pourrait quand même être utile pour améliorer HoughCircle (qui ne détectera plus le bruit).

    De la même façon que findContour, HoughCircle te fournira un vecteur, la taille correspond au nombre de bulle (si tes paramêtres sont bons).

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    Avant tout, merci pour ta rapidité.

    Voilà un exemple d'image à traiter.

    J'avais déjà pensé à HoughCircles. Cependant, je ne maîtrise pas du tout cette fonction: je ne comprends pas quel est l'influence des variables:
    minRadius – Minimum circle radius.
    maxRadius – Maximum circle radius.

    http://docs.opencv.org/modules/imgpr...int maxRadius)

    En effet, les résultats n'étaient vraiment pas bons: des cercles dont les rayons dépassaient les deux limites étaient tout de même tracés.
    On peut voir dans l'exemple proposé dans la doc:
    "HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray->rows/4, 200, 100 );" Donc,
    minRadius: 200
    maxRadius: 100 o_O
    Pour moi, mettre ces valeurs-ci ne devrait aboutir à rien, mais cela fonctionne.
    J'ai essayé, pour ExempleDeBulle.png ( le rayon est à peu près de 350 pixels ), d'utiliser HoughCircles avec
    minRadius: 400 ( resp 300 )
    maxRadius: 300 ( resp 400 )
    et aucun cercle n'est détecté.

    Si vous pouvez m'expliquer comment bien utiliser cette fonction, je suis preneur.

    Pour détecter le disque, j'ai fait un seuillage grâce à la moyenne des pixels et j'ai appliqué ensuite un filtre de Canny. Si je mets alors minRadius = 200 et maxRadius = 100, je trouve deux cercles un à 370 et un autre à 120. Certes, je peux garder uniquement le plus grand et j'obtiendrais alors ma région d'intérêt.

    Mais, c'est pour les bulles que cela se corse. Sobel et/ou Canny me permettent bien de détecter, dans un premier temps, la grosse bulle ( qui est plutôt elliptique ), mais se pose alors le problème des seuils. Il me faudrait un moyen pour que ces seuils se ré-ajustent tout seul selon certains critères, car les photos peuvent voir leur intensité changer par exemple. J'avais laissé tomber ces techniques, car il est souvent répété qu'il n'y a pas de méthodes miracles pour trouver le bon seuil.
    Mais, je veux bien croire que non.
    Images attachées Images attachées  

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    sinon tu ne pourrais pas avoir une approche colorimétrique en étudiant les zones de couleurs similaire; on voit bien sur ton image que les bulles n'ont pas la même couleur que le fond (en imaginant que le disque est correctement isolé)
    Si tu constate que les bulles ont une couleur plus clair que le disque (quelque soit la luminosité), tu pourrais déterminé la valeur moyenne, la valeur max (clair) et la valeur min (foncé).
    Avec un certain taux d'acceptation, tu ne garde que les pixels ayant une intensité supérieur à taux * valeur max (ex : 0.8 pour 80%); tu obtient une image binaire.
    Tu auras surement du bruit que tu peux éliminer en faisant des ouvertures (érosion puis dilatation).
    Ensuite je pense qu'il sera intéressant pour toi de déterminer si la tache détecté est vraiment une bulle, pour cela tu peux déterminer un nombre minimum de pixel en dessous duquel ce ne peut pas être une bulle car trop petite (c'est du bruit).

    Après je pense quand même qu'un Sobel est la meilleure approche : ton pseudo dégradé qui forme ton fond va disparaitre et tu vas voir apparaitre uniquement les frontières entre tes bulles et le fond.
    Même si le niveau lumineux change, il changera sur l'ensemble de ton image : ça n'affecte pas Sobel.
    Perso, je n'utilise pas le Sobel d'openCV, je préfère le recoder pour agir directement sur mes paramètres. (c'est pas trop compliqué, si t'as besoin du code je peux te l'envoyer par mp).

    Voici un exemple de HoughCircle extrait d'un de mes projets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    cv::HoughCircles(imgGS, circles, CV_HOUGH_GRADIENT,
    		2,
    		150,
    		300,
    		80,
    		20, 80);
    avec std::vector<cv::Vec3f> circles;
    et imgGS un cv::Mat (CV_8UC1) de grande taille (5000*3000).
    Je l'utilise pour détecter des mires circulaires dans une photo.


    cv::HoughCircles(imgGS, circles, CV_HOUGH_GRADIENT,
    2,
    150, // prend environ 2 fois ton rayon max
    300, // ajuste s'il faut
    80, // agit sur ce parametre s'il détecte trop de cercle (+ = moins de cercle)
    20, 80); // ajuste les tailles de rayon minimum et maximum

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    L'approche colorimétrique est très intéressante: je vais essayer tout ça dès demain et je te tiens au courant. Par la même occasion, je préfère essayer de coder Sobel avant de te demander ton code: cela ne peut que me faire du bien!
    Merci aussi pour HoughCircles!

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    Voilà ce que j'obtiens avec ton expression de HoughCircles:
    Pour ExempleDeBulle
    HoughCircles( *img, circles, CV_HOUGH_GRADIENT,
    2,
    800,
    150, //MinDistBetweenCenters
    80,
    200, 500);
    Pour ExempleDeBulle2
    HoughCircles( *img, circles, CV_HOUGH_GRADIENT,
    2,
    800,
    80, //MinDistBetweenCenters
    80,
    200, 500);

    Je dois à chaque réajuster à chaque fois. Pour ExempleDeBulle2, on détecte un cercle pour des minDistBetweenCenters inférieurs à 80:
    Est-ce raisonnable ( en terme de temps et d'éthique^^ ) de diminuer MinDistBetweenCenters tant que HoughCircles n'a pas détecté de cercle ( les vraies conditions sont: au moins un cercle détecté et son centre se trouve vers le milieu de l'image [ on ajoute une variable de tolérance ] )?^

    Sinon, pour l'approche colorimétrie, je me suis rappelé de mon prof de traitement d'images qui nous avait dit qu'il ne fallait jamais faire confiance à ses yeux!
    L'intensité est maximale au centre et non dans la bulle. J'ai tout de même codé qqs fonctions:
    int DetectMax( Mat img )
    int DetectMin( Mat img )
    void FindAverageMax( Mat* img, float openness );
    Cette dernière fonction colorie en blanc les pixels supérieurs à DetectMax( img ) * openness.
    Voici deux résultats pour openness = 0,4

    J'ai choisi de conserver la même valeur de openness, car mon application doit être indépendante de l'éclairage.
    Je vais donc continuer Sobel!
    Images attachées Images attachées     

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    effectivement pour l'approche colorimétrique ça ne va pas être exploitable.

    Pour le houghcircle, pourquoi tu met des limite min/max de rayon aussi haute ? le but n'est pas de détecter ton disque mais des bulles dans celui-ci donc réduit au minimum. Oublie pas que c'est le rayon (en pixel) et pas le diametre
    Réduit peut être le "80" pour détecter plus de cercles.

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    En fait, je pensais qu'il serait bon de commencer par diminuer la zone de travail pour éviter les aberrations et réduire les temps de calcul ( si les méthodes de détection en demandent beaucoup ).

    J'avais déjà laissé tomber HoughCircles pour détecter les bulles, car leur taille et leur forme varient très facilement d'un disque à l'autre.
    Ci-joint deux résultats.

    Même en faisant varier plusieurs paramètres, je ne parviens pas à isoler les deux bulles pour la première image.
    [ En bleu, j'ai colorié les cercles qui sont placés vers les petites bulles ]

    Sinon, avec un filtre de Canny, je suis arrivé à obtenir le contour des deux bulles sur la première image que j'ai publiée. Grâce à FindContours ( http://docs.opencv.org/modules/imgpr... Point offset) ), je sais où se trouve mes bulles sur mon image initiale et je compare l'intensité des pixels qui sont à l'intérieur des contours avec l'intensité minimale du grand disque ( que je peux obtenir avec FindContours ).
    Je n'ai pas du tout tester cela, peut-être je me trompe même sur les output de la fonction FindContours, mais je vais essayer de voir cela maintenant.
    Vous en pensez quoi?
    Images attachées Images attachées   

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    oula tu détecte trop de cercles là, il faut jouer sur le parametre précédent min_radius (qui vaut 80 dans mon exemple), ça va éliminer les cercles les moins probable.
    et puis tu n'exploite pas ton 1er masque qui t'as sélectionné la zone de ton disque (on voit des cercles ailleurs).

    pour findContour, il faut récupérer le 2eme parametres qui doit être un std::vector<std::vector<cv:oint> >
    chaque élement (dont un std::vector<cv:oint>) contient l'ensemble des points appartenant à un contours trouvé.

    ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cv::findContours(image, contours,  CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    avec ces paramètres tu obtiens tous les points de chaque contours.

    Tient j'ai fait un test avec ma fonction de gradient (et sans affiner les réglages) et j'obtient l'image en PJ sur la 1ère image non traité que tu as fourni. applique un findContour dans la zone du disque, trie tes contours suivant leur taille (std::sort) et tu regarde combien sont entre MIN et MAX en nombre de points de contours.
    Images attachées Images attachées  

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    "oula tu détecte trop de cercles là, il faut jouer sur le parametre précédent min_radius (qui vaut 80 dans mon exemple), ça va éliminer les cercles les moins probable."

    J'avais déjà descendu jusqu'à 10 et c'étaient des petits cercles sur le contour intérieur qui étaient détectés. Il y en avait une dizaine, mais ma grosse bulle n'était plus reconnue.

    "et puis tu n'exploite pas ton 1er masque qui t'as sélectionné la zone de ton disque (on voit des cercles ailleurs)."
    Désolé, je me suis allé un peu vite pour faire ces photos, mais je te rassure, je travaille avec mon premier masque.

    Enfin, pour FindContours, quand j'ai vu que j'avais 200 contours sur mon image à la sortie d'un filtre de Canny, j'ai pensé à discriminer les contours par leur nombre de points.

    Je n'ai pas codé Sobel moi-même, je vais donc prendre ton image pour tester FindContours.

    Merci

  11. #11
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    Citation Envoyé par Linkis Voir le message
    "oula tu détecte trop de cercles là, il faut jouer sur le parametre précédent min_radius (qui vaut 80 dans mon exemple), ça va éliminer les cercles les moins probable."

    J'avais déjà descendu jusqu'à 10 et c'étaient des petits cercles sur le contour intérieur qui étaient détectés. Il y en avait une dizaine, mais ma grosse bulle n'était plus reconnue.
    Non au contraire il faut l'augmenter !
    plus il est bas : plus tu détecte de cercles peu probable
    plus il est haut : plus tu détecte de cercle correct, donc tu en détecte moins.

    Pour trier des contours par taille (du plus grand au plus petit) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool DescendingCompare (std::vector<cv::Point> i,std::vector<cv::Point> j) { return (i.size()>j.size()); }
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::sort(contours.begin(), contours.end(), DescendingCompare);

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    "Non au contraire il faut l'augmenter !" cela m'apprendra à lire plus calmement la doc.

    Je suis en train de coder une fonction pour faire ce tri.

  13. #13
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    Citation Envoyé par Linkis Voir le message
    "Non au contraire il faut l'augmenter !" cela m'apprendra à lire plus calmement la doc.

    Je suis en train de coder une fonction pour faire ce tri.
    pourquoi ? std::sort le fait directement !

    (cf message précédent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // contours non trié de type std::vector<std::vector<cv::Point> >
    std::sort(contours.begin(), contours.end(), DescendingCompare);
    // contours trié
    il faut juste ajouter la fonction suivante à ton projet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool DescendingCompare (std::vector<cv::Point> i,std::vector<cv::Point> j) { return (i.size()>j.size()); }
    il suffit même de modifier cette fonction si tu veux du plus petit au plus grand (juste le "i.size()>j.size()" qui devient "i.size()<j.size()")
    )

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    "Je suis en train de coder une fonction pour faire ce tri. " Je voulais dire que j'étais dessus comme je ne connaissais pas sort. Après un petit tour sur le net, j'ai vu que tu m'avais tout fait: Merci bien!

    Sinon, cela fonctionne bien, mais il faut améliorer la détection: bien que je repère les deux bulles ( grâce au deuxième et au sixième contours ), les contours ne sont pas si terribles que cela.
    Images attachées Images attachées  

  15. #15
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    Comme je t'ai dis, j'ai pris un projet et j'ai utiliser mon algo direct sans régler les paramètres, tu pourras surement obtenir de meilleurs résultats en les réglant (ça supprimera surement le bruit, attention à ne pas être trop extrême sinon tu vas trouer les bulles ^^

    Sinon un algo pour supprimer le bruit (c'est clairement ce qui cause ton problème actuel).

    Tu t'en sors dans ton Sobel ?

  16. #16
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    Avec une ouverture, on peut éliminer un peu ce bruit, et oui il faut bien faire attention à ne pas percer les bulles.
    J'ai eu pas mal de choses depuis hier: je vais essayer de coder Sobel cette apreès-midi. Sur quelle page t'es appuyé pour la coder?

  17. #17
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    euh j'ai pas utilisé internet pour la coder, je suis en école d'ingé et on a eu des cours dessus, il doit y avoir quelques infos sur wikipedia (prend la version anglaise, elle est beaucoup plus complète)

    Bref l'algo de base c'est d'appliquer 4 matrice 3x3 en chaque point et de prendre le résultat le plus grand.
    J'ai un peu modifié la chose pour l'adapter à la couleur, mais t'en as pas besoin si tu traite que du noir et blanc.

    donc tu parcours ton image (attention, il ne faut pas traiter le cadre de 1 pixel formant l'image), les matrices sont les suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    -1 0 1
    -2 0 2
    -1 0 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    0 1 2
    -1 0 1
    -2 -1 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    1 2 1
    0 0 0
    -1 -2 -1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    2 1 0
    1 0 -1
    0 -1 -2
    ton pixel courant se trouve au centre.
    donc tu stock ces 4 résultats, tu garde le plus grand (en valeur absolue, le signe sert à déterminer la direction du gradient et on ne l'utilise pas ici), et s'il dépasse un certain niveau (tu défini toi même son seuil, dans l'image exemple que je t'ai envoyé, j'avais pris 25) alors tu écrit un pixel blanc sur une image résultante, sinon un pixel noir, aux coordonnées du pixels courant.

  18. #18
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    J'ai essayé de code tout cela, mais arrivé au bout, j'ai l'impression de n'avoir rien compris.
    1) Je convolue indépendamment tes 4 matrices avec une matrice 3x3 extraite de mon image.
    2) Je récupère 4 valeurs et je ne conserve que la plus grande valeur au pixel courant ( en valeur absolue )
    3) si cette dernière valeur max est plus grande que mon seuil ( j'ai gardé 25 ), je place un pixel blanc au pixel courant.
    Ai-je bon?


    Eest-ce bien ce calcul qui doit être fait?
    g(x,y) = sum( i= -1..1,
    sum( j= -1..1,
    (
    f(x+i, y+j)*h(i,j)
    )
    )
    avec f(x,y), le pixel (x,y) de mon image initiale et h(x,y) le coefficient du masque situé en (x,y)

    Pour réaliser la convolution, j'ai utilisé la fonction filter2D. Cependant, le résultat de la convolution, pour une matrice 3x3 extraite de mon image, dépasse 1000 ( pour le 1er masque dont les coeffs sont définis comme des uchar ).Je précise que mes coeffs sont définis ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Mat mask1=Mat(3,3,CV_8U);
        mask1.at<uchar>(0,0)=-1;
        mask1.at<uchar>(0,1)=0;
        mask1.at<uchar>(0,2)=1;
        mask1.at<uchar>(1,0)=-2;
        mask1.at<uchar>(1,1)=0;
        mask1.at<uchar>(1,2)=2;
        mask1.at<uchar>(2,0)=-1;
        mask1.at<uchar>(2,1)=0;
        mask1.at<uchar>(2,2)=1;
    flip(mask1,mask1,-1);
    Il s'agit d'un problème de type de variables.

    Je voudrais donc savoir comment je dois définir mon image initiale: dois-je convertir son type ( grâce à convertTo ) et/ou normaliser les coefficients de l'image? Quels sont les types des coefficients et des matrices que tu utilises pour ton calcul?
    Enfin, je précise que j'avais testé filter2D avec une matrice initiale simple ( 3x3 ) et les résultats étaient cohérents.

  19. #19
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Points : 58
    Points
    58
    Par défaut
    C'est normal que ça dépasse les 1000, parfois (tu peux avoir 1*255 + 2*255 + 1*255 -1*0 -2*0 -1*0 = 1020 au max).

    si tu veux lire ton image en niveau de gris (pixel stocké dans des uchar) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cv::imread("image.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    moi en fait je fais le calcul direct (c'est assez moche du coup)
    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int kernel[9] = {image.at<cv::Vec3b>(i-1, j-1)[k],
    						image.at<cv::Vec3b>(i, j-1)[k],
    						image.at<cv::Vec3b>(i+1, j-1)[k],
    					image.at<cv::Vec3b>(i-1, j)[k],
    						image.at<cv::Vec3b>(i, j)[k],
    						image.at<cv::Vec3b>(i+1, j)[k],
    					image.at<cv::Vec3b>(i-1, j+1)[k],
    						image.at<cv::Vec3b>(i, j+1)[k],
    						image.at<cv::Vec3b>(i+1, j+1)[k]};
     
    gradInter[0] = (-1) * kernel[0] +
    					(-2) * kernel[3] +
    					(-1) * kernel[6] +
    					kernel[2] +
    					2 * kernel[5] +
    					kernel[8];
    (etc)

    En fait, j'ai découvert quand l'accès direct aux valeurs du pixel de l'image via .at<...>() prenait plus de temps qu'en le stockant ... (remarque : j'aurais du mettre uchar kernel[9]...)

  20. #20
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2012
    Messages : 43
    Points : 28
    Points
    28
    Par défaut
    Entre temps, j'avais regardé ailleurs et trouvé ce code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void SobelTest( Mat* p_grayImg )
    {
      int scale = 1;
      int delta = 0;
      int ddepth = CV_16S;
     
      GaussianBlur( *p_grayImg, *p_grayImg, Size(3,3), 0, 0, BORDER_DEFAULT );
     
      /// Generate grad_x and grad_y
      Mat grad_x, grad_y;
      Mat abs_grad_x, abs_grad_y;
     
      /// Gradient X
      Sobel( *p_grayImg, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
      convertScaleAbs( grad_x, abs_grad_x );
     
      /// Gradient Y
      Sobel( *p_grayImg, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
      convertScaleAbs( grad_y, abs_grad_y );
     
      /// Total Gradient (approximate)
      addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, *p_grayImg );
    }
    Ci-joint, tu peux voir le résultat après seuillage et fermeture.
    Merci bcp pour ton code, c'est sympa!
    Mais, du coup, je ne sais pas quoi garder^^ Je repars sur FindContours


    D'ailleurs, qq'un aurait-il compris quelles sont les différences entre les champs "type", "channels" et "depth" d'un objet Mat? La doc ne me permet pas d'y voir clair.
    Images attachées Images attachées  

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. corrélation de phase
    Par dudux dans le forum Traitement d'images
    Réponses: 3
    Dernier message: 22/03/2011, 08h49
  2. corrélation de phases( phase only correlation)
    Par annabiste dans le forum Images
    Réponses: 1
    Dernier message: 29/05/2010, 20h23
  3. Corrélation de phase
    Par widwid82 dans le forum OpenCV
    Réponses: 2
    Dernier message: 28/07/2009, 04h00
  4. Fitter une fonction (méthode Corrélation de phase)
    Par Programmeur_Aladdin dans le forum Traitement d'images
    Réponses: 7
    Dernier message: 10/03/2008, 17h46
  5. Augmenter la précision avec la méthode de corrélation de phase
    Par Programmeur_Aladdin dans le forum Traitement d'images
    Réponses: 0
    Dernier message: 28/02/2008, 15h59

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