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++Builder Discussion :

Temps d'execution très lent


Sujet :

C++Builder

  1. #1
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut Temps d'execution très lent
    Bonjour à tous,
    J’ai écrit un programme qui permet d’attribuer à chaque pixel d’une image la valeur minimale de tous les pixels voisins qui se trouvent à une distance inférieure ou égale à d (d représente le rayon d’un disque).
    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
    47
    48
    49
    50
    51
    52
     
    int tri[1000];
    H=Image1->Picture->Bitmap->Height;
    W=Image1->Picture->Bitmap->Width;
    for(int x=0;x<W;x++)
            for(int y=0;y<H;y++)
            {
            a=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
            b=a%256;
            g=(a/256)%256;
            r=(a/(256*256))%256;
            Image[x][y]=(int)(r*0.299+g*0.587+b*0.114);
            }
     
    int px, py;
    double d;
    int min;
    for(int x = 0; x < W; x++)
        for(int y = 0; y < H; y++)
           {
           int k=1;
           for (int i = -50; i <= +50; i++)
               {
               px = x + i;
               for(int j = -50; j <= +50; j++)
                  {
                   py = y + j;
                   if((px >= 0) && (px < W) && (py >= 0) && (py < W))
                     {
     
                      d=sqrt(pow(x-px,2)+pow(y-py,2));
     
    		  if (d <= 50)
                         {
                         tri[k]=Image[px][py];
                         k=k+1;
                         }
                       }
                    }
                 }
                 min=tri[1];
                 for (int l=2;l<=k;l++)  {
                                         if (min>tri[l])min=tri[l];
                                         }
    image[x][y]=min;
            }
     
    for(int x=0;x<W;x++)
        for(int y=0;y<H;y++)
        {
        Image1->Canvas->Pixels[x][y]=(TColor)((int)(image[x][y]+256*image[x][y]+256*256*image[x][y]));
        }
    Mon problème est le suivant : quand d augmente l’exécution devient plus lente et mon application nécessite un d>=50 .
    Si vous avez une idée pour résoudre ce problème veuillez me laisser un message

  2. #2
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Bonjour
    ton code me semble obscur
    qu'en est il de la variable <image> ,<Image> et <Image1>
    cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  3. #3
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut

    Pour <image> et <Image> il suffit d'ajouter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    int H,W,a,r,g,b;
    unsigned char image[1000][1000];
    byte Image[1000][1000];
    <Image1> représente le nom de l'image du composant graphique TImage

    A+

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    d=sqrt(pow(x-px,2)+pow(y-py,2));
    if (d <= 50)
    ....
    sqrt et pow sont des fonctions couteuses en temps de calcul. Il est plus rapide de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int d;
    d=(x-px)*(x-px)+(y-py)*(y-py);// ou d = i*i+j*j
    if (d <= 2500)
    .....
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut
    Salut,
    sqrt et pow sont des fonctions couteuses en temps de calcul. Il est plus rapide de faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int d;
    d=(x-px)*(x-px)+(y-py)*(y-py);// ou d = i*i+j*j
    if (d <= 2500)
    .....
    je viens de l'essayer et malheureusement ça donne le même résultat

    A+

  6. #6
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    Salut, un petit conseil essaie d'optimiser ton code. Par exemple dans ta boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            for(int y=0;y<H;y++)
            {
            a=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
            b=a%256;
            g=(a/256)%256;
            r=(a/(256*256))%256;
            Image[x][y]=(int)(r*0.299+g*0.587+b*0.114);
            }
    Essai d'utiliser moins d'allocation de mémoire si c'est possible, ne déclare pas de variable si ce n'est pas pour les utiliser plus d'une fois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            for(int y=0;y<H;y++)
            {
            a = Image1->Picture->Bitmap->Canvas->Pixels[x][y];
            Image[x][y]=(int)(((a/(256*256))%256) * 0.299 +
                              ((a/256)%256) * 0.587 +
                              (a%256) * 0.114);
            }
    En plus, ne calcule pas des valeurs que tu conais (256*256 = 65536):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            for(int y=0;y<H;y++)
            {
            a = Image1->Picture->Bitmap->Canvas->Pixels[x][y];
            Image[x][y]=(int)(((a/(65536))%256) * 0.299 +
                              ((a/256)%256) * 0.587 +
                              (a%256) * 0.114);
            }
    Se n'est pas ceci qui va faire un gros changement, mais c'est un début. Une autre chose que tu peux c'est d'essayer d'utiliser moins de boucle for, essaie d'en inclure une dans les autres quand c'est possible.

    PS: je ne suis pas au courant de tout les optimisations que fait le compilateur.
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Peut-être en commençant par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class jPixel
    {
    public :
    Byte Blue;
    Byte Green;
    Byte Red;
    };

    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
    jPixel *Pixel;
    int b;
    int r;
    int g;
    Graphics::TBitmap *B = Image1->Picture->Bitmap;
     
    for(int y = 0; y < B->Height; y++)
        {
        Pixel = (jPixel*)B->ScanLine[y];
        for(int x = 0; x < B->Width; x++)
            {
            b = Pixel->Blue * 11; //0.114
            g = Pixel->Green * 59; //0.587
            r = Pixel->Red * 30; //0.299
            Image[y][x] = (Byte)((b + g + r) / 100);
            Pixel++;
            }
        }
    Ici, j'ai supposé que l'on travaille sur un bitmap 24 bits.

    A plus !

  8. #8
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut
    Salut,

    J'ai suivi tous vos conseils mais malheuresement le problème persiste

    A+

  9. #9
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Ensuite remplacer :

    d=sqrt(pow(x-px,2)+pow(y-py,2));
    par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d = hypot(x-px, p-py); //racine de a²+b² est donné par hypot
    Puis remplacer la partie :

    for(y)
    for(x)
    Image1->Canvas->Pixels[x][y]=(TColor)((int)(image[x][y]+256*image[x][y]+256*256*image[x][y]));
    par (selon le même principe...):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Byte v;
    for(y=0; y < B->Height...)
        {
        Pixel = (jPixel*)B->ScanLine[y];
        for(int x = 0; x < B->Width...)
            {
            v = image[y][x]; //ici selon ma propre vision au niveau du tableau
            Pixel->Blue = v;
            Pixel->Green = v;
            Pixel->Red = v;
            Pixel++;
            }
        }
    Plus tard en soirée... je testerai l'ensemble...

    Salut !

  10. #10
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut

  11. #11
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Cette érosion de l'image a déjà été abordée (à l'époque c'était avec un seuillage max il me semble)

    En fait, il faut précalculer les offsets pour chaque point sur le disque de manière à ne pas le faire dans le traitement, sinon, on a une grande redondance au niveau calcul pour chaque centre (x,y).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int Rayon;  //ici Rayon <= 50
    int Ofx[10000]; // 100 * 100
    int Ofy[10000];
    Précalculer les offsets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int NbOf=0;
    for(int y = -Rayon; y <= Rayon; y++)
        {
        for(int x = -Rayon; x <= Rayon; x++)
            {
            d = sqrt((x*x) + (y*y)); //un peu plus rapide que hypot
            if(d < Rayon)
                {
                Ofx[NbOf] = x;
                Ofy[NbOf] = y;
                NbOf++;
                }
            }
        }
    Pour le traitement :

    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
    for(int y = 0; y < he; y++)
        {
        for(int x = 0; x < we; x++)
            {
            min = 0xFF; //max = 0;
            for(int of=0; of < NbOf; of++)
                {
                px = x + Ofx[of];
                py = y + Ofy[of];
                if((py>=0) && (py<he) && (px>=0) && (px<we))
                    {
                    v = I[py][px];
                    if(min > v) min = v; // if(max < v) max = v; 
                    }
                }
            T[y][x] = min; // T[y][x] = max;
            }
        //Caption = IntToStr(y); //Echo de la progression
        }
    A plus !

  12. #12
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il y a des erreurs dans le code que tu proposes :
    - 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (int l=2;l<k;l++)  {
              if (min>tri[l])min=tri[l];
       }
    -2 plus grave, la dimension de tri est beaucoup trop faible et conduit presque à coup sûr à des dépassements pour d = 50. La dimension de sécurité devrait être de 4*d*d. Ceci peut expliquer des comportements bizarres pour d de l'ordre de 20 ou supérieur.
    - Il est inutile de calculer d avec puissance, racine carrée ou hypothénuse
    - la valeur de d est la même pour i et -i et pour j et -j. Les boucles i et j de 0 à d devrait suffire.
    - Il n'est peut être pas astucieux de déclarer ces variables dans l'instruction for, ce qui amène à leur création/destruction à chaque pas de la boucle supérieure.

    Je te propose qq chose du genre
    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
    47
    48
    int i,j,x,y;
    int p;
    int min;
    int d;
    int L = 50;
    int L2 = L*L;
    for(x = 0; x < W; x++)
        for(y = 0; y < H; y++)
        {
            min = 255; // si Image est un tableau de unsigned char
            for (i = 0; i <= L; i++)
            {
               d = i*i;
               for(j = 0; j <= L; j++)
               {
                   if (d+ j*j > L2) break;
                   if(x+i<W)
                   {
                      if(y+j<W)
                      {
                         p = Image[x+i][y+j];
                         min = min > p ? p : min;
                      }
                      if(y-j>=0)
                      {
                         p=Image[x+i][y-j];
                         min = min > p ? p : min;
                       }
                   }
                   if(x-i>=0)
                   {
                      if(y+j<W)
                      {
                         p=Image[x-i][y+j];
                         min = min > p ? p : min;
                      }
                      if(y-j>=0)
                      {
                         p=Image[x-i][y-j];
                         min = min > p ? p : min;;
                      }
                   }
                }
     
            }
     
              image[x][y]=min;
        }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  13. #13
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    J'ai supprimé le tableau tri puisqu'il est inutile (il me semble) !
    Par ailleurs, il vaut mieux précalculer l'offset des points dans le disque.
    Parce que dans le code qui a été donné, ce que l'on fait pour (0,0) on le répète sans cesse de y en y et de x en x... ce qui représente une perte de temps énorme !

    Ce faisant, chez moi, ça divise le temps de calcul par 6 !

    A plus !

  14. #14
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut
    Salut à tous,

    Merci pour vos messages

    je vais tout essayer maintenant
    henderson à écrit:
    il faut précalculer les offsets pour chaque point sur le disque
    ma question va peut être te paraitre bizarre <les offsets> c'est quoi?

    A+

  15. #15
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut
    -2 plus grave, la dimension de tri est beaucoup trop faible et conduit presque à coup sûr à des dépassements pour d = 50. La dimension de sécurité devrait être de 4*d*d. Ceci peut expliquer des comportements bizarres pour d de l'ordre de 20 ou supérieur.
    Mille mercis en changeant la dimension de tri j'arrive à visualiser l'image pour d=50

  16. #16
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    En parlant d'offset, je voulais parler des coordonnées relatives pour chaque point du disque depuis un centre quelconque (x,y) sur ton image.
    On a donc bien à un moment donné x+i et y+j.
    Le fait de les précalculer revient également à limiter le nombre de points à ce qui est utile pour la surface du disque. C'est autant que le traitement n'aura pas à vérifier.
    Ton algo lui, calcule en permanence ces coordonnées relatives pour chaque cercle en (x,y) en vérifiant à chaque fois si un point d'une surface carré est celui d'un disque, d'où la lenteur du traitement.

    A plus !

  17. #17
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut


    Je vous remercie de tout coeur, grâce à vous mon problème est résolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Execution trés lente d'un executable JAR
    Par debana dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 07/06/2012, 14h29
  2. Réponses: 1
    Dernier message: 30/06/2008, 17h01
  3. Requête rapide après une 1ere execution / très lente avant
    Par nc_dvlp dans le forum Administration
    Réponses: 5
    Dernier message: 03/06/2008, 18h29
  4. Temps d'exécution très lent
    Par michelin123 dans le forum MATLAB
    Réponses: 14
    Dernier message: 20/11/2007, 15h17
  5. [VBA-E]temps d execution trop lent
    Par chmod777 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 08/03/2006, 15h10

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