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

Images Discussion :

optimisation d'un code pour selectionner des pixels aléatoires


Sujet :

Images

  1. #1
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 89
    Points : 85
    Points
    85
    Par défaut optimisation d'un code pour selectionner des pixels aléatoires
    Bonjour à tous,

    Alors voilà, j'ai écrit un programme qui me sélectionne un certain nombre de pixels d'une image de façon aléatoire dans une image. L'image est une matrice rempli d'entiers pouvant prendre des valeurs comprises entre 1 et N.
    Le code marche, mais le problème, c'est que le temps de calcul croit très rapidement avec la taille et le nombre de pixels à selectionner. J'aimerai avoir votre avis sur mon code, histoire de voir si je peux l'améliorer un peu.

    voici la bête:

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    function generate_markers(class_map,nb_mark,N,i,nb_map,Imshort)
     
    dim=size(class_map);
    marker_map=zeros(dim);
    k=0;
     
    while k<nb_mark
     
        x=floor(dim(1)*rand+1);
        y=floor(dim(2)*rand+1);
     
        %with this little test, it is sure that the correct number of markers
        %is computed -> impossible to have the same marker twice
        if marker_map(x,y)==0  
            marker_map(x,y)=class_map(x,y);
            k=k+1;
        end
     
    end
    %% filling the file in a compatible format for the MSF software
    fid=fopen(['../results/' Imshort '/' Imshort '_' int2str(nb_map) '_MSF_' int2str(nb_mark) '/marker_map_' int2str(nb_mark) '_' int2str(i) '.marker'],'wt');
     
    fprintf(fid,'%d\n',nb_class);
    for i=1:dim(1)   
        fprintf(fid,'%d ',marker_map(i,:));   
        fprintf(fid,'\n');  
    end
     
    vect_class = 1:nb_class;
     
    fprintf(fid,'\n');
    fprintf(fid,'%d ',vect_class(:,:));
    fprintf(fid,'\n'); 
    fclose(fid);
     
    end
    Le paramètre "i" est là car je repète cette opération M fois et j'appelle cette fonction dans un autre programme.

    Une contrainte est aussi la mise en forme du résultat. Vous allez me dire de faire juste un imsave ou un truc du genre, mais je peux pas, il faut que ça ait le format sous lequel je le sauvegarde.
    ceci dit, si quelqu'un peut me dire à priori combien de temps je pourrai gagner en simplifiant la sauvegarde, ça pourrait m'aider aussi.

    Y'a peut-être des points ou j'ai pas été clair, donc n'hésitez pas à me le dire, j'essaierai de préciser.

    Merci d'avance,
    kévin

  2. #2
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 52 884
    Points
    52 884
    Par défaut
    Inspire toi de ceci : Comment obtenir un tirage aléatoire sur un nombre donné d'élément d'une matrice ?

    Et la boucle suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i=1:dim(1)   
        fprintf(fid,'%d ',marker_map(i,:));   
        fprintf(fid,'\n');  
    end
    s'écrit aussi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fmt = [repmat('%d ',1,dim(2)) '\n'];
    fprintf(fid, fmt, marker_map.');
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

  3. #3
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 89
    Points : 85
    Points
    85
    Par défaut
    Merci Dut pour ta réponse.
    Néanmoins, j'ai essayé de faire un truc avec les fonctions numel et randperm, comme suggéré dans la FAQ. mais le temps de calcul est bien superieur à ce que j'ai proposé:

    mon code pour une image de 610*340 pixels me donne un temps de calcul de 0.009401 secondes

    avec le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    marker_map=zeros(size(class_map));
    ind=numel(class_map);
    rdind=randperm(ind);
     
    for i=1:nb_mark
        marker_map(rdind(i))=class_map(rdind(i));
    end
    , j'obtient Elapsed time is 0.037553 seconds, donc 3 fois plus!

    Et c'est bien la partie séléction des pixels qui prend le plus de temps (j'ai verifié sans la partie remplissage, et ça me donne un temps d'environ 0.034 sec).

    du coup, je pense que c'est bien la partie sauvegarde qui prend le plus de temps.
    Pour la petite histoire, avec le code que j'ai posté, ça me donne 0.65 sec, et avec la modif de Dut (merci beaucoup!), ça tombe à 0.32 sec.

    merci encore Dut, temps de calcul divisé par 2, c'est pas mal déja, merci!

  4. #4
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 52 884
    Points
    52 884
    Par défaut
    Citation Envoyé par kevin07 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    marker_map=zeros(size(class_map));
    ind=numel(class_map);
    rdind=randperm(ind);
     
    for i=1:nb_mark
        marker_map(rdind(i))=class_map(rdind(i));
    end
    Pas besoin de la boucle FOR-END ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    marker_map=zeros(size(class_map));
    ind=numel(class_map);
    rdind=randperm(ind);
     
    marker_map(rdind)=class_map(rdind);
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

  5. #5
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 89
    Points : 85
    Points
    85
    Par défaut
    En effet, sans la boucle ça marche aussi, mais le temps de calcul augmente.
    avec le code que tu proposes, j'obtient 0.047752 secondes, soit 1 centième de plus...

  6. #6
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 52 884
    Points
    52 884
    Par défaut
    Citation Envoyé par Dut Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    marker_map(rdind)=class_map(rdind);
    Une petite erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    marker_map(rdind(1:nb_mark))=class_map(rdind(1:nb_mark));
    Maintenant pour le temps d'exécution, tout dépend de la taille des différentes variables (surtout nb_mark);
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

  7. #7
    Expert éminent sénior
    Avatar de Caro-Line
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    9 458
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 9 458
    Points : 14 830
    Points
    14 830
    Par défaut
    Mes quelques remarques directement dans le code (je n'ai pas repris les remarques de Dut, et je ne sais pas si cela permettra un gain de temps).
    Mes commentaires sont précédés de %c%

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    function generate_markers(class_map,nb_mark,N,i,nb_map,Imshort)
     
    dim=size(class_map);
    marker_map=zeros(dim);
     
    %c%Pour quoi faire un while plutôt qu'un FOR ?
    %c%Je ne pense pas que ça change beaucoup de chose au niveau timing mais c'est plus propre
    %c%k=0;
     
    for k = 1:nb_mark
    %c%note : le paramètre k ne sert pas vraiment donc de 1 à nb_mark est pareil que de 0 à nb_mark-1
    %c%while k<nb_mark    
        x=floor(dim(1)*rand+1);
        y=floor(dim(2)*rand+1);
     
        %with this little test, it is sure that the correct number of markers
        %is computed -> impossible to have the same marker twice
        if marker_map(x,y)==0  
            marker_map(x,y)=class_map(x,y);
            %c%k=k+1;
        end
     
    end
    %% filling the file in a compatible format for the MSF software
    %c%Pour l'écriture du fichier voir les faq données à la suite
    %c%fid=fopen(['../results/' Imshort '/' Imshort '_' int2str(nb_map) '_MSF_' int2str(nb_mark) '/marker_map_' int2str(nb_mark) '_' int2str(i) '.marker'],'wt');
    fichier = fullfile('..','results',Imshort,sprintf('%s_%d_MSF_%d',Imshort,nb_map,nb_mark),sprintf('Marker_map_%d_%d.marker',nb_mark,i));
    fir = fopen(fichier,'wt');
     
     
    fprintf(fid,'%d\n',nb_class);
    for i=1:dim(1)   
        fprintf(fid,'%d ',marker_map(i,:));   
        fprintf(fid,'\n');  
    end
     
    vect_class = 1:nb_class;
     
    fprintf(fid,'\n');
    %c%drôle d'écriture
    %c%fprintf(fid,'%d ',vect_class(:,:));
    fprintf(fid,'%d ',vect_class');
    fprintf(fid,'\n'); 
    fclose(fid);
     
    end

    Comment concaténer le nom d'un fichier et celui d'un répertoire ?
    Comment nommer une suite de fichiers : nom_1.ext, nom_2.ext... nom_N.ext ?
    Règles du Forum

    Adepte de la maïeutique

  8. #8
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 89
    Points : 85
    Points
    85
    Par défaut
    Merci caroline pour tes suggestions qui permettent de rendre l'écriture de mes fichiers un peu plus propre.

    Par contre, j'ai une question sur la boucle 'for'. Je pense que ça ne fait pas la même chose que ma boucle 'while'.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    %c%while k<nb_mark    
        x=floor(dim(1)*rand+1);
        y=floor(dim(2)*rand+1);
     
        %with this little test, it is sure that the correct number of markers
        %is computed -> impossible to have the same marker twice
        if marker_map(x,y)==0  
            marker_map(x,y)=class_map(x,y);
            %c%k=k+1;
        end
     
    end
    Avec le while, il faut que la condition à l'intérieur du 'if' soit vérifiée pour que la valeur de k soit incrémentée. et donc j'évite les cas ou par hasard, le tirage aléatoire me sort un pixel qui a déja été selectionné.
    Par contre, avec la boucle 'for', si j'ai bien compris, si la condition du 'if' n'est pas vérifiée, k est quand même incrémenté. Et du coup à la fin je peux me retrouver dans une situation ou j'ai moins de pixels que prévu (ce qui arrive plus fréquemment si l'image est petite).

    est-ce que j'ai bien compris?

    merci encore pour vos suggestions à tous les deux

  9. #9
    Expert éminent sénior
    Avatar de Caro-Line
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    9 458
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 9 458
    Points : 14 830
    Points
    14 830
    Par défaut
    Oups j'ai honte, mais bien sûr que
    Remet ta boucle WHILE, je vais aller me cacher au fond d'un igloo sur la banquise et rechercher un bon opticien....
    Règles du Forum

    Adepte de la maïeutique

Discussions similaires

  1. [XL-2002] Optimisation code pour générer des balises richtext
    Par stef_PBR dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 29/07/2009, 19h13
  2. code pour lire des carte à puce
    Par kuzamba dans le forum Général VBA
    Réponses: 1
    Dernier message: 18/05/2007, 09h14
  3. Réponses: 8
    Dernier message: 08/03/2007, 16h54
  4. Réponses: 5
    Dernier message: 14/05/2006, 12h57

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