Programme très lent

Signaler
Messages postés
3
Date d'inscription
jeudi 31 mai 2007
Statut
Membre
Dernière intervention
1 juin 2007
-
Messages postés
3
Date d'inscription
jeudi 31 mai 2007
Statut
Membre
Dernière intervention
1 juin 2007
-
   Bonjour a tous, je suis en projet et je developpe une petite application qui gère les modifications géométrique d'une image. J'utilise une interpolation bilinéaire.
   Cependant lors de l'éxécution d'une fonction d'agrandissement sur X et Y, la programme met presque une minute à renvoyer l'image agrandie.
   Quelqu'un pourrait-il m'aider ou me donner des piste pour rendre mon programme plus rapide ?
   Merci d'avance   

7 réponses

Messages postés
987
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
30 août 2012
24
Premierement si ce n'est pas deja fait, tu peux mettre ton code en release au lieu qu'il soit de debug.
Après faut voir dans ton algo, peut etre que tu peut simplifier les boucles, et essayer de limiter les calculs couteux en temps de mémoire ( par exemple au lieu de faire sqrt(10) tu stocke la valeur dans une variable au lieu d'utiliser a chaque fois la fonction).
Sans le code, c'est difficile de dire ce que tu peux modifier d'autre.
++ 
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
Salut,

Si ca ne te dérange pas d'utiliser les routines de windoze, tu peux utiliser StretchBlt (Ou StretchDIBits).

Pour avoir un beau résultat, il faut utiliser SetStretchBltMode avec HALFTONE en paramètre, sans oublier le SetBrushOrgEx comme précisé.
Messages postés
3
Date d'inscription
jeudi 31 mai 2007
Statut
Membre
Dernière intervention
1 juin 2007

Tout d'abord merci de prendre un peu de temps pour résoudre mon problème.
Mon code est déjà en release.
J'ai implémenté mon code de la façon la plus simple à mes yeux. Voici celui-ci:

void CImageBMP::agrandissement(CImageBMP& out, double factorX, double factorY)
{
 int imageType = m_iTypeImage;
 int HauteurIn = m_iHauteur;
 int LargeurIn = m_iLargeur;
 int HauteurOut = (int)ceil((double)HauteurIn * (double)factorY);
 int LargeurOut = (int)ceil((double)LargeurIn * (double)factorX);
 
 out.initialisation( HauteurOut,LargeurOut,imageType,-1);


 double iPrim;
 double jPrim;
 double x;
 double y;
 int flooriPrim;
 int floorjPrim;
 int ceiliPrim;
 int ceiljPrim;
 
   //parcour de l'image
  for (int i=0; i < HauteurOut; i++)
  {
   for (int j=0; j < LargeurOut; j++)
   {
    iPrim = (  ( i+1.0 ) / factorY  ) - 1.0;
    jPrim = (  ( j+1.0 ) / factorX  ) - 1.0;
     
    // interpolation bilineaire
    x = (double)iPrim - (int)iPrim; 
    y = (double)jPrim - (int)jPrim;
    
    flooriPrim = (int)(iPrim);
    floorjPrim = (int)(jPrim);
    ceiliPrim  = (int)(iPrim)+1;
    ceiljPrim  = (int)(jPrim)+1;

    //remplissage de l'image et gestion des bords
    if (((iPrim) <= HauteurIn-2)&&((jPrim) <= LargeurIn-2))
    {
     out (i, j) = (unsigned char) (m_ppucLigne[ flooriPrim ][ floorjPrim ] * ( (1-x) * (1-y) )  
      + m_ppucLigne[ flooriPrim ][ ceiljPrim  ] * ( (1-x) *   y   )
      + m_ppucLigne[ ceiliPrim  ][ floorjPrim ] * (   x   * (1-y) )
      +   m_ppucLigne[ ceiliPrim  ][ ceiljPrim  ] * (   x   *   y   ));  
    }
    else
    { 
     out (i, j) = 0;
    }      
   }
  }

Cette fonction permet l'agrandissement d'une image par des facteurs X et Y à l'aide d'une interpolation bilinéaire.
Mais lorsque je pose deux facteurs de 10, la fonction met presque une minute à me renvoyer la nouvelle image !!!
Pour moi, ce code est simplement deux boucles for imbriquée avec un calcul inséré.
Je ne vois pas les données que je pourrais stocker. 

 

 
Messages postés
987
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
30 août 2012
24
C'est normal que ce soit long si tu mets des grands facteurs sur des images assez grandes. La quantité d'informations à traiter devient forcément importante.  Tu pourrais peut etre essayer d'utiliser des threads qui travaillent chqu'un sur des parties de l'images, mais je ne suis pas sur que cela puisse te faire gagner beaucoup de temps.

++  
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
iPrim = ((i + 1.0) / factorY) - 1.0;
Pourquoi ce recalcul à chaque tour de j puisqu'il n'en dépend pas ???


jPrim = ((j + 1.0) / factorX) - 1.0;


Pour ces 2 calculs très lourds en cycles, il vaut mieux calculer au départ le pas d'incrémentation et faire une simple addition dans les boucles.

ciao...
BruNews, MVP VC++
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
5
D'utiliser des float au lieu des doubles, ca aiderait aussi.

De plus, quand tu fais ca:
    // interpolation bilineaire
    x = (double)iPrim - (int)iPrim; 
    y = (double)jPrim - (int)jPrim;
    
    flooriPrim = (int)(iPrim);
    floorjPrim = (int)(jPrim);
    ceiliPrim  = (int)(iPrim)+1;
    ceiljPrim  = (int)(jPrim)+1;

Tu convertis 3 fois de double en int la meme quantité, alors que tu pourrais le faire une seule fois:
    // interpolation bilineaire

    flooriPrim = (int)(iPrim);


    floorjPrim = (int)(jPrim);


    ceiliPrim  = flooriPrim +1;


    ceiljPrim  = floorjPrim +1;


    x = (double)iPrim - flooriPrim ; 

    y = (double)jPrim - floorjPrim ;

    

Mais c'est en passant en float, que tu vas gagner le plus. Le float te permettrait aussi d'utiliser le GPU pour faire ca. Il serait content de pouvoir t'aider :) il est spécialiser la dedans. Il te le ferait en 1/10sec ce calcul pour peu que ton image ne soit pas trop grande. Dans le cas contraire, il faudrait la découper et l'envoyer a la carte video par morceau.
Messages postés
3
Date d'inscription
jeudi 31 mai 2007
Statut
Membre
Dernière intervention
1 juin 2007

   Merci beeaucoup de tous ces renseignements  je fais un essai et vous tiens au courant !!!