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

C++ Discussion :

tri d'un tableau dynamique


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut tri d'un tableau dynamique
    Bonjour à tous !

    Deux petites questions:

    -Afin de réaliser un filtrage médian sur une image (en c++), j'aimerais trier un tableau dynamique à 2 dimensions (mon tableau de pixels). J'ai bien regardé dans tous ce qui est algo de tri rapide mais je vois pas du tout comment les implanter avec des tableaux dynamique.

    -Laquelles des écritures il faut privilégier pour définir un tableau dynamique à 2 dimensions ?

    -vector< vector<int> > tab;

    ou

    -**int tab;

    il y a une différence notable ?

    D'avance merci pour vos lumières !

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    L'allocation dynamique à la main int** va rapidement devenir inextricable pour assurer une garantie face aux exceptions. Je te le déconseille fortement.

    Si le nombre de colonnes par lignes est toujours le même, je me demande si un vecteur à plat (std::vector<int>(nbrLigne*nbrColonne)) ne serait pas préférable à un std::vector<std::vector>> (au - meilleur localité dans le premier cas).

    Je ne suis pas expert en traitement d'image, loin de là, mais à quoi sert ton tri ? Le filtrage médian ne consiste-t-il pas à prendre la moyenne des pixels autour de chaque pixel ? Quel rapport avec le tri ?

    Autre chose : n'existe-t-il pas de bibliothèque éprouvée faisant ce que tu souhaites ?

  3. #3
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Sous OpenCV on peut le faire assez simplement :
    (je n'ai pas vérifié le code, c'est sûrement truffé d'erreurs)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <opencv2/opencv.hpp>
     
    int main() {
    cv::Mat image_in = imread("image.jpg");
    cv::Mat image_out(image_in);
     
    cv::medianBlur(image_in, image_out, 3);
     
    cv::imshow("Resultat", image_out);
     
    return 0;
    }
    Construire une matrice sous OpenCV ?
    Filtrer cette matrice avec medianBlur ?

  4. #4
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut
    Bonsoir,

    Déjà merci de vos réponses et ensuite précisions :

    - Le truc s'inscrit dans le cadre d'un projet en cours d'informatique , exit l'utilisation des bibliothèques qui feraient (presque) tout le boulot à notre place Ce s'rait pas drôle sinon !

    -@ 3DArchi : ce que tu me décrits est le filtrage Moyen. Le filtrage Median, c'est attribuer au pixel traité la valeur médiane de son voisnage. D'où le tri. Bon c'est vrai, Median, Moyen... c'est jouer sur les mots mais c'est le jeu

    Alors pour le coup de la déclaration des tableaux dynamiques, j'ai commencé- et même bien avancé- avec ce que tu m'as déconseillé, les int**...
    C'est une erreur ou une faute ? J'veux dire, j'dois m'amuser à tout redéfinir ou le prof ne verra pas la différence ? Question d'élégance ? De quelles exception parles tu ?
    Mes tableaux dynamiques correspondent au matrice de l'image et sont globalement assez gentils ( de simple int en ligne et colonne quoi !)

    Enfin bref ça me résout pas la question du tri tout ça

  5. #5
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 391
    Points
    11 391
    Billets dans le blog
    11
    Par défaut
    Qu'est-ce que tu entends par "valeur médiane de son voisinage" ?
    De plus, c'est un code C ou C++ que tu dois produire ? Car si c'est un code C++, je ne vois pas en quoi le fait d'utiliser la STL (pour vector) peut poser un problème, même à ton prof.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par dragonjoker59 Voir le message
    je ne vois pas en quoi le fait d'utiliser la STL (pour vector) peut poser un problème, même à ton prof.
    Il disait ça par rapport à OpenCV.

    Par contre, je vois toujours pas pourquoi tu veux trier. Trier comment, dans quel sens ? Quelle est la relation d'ordre entre les pixels ?

    A mon avis, c'est un filtre, pas un tri. Le mieux je pense est d'utiliser la solution proposée par 3DArchi. T' encapsules ça dans une classe qui va te représenter une matrice de pixels et le tour est joué.

    Ensuite tu auras ta matrice de départ, et ta matrice d'arrivée. Tu ne peux pas écrire directement dans la matrice de départ car tu as besoin de la valeur initiale du pixel sur lequel tu écris pour que l'algo fonctionne.
    Find me on github

  7. #7
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut
    Oui en effet, c'est pour OpenCV que je disais cela.

    Et absolument d'accord pour le reste aussi : j'ai ma matrice de pixel d'entrée ( contenue dans le tableaux dynamique 2 dimensions) que je convolue ( un filtre quoi) par différents filtres.
    J'ai déjà réalisé differentes convolutions (aller, on va dire "filtre" c'est moins pédant ) genre Laplacien, Gaussien, filtre de Sobel i tutti quanti.

    Pour le filtre médian, le pixel courant vaut la valeur médiane de son voisinage . C'est donc bien un filtre que je réalise. Mais pour récupérer la valeur médiane, j'dois bien trier dans l'ordre croissant les valeurs de mon voisinage pour récupérer ensuite la valeur médiane ( qui d'après mes souvenirs de stats de 2nd "coupe" l'effectifs trié en ordre croissant en 2) ?

    D'ou l'idée du tri de mon tableaux dynamique.

    Après j'suis p'tet complètement à côté de la plaque !

    J'peux p'tet poster mon code quelque part histoire d'y voir plus clair mais je ne sais trop où .. ici même ?

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par serge_galoup Voir le message
    Pour le filtre médian, le pixel courant vaut la valeur médiane de son voisinage . C'est donc bien un filtre que je réalise. Mais pour récupérer la valeur médiane, j'dois bien trier dans l'ordre croissant les valeurs de mon voisinage pour récupérer ensuite la valeur médiane ( qui d'après mes souvenirs de stats de 2nd "coupe" l'effectifs trié en ordre croissant en 2) ?

    D'ou l'idée du tri de mon tableaux dynamique.
    J'ai compris ! En fait tu veux juste obtenir une valeur, la position du pixel dans le voisinage n'a pas d'importance (ou alors il a un poids mais ça change pas grand chose en fait).

    Dans ce cas, la solution à ton problème est simple : tu n'as pas besoin d'un tableau à deux dimensions mais à une seul dimension, puisque la valeur de chaque pixel n'a aucune corrélation avec sa position dans la matrice.

    J'ai pas le temps de détailler le code, mais il te faut un std::vector< Pixel > (ou simplement std::vector< (int | float) > si tu travailles en niveaux de gris). Ensuite tu peux utiliser std::sort et tout le tsoin tsoin. A chaque pixel, tu stockes le voisinage dans ton tableau d'une dimension et tu le tries. Puis tu récupères ta valeur.

    C'est sûrement pas optimisé mais là n'est pas le problème : ça fonctionnera.
    Find me on github

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    La valeur médiane, si mes souvenirs sont bons, est celle où 50% de l'échantillon est en dessous et 50% est au dessus. D'où le tri puisqu'il suffit ensuite de prendre celle du milieu.

    Pour le stockage, je te (re)déconseille les int** et repasse sur une seule dimension, idéalement vector<int>. Par exception, j'entendais la possibilité de ton code de lever une exception (allocateur par expl) et sa solidité face à ce problème : tout sera-t-il bien libéré ? Mais aussi je pense que l'allocation sur une ligne te garantie une certaine localité des données là où plusieurs allocations peuvent très bien conduire à une fragmentation de ta matrice sur la mémoire. Ca aura probablement une conséquence sur les perf.

    pour ton problème de tri, je pense que tu dois copier le voisinage du pixel dans un tableau temporaire de dimension réduite puis effectuer le tri dessus.

  10. #10
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Je rejoins 3Darchi sur l'utilisation d'un tableau unidimensionnel.

    Maintenant, plutôt que copier et trier (tri = o(25 * 7) = o(175)), pourquoi ne pas profiter du fait que les valeurs sont comprises entre 0 et 255 ? On crée un tableau de 256 compteurs, on les remplit à partir des 25 valeurs, puis on parcourt le tableau jusqu'à avoir plus de 12 occurrences. En moyenne ce sera du o(128) et il y aura moins de branchements conditionnels et pas de récursion. Surtout, c'est plus élégant.

  11. #11
    Membre confirmé

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Points : 527
    Points
    527
    Par défaut
    A noter que ce problème est un vrai cas d'école d'utilisation des shaders de GPU. Puisqu'il s'agit d'un environnement scolaire, j'espère que votre enseignant le mentionne.
    "Maybe C++0x will inspire people to write tutorials emphasizing simple use, rather than just papers showing off cleverness." - Bjarne Stroustrup
    "Modern C++11 is not your daddy’s C++" - Herb Sutter

  12. #12
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup pour toutes ces réponses et conseils avisés !!

    Pour le coup de "l'utilisation des shaders de GPU" j'ai envi de dire "What is the fuque ?" mais j'le dirais pas, c'est grossier
    Je n'ai pas souvenir de cela dans les cours dispensés mais je suis plutôt du genre au-fond-près-du-radiateur en cours d'info.. et voilà ou ça me mène ! 'Fin bref, c'est pas le sujet.

    Vacances de Noël obligent, je risque d'être absent quelque temps mais promis, je tente ça dès que possible ( suppression de l'écriture int** et passage en uninidimensionel pour le filtrage median ) et je vous tient au jus !

    Encore merci et comme c'est l'époque, joyeuses Pâques à tous !

  13. #13
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    Je rejoins 3Darchi sur l'utilisation d'un tableau unidimensionnel.

    Maintenant, plutôt que copier et trier (tri = o(25 * 7) = o(175)), pourquoi ne pas profiter du fait que les valeurs sont comprises entre 0 et 255 ? On crée un tableau de 256 compteurs, on les remplit à partir des 25 valeurs, puis on parcourt le tableau jusqu'à avoir plus de 12 occurrences. En moyenne ce sera du o(128) et il y aura moins de branchements conditionnels et pas de récursion. Surtout, c'est plus élégant.
    Salut
    L'idée est effectivement élégante pour un petit échantillon.

    Mais pourquoi supposer que les valeurs sont sur un octet ? A priori, il encode ses pixels sur des ints ?

  14. #14
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut
    L'idée est effectivement élégante pour un petit échantillon.

    Mais pourquoi supposer que les valeurs sont sur un octet ? A priori, il encode ses pixels sur des ints ?
    Parce que chaque canal réclame un traitement séparé je présume : R est la valeur médiane des R des 25 pixels voisins, etc.

  15. #15
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Je ne sais pas trop, entre le tri de 8 valeurs et la lecture d'en moyenne 128 valeurs dans un tableau ce qui sera en pratique le plus lent.

    Par contre, le voisinage étant de taille fixe (même pour une image étant un tableau dynamique), pour le mettre dans un mini conteneur adapté au tri, un [boost/std]::array<int, 8> est probablement plus intéressant qu'un vector<int>.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #16
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Je ne sais pas trop, entre le tri de 8 valeurs et la lecture d'en moyenne 128 valeurs dans un tableau ce qui sera en pratique le plus lent.
    Tu pars du principe qu'on ne considère que les 8 voisins (rayon égal à 1) mais le filtre peut très bien être de rayon variable.

  17. #17
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    En effet, si le voisinage est variable, ce que j'ai dit sur array ne s'applique plus, et plus il est grand, plus la méthode à base de stockage dans un tableau de valeurs a des chances d'être plus efficace.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  18. #18
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut
    Bonjour à tous !

    Je vois que j'ai été gâté pour les fêtes !

    C'est en effet la solution de passer par un tableau une dimension qui fonctionne !

    Pour le coup de **int ou vector <> c'est également vector qui s'avère le mieux (plus souple à utiliser , et visiblement moins de problèmes, même si ça j'ai pas trop compris ); ) La STL a du bon !

    Du coup j'vous salue bien bas et vous remercie grandement pour l'aide !

  19. #19
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 3
    Points
    3
    Par défaut
    Et bien en fait je reviens vers vous car je croyais avoir résolu mon problême mais en regardant bien...pas du tout.

    C'est bien le fait de passer par un tableau dimension qui marche mais là, c'est le drame !

    ( attention, question d'une simplicité confondante, mais pas pour moi !)

    J'ai un vecteur de dimension 2 et je veux le transformer en un vecteur 1 dimension. Ben comment qu'on fait dites ?

    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
     
    // déclaration d'un vector 2 dimensions :
     
     vector< vector<int> >vecteur_2D (largeur, std :: vector <int> (hauteur));
     
     
    // on alloue vecteur_2D avec les valeurs de newPixels:
     
        for( i = 0; i < vecteur_2D.size(); i++ )
        {
            for( j = 0; j < vecteur_2D[i].size(); j++ )
            {
     
    /* alors là c'est moche, j'ai finalement gardé la notation int** ( pour mon niveau ça passe et j'ai pas envie/pas le temps de tout transformé..:s)*/
     
                vecteur_2D [i][j]=  newPixels [i][j]; 
     
     
            }
        }

    Si quelqu'un passe par là, j'suis preneur de toutes les remarques et suggestions..


    D'avance merci !

  20. #20
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par serge_galoup Voir le message
    J'ai un vecteur de dimension 2 et je veux le transformer en un vecteur 1 dimension. Ben comment qu'on fait dites ?
    Bonjour. Typiquement, avec quelque chose du genre : vecteur1d[i * width + j] = vecteur2d[i][j]

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

Discussions similaires

  1. [XL-2013] Tri de données / Tableau Croisé Dynamique / Gestions des Doublons.
    Par arnachronox dans le forum Excel
    Réponses: 5
    Dernier message: 29/12/2014, 13h41
  2. Réponses: 2
    Dernier message: 06/09/2007, 15h08
  3. [Kylix] tableau dynamique
    Par sdoura2 dans le forum EDI
    Réponses: 1
    Dernier message: 31/10/2002, 08h57
  4. [] Tri d'un tableau par ordre alphabétique
    Par cafeine dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 17/09/2002, 08h43
  5. Réponses: 4
    Dernier message: 13/05/2002, 16h43

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