Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 14 sur 14
  1. #1
    Invité de passage
    Inscrit en
    avril 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : avril 2007
    Messages : 21
    Points : 0
    Points
    0

    Par défaut rotation d'une matrice

    Bonjour voici ma fonction qui a pour but de faire la rotation de ma matrice! C'est à dire que je dois faire la rotation d'une image de format .ppm! Mais avec mon code ci dessous j'arrive à faire la rotation mais ce n'est que la moitié de l'image qui est tourné de 90°! Et je ne comprends pas pourquoi!
    //colonne signifie le nombre de colonnes
    //ligne signifie le nombre de lignes

    Je n'ai pas tout mon code mtn ici sur cette rubrique car cela prendrai trop de place mais j'espère que vous avez assez d'informations pour comprende mon problème et pouvoir m'aider! Le code pour ecrire fonctionne car j'ai deja réaliser d'autres fonctions et cela va tres bien! Merci d'avance

    le code de ma fonction:

    Code :
    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
    struct pixel 
    {
    	int R;
    	int G;
    	int B;
    };
     
    struct pixel temp[MAX][MAX];
     
    void rotation (struct pixel mat[MAX][MAX],int colonne, int ligne)
    {
    	int i,j;
    	for(i=0;i<=ligne;i++) 
          {
                for(j=colonne;j>=1;j--) 
                {
    	            temp[j][i].R =mat[i][j].R;
    	            temp[j][i].G =mat[i][j].G; 
    	            temp[j][i].B =mat[i][j].B;
    	        }
    	  } 
    	for(i=1;i<=(ligne);i++) 
        {
    	   for(j=1;j<=(colonne);j++) 
    	       { 
    		       mat[i][j].R = temp[i][j].R;  
    		       mat[i][j].G = temp[i][j].G; 
    		       mat[i][j].B = temp[i][j].B;
    		   }
    	}
    }

  2. #2
    Expert Confirmé Sénior

    Homme Profil pro Patrick Gonord
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 664
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrick Gonord
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 664
    Points : 13 489
    Points
    13 489

    Par défaut

    - Même si le résultat y ressemble, ce n'est pas une rotation de 90° que tu as programmé puisque tous les pixels pour lequel i=j n'ont pas bougé. Une rotation laisse un seul point invariant : le centre de rotation
    - Pour ton problème qui doit se produire si l'image n'est pas carrée,
    Code :
    1
    2
    3
    4
    5
    6
    for(i=0;i<=ligne;i++) 
                for(j=colonne;j>=1;j--) 
                {
    	            temp[j][i].R =mat[i][j].R;
                         ....
    	        }
    fait que si l'image d'origine a ligne lignes et colonne colonnes, dans temp, elle a colonne ligne et ligne colonnes
    Code :
    1
    2
    3
    4
    5
    6
    	for(i=1;i<=(ligne);i++) 
        {
    	   for(j=1;j<=(colonne);j++) 
    	       { 
    		       mat[i][j].R = temp[i][j].R;
                           ....
    copie dans l'image d'origine le contenu de temp de ligne lignes et colonne colonnes, donc pas le contenu "utile".
    Par exemple, si l'image a 5 lignes et 10 colonnes, temp a 10 lignes et 5 colonnes " utiles" (les colonnes suivantes de temp sont à zéro puisque temp est semble t-il en global) et je recopie 5 lignes et 10 colonnes de temp dans l'image. L'image finale n'est modifiée que pour le carré de 5 lignes et 5 colonnes , le reste est noir.

    si l'image a 10 lignes et 5 colonnes, temp a 5 lignes et 10 colonnes " utiles" (les lignes suivantes de temp sont à 0) et je recopie 10 lignes et 5 colonnes de temp dans l'image. L'image finale n'est modifiée que pour le carré de 5 lignes et 5 colonnes , les 5 colonnes suivantes sont celles de l'image originale et le reste est noir.

  3. #3
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 183
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 183
    Points : 14 353
    Points
    14 353

    Par défaut

    pour une rotation d'iage, TOUJOURS partir du pixel résultat et calculer le pixel d'origine, à cause des erreurs d'arrondi qui donneront dans l'image résultante des pixels noirs, et donc des effets de moirés.

    De plus, ton image résultante n'aura pas les mêmes dimensions, et aura des angles noirs (sauf si tu coupes après coup).

    Donc, primo, calculer les coordonnées limites (par calcul de la rotation des sommets, puis min/max des (x,y) pour ces 4 points.

    Secondo, il est plus pratique de faire une fonction qui effectue la rotation.

    Tertio, par conséquent, il faut écrire, pour effectuer une rotation Angle de l'image originale IM1, pour un résultat dans IM2 :

    Code :
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
     
    /*
     * Fonction de rotation
     */
    static void RotateInteger ( int Xc, int Yc, int Xin, int Yin, double Angle, 
                                         int *Xout, int *Yout ) 
    {
      *Xout = Xc + (int)(((Xin - Xc) * cos(Angle)) + ((Yin - Yc) * sin(Angle))) ;
      *Yout = Yc + (int)(- ((Xin - Xc) * sin(Angle)) + ((Yin - Yc) * cos(Angle))) ;
    }
     
    /* 
     * Rotation d'une image
     */
    int RotateImage ( unsigned char *IM1, int Dimx1, int Dimy1, double Angle,
                             unsigned char **IM2, int *Dimx2, int *Dimy2 )
    {
    int                  i, j ; /* Indices de boucle */
    int                  x1, y1 ; /* Pour les coordonnées dans l'image initiale */
    int                  x[4], y[4] ;  /* Pour calculer les limites de la nouvelle image */
    int                  xc1, yc1, xc2, yc2 ;  /* Coordonnées du centre */
    int                  xmin, xmax=0, ymin, ymax=0 ;
     
     
    /* Calcul du centre */
     
    xc1 = Dimx1/2 ;
    yc1 = Dimy1/2 ;
     
     
    /* Calcul des limites */
     
    RotateInteger ( xc1, yc1, 0, 0, Angle, &x[0], &y[0] );
    RotateInteger ( xc1, yc1, Dimx1, 0, Angle, &x[1], &y[1] );
    RotateInteger ( xc1, yc1, 0, Dimy1, Angle, &x[2], &y[2] );
    RotateInteger ( xc1, yc1, Dimx1, Dimy1, Angle, &x[3], &y[3] );
     
    xmin = Dimx1 ;
    ymin = Dimy1 ;
     
    for ( i = 0 ; i < 4 ; i++ )
      {
         if ( x[i] < xmin )
            xmin = x[i] ;
         if ( x[i] > xmax )
            xmax = x[i] ;
         if ( y[i] < ymin )
            ymin = y[i] ;
         if ( y[i] > ymaw )
            ymax = y[i] ;
      }
     
    *Dimx2 = xmax - xmin + 1 ;
    *Dimy2 = ymax - ymin + 1 ;
     
     
    /* Allocation du buffer pour l'image resultat */
     
    *IM2 = calloc ( ((*Dimx2)*(*Dimy2)), sizeof(unsigned char) );
    if ( *IM2 == NULL )
      {
         *Dimx2 = 0 ;
         *Dimy2 = 0 ;
         return ERROR ;  
      }
     
     
    /* Calcul du centre image 2 */
     
    xc2 = *Dimx2/2 ;
    yc2 = *Dimy2/2 ;
     
    /* Remplissage du buffer */
     
    for ( i = 0 ; i < *Dimy2 ; i++ )
        for ( j = 0 ; j < *Dimx2 ; j++ )
          {
              RotateInteger ( xc2, yc2, j, i, -Angle, &x1, &y1 );
     
     
              /* Elimination des points qui tomberaient en dehors de IM1 */
     
              if ( ((int)fabs((double)(x1-xc)) > xc) || 
                   ((int)fabs((double)(y1-yc) > yc) )
                 continue ;
     
     
              /* Remplissage */
     
              (*IM2)[i*(*Dimx2)+j] = IM1[y1*Dimx1+x1] ;
          }
     
    return SUCCESS ;
    }
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  4. #4
    Invité de passage
    Inscrit en
    avril 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : avril 2007
    Messages : 21
    Points : 0
    Points
    0

    Par défaut bonjour

    Tout d'abord merci à vous deux de votre aide! Et bien mon problème est que nous avons vu pour le moment que tres peu de foncttionalités et methodes pour definir une fonction et algorithme! Pour cela je ne comprends pas du tout le dernier là! Désolé et j'aurais du mal à l'expliquer à mon professeur! :S Mais si la 1ère personnne saurais m'aider d'avantage pour restructurer ma fonction j'en serais tres reconnaissant! MERCI

  5. #5
    Expert Confirmé Sénior

    Homme Profil pro Patrick Gonord
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 664
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrick Gonord
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 664
    Points : 13 489
    Points
    13 489

    Par défaut

    - Pour une rotation de 90°(sens direct, inverse des aiguilles d'une montre) , le pixel de coordonnées (colonne = col, ligne = lg) doit se déplacer en (colonne = lg, ligne = N-1-col). (N = nombre de colonnes de l'image)
    - Pour une rotation de 90°(sens inverse, sens des aiguilles d'une montre) , le pixel de coordonnées (colonne = col, ligne = lg) doit se déplacer en (colonne = M-1-lg, ligne = col). (M = nombre de lignes de l'image)
    - L'image après rotation est de dimension M colonnes x N lignes

    - Tu utilises un tableau intermédiaire dans ton programme. Ce n'est pas obligatoire : La rotation peut se faire sur place, sans tableau intermédiaire MxN , mais nécessite de traiter simultanément 4 points : En rotation de sens direct
    Code :
    1
    2
    3
    4
    5
    6
    (col,lg) ->  (lg, N-1-col) -> (N-1-col, N-1-lg) -> (N-1-lg, col)
    Temp <- Point(col,lg)
    Point(col,lg) <- Point(N-1-lg, col)
    Point(N-1-lg, col) <- Point(N-1-col, N-1-lg)
    Point(N-1-col, N-1-lg) <- Point(lg, N-1-col)
    Point(lg, N-1-col) <- Temp
    Comme la rotation ne doit pas se produire plusieurs fois pour un même point, col et lg parcourent seulement 1/4 du plan NxN :
    Code :
    1
    2
    0 <=  col < (N+1)/2 (division entière)
    0 <= lg < Minimum ((N+1)/2, M)

  6. #6
    Membre émérite
    Inscrit en
    juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 29

    Informations forums :
    Inscription : juin 2006
    Messages : 1 116
    Points : 976
    Points
    976

    Par défaut

    En algèbre linéaire on parle de 'matrice transposée', c'est ce qui correspond à une rotation de 90 degrés dans le sens horaire, additionnée d'un retournement 'miroir' horizontal (symétrie horizontale). Voilà pour la recherche google 'théorie'

  7. #7
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 183
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 183
    Points : 14 353
    Points
    14 353

    Par défaut

    je signale juste que je donnais la rotation générale d'une image....

    Et sans buffer intermédiaire....
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  8. #8
    Membre émérite
    Inscrit en
    juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 29

    Informations forums :
    Inscription : juin 2006
    Messages : 1 116
    Points : 976
    Points
    976

    Par défaut

    Est-ce que ça veut dire que chaque point de l'image est indexé par ses coordonnées cartésiennes et non par ses coordonnées dans un tableau C à deux dimensions ?

  9. #9
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 183
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 183
    Points : 14 353
    Points
    14 353

    Par défaut

    que veux-tu dire par là ?
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  10. #10
    Membre émérite
    Inscrit en
    juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 29

    Informations forums :
    Inscription : juin 2006
    Messages : 1 116
    Points : 976
    Points
    976

    Par défaut

    En fait comme vous parliez d'algorithme général de rotation : la rotation "générale" pour moi serait celle d'angle quelconque, pour laquelle le carré (l'image) prendrait place dans un cercle.

    Comme l'image est une matrice au sens strict, c'est difficile de faire des rotations pour un angle quelconque. La rotation de 90° serait celle où les lignes viennent prendre les places des colonnes, mais c'est limité car la rotation ne prend effet que pour des valeurs d'angle de rotation bien déterminée. La rotation d'angle quelconque doit utiliser une autre indexation, une indexation spatiale.

    C'est comme sous paint : un trait de largeur 1 pixel ne sera plus lissé si on lui fait prendre une orientation de 10° par rapport à l'horizontale. Donc j'ai du mal à imaginer la construction d'une image qui aurait effectuée une rotation d'angle quelconque si elle ne prenait pas place dans un repère plus vaste

    (rotation de la matrice principale située dans une matrice plus vaste composée de zéros en calculant les déplacements par des formules trigonométriques comme celles que vous utilisez dans votre code, ce qui implique l'utilisation d'un repère cartésien en x, y pour les déplacements)

  11. #11
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 183
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 183
    Points : 14 353
    Points
    14 353

    Par défaut

    Citation Envoyé par kromartien
    En fait comme vous parliez d'algorithme général de rotation : la rotation "générale" pour moi serait celle d'angle quelconque, pour laquelle le carré (l'image) prendrait place dans un cercle.
    Je ne comprend pas du tout ce que tu veux dire..

    La rotation présentée ci-dessus est une rotation de n'importe quel angle, de 0 à 360 degrés, centrée au centre de l'image intiale.

    Comme le résultat de la rotation d'une matrice sera un paralléllipède, il sera tronqué suivant l'angle si on garde la dimension originale, ou au contraire si on calcule (comme je le fais dans le code ci-desus) les nouvelles dimensions, il y aura du noir à certains endroits (coins noirs plus ou moins grands).

    Citation Envoyé par kromartien
    (rotation de la matrice principale située dans une matrice plus vaste composée de zéros en calculant les déplacements par des formules trigonométriques comme celles que vous utilisez dans votre code, ce qui implique l'utilisation d'un repère cartésien en x, y pour les déplacements)
    Le repère est forcément cartésien puisqu'une image/matrice est un rectangle défini par (N,M) et donc un point a une coordonnée rectangulaire (x,y).
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  12. #12
    Membre émérite
    Inscrit en
    juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 29

    Informations forums :
    Inscription : juin 2006
    Messages : 1 116
    Points : 976
    Points
    976

    Par défaut

    ? Juste qu'un carré qui tourne sur son centre de gravité tient dans un cercle. Il faut prévoir des pixels en plus suivant mon idée.

    en fait vous déplacez les pixelsvers la gauche par exemple pour les points en dessous du centre du carré, et vers la droite pour les points au dessus du centre du carré, c'est à dire vous étirez les sommets opposés d'après ce que j'ai compris, puis vous tronquez les bords pour que l'ensemble forme à nouveau une image carrée ? Oui, le nombre de pixels est réduit à ce moment.

    un parallélépipède est un volume de l'espace, un "pavé". un parallélogramme est un polygone dont les côtés opposés sont parallèles deux à deux. Je crois que vous vouliez parler d'un parallélogramme.

  13. #13
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 183
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 183
    Points : 14 353
    Points
    14 353

    Par défaut

    Citation Envoyé par kromartien
    un parallélépipède est un volume de l'espace, un "pavé". un parallélogramme est un polygone dont les côtés opposés sont parallèles deux à deux. Je crois que vous vouliez parler d'un parallélogramme.
    oui absolument... Faute d'inattention..

    Par contre, pour le reste :

    Citation Envoyé par kromartien
    Juste qu'un carré qui tourne sur son centre de gravité tient dans un cercle. Il faut prévoir des pixels en plus suivant mon idée.
    c'est ce qui est fait, pusique je calcule la nouvelle dimension en faisant tourner les 4 sommets et calculant les mix/max résultants en X, et en Y.

    Mais avoir une image circulaire... Jamais vu un buffer étant circulaire, à moins de n'avoir qu'une liste chaînée de points.

    Citation Envoyé par kromartien
    en fait vous déplacez les pixelsvers la gauche par exemple pour les points en dessous du centre du carré, et vers la droite pour les points au dessus du centre du carré, c'est à dire vous étirez les sommets opposés d'après ce que j'ai compris, puis vous tronquez les bords pour que l'ensemble forme à nouveau une image carrée ? Oui, le nombre de pixels est réduit à ce moment.
    Pas du tout, simplement je ramène la rotation au centre de l'image..

    Il n'y a aucune translation, uniquement une rotation... Mais comme justement la dimension change, il faut tout faire par rapport au centre (nouveau et ancien).
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #14
    Membre émérite
    Inscrit en
    juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 29

    Informations forums :
    Inscription : juin 2006
    Messages : 1 116
    Points : 976
    Points
    976

    Par défaut

    D'accord ...

    Je disais cercles pour restreindre. Je sais qu'il n'est pas possible d'avoir des buffers circulaires. Les pavés empilés tiennent moins de place que les billes .

    Pour le repère cartésien, je voulais surtout parler d'un repère étendu, donc d'un buffer qui n'aurait pas strictement la taille de l'image, sans quoi on ne peut faire que des rotations de 90°, et encore avec des matrices (image) carrées.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •