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 :

rotation d'une matrice


Sujet :

C

  1. #1
    Futur Membre du Club
    Inscrit en
    Avril 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 21
    Points : 9
    Points
    9
    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 : 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
    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 é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
    - 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    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 : 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
    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
    Futur Membre du Club
    Inscrit en
    Avril 2007
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 21
    Points : 9
    Points
    9
    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 é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
    - 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    0 <=  col < (N+1)/2 (division entière)
    0 <= lg < Minimum ((N+1)/2, M)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  6. #6
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    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 éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    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 éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    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 éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    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 éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    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 éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    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 éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    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 éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    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 éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    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.

Discussions similaires

  1. rotation d'une matrice
    Par paladice dans le forum Langage
    Réponses: 1
    Dernier message: 02/12/2010, 16h41
  2. Réponses: 3
    Dernier message: 17/04/2009, 12h32
  3. Réponses: 3
    Dernier message: 21/09/2007, 17h28
  4. Rotation d'une matrice
    Par timtim2007 dans le forum Prolog
    Réponses: 8
    Dernier message: 25/04/2007, 21h17
  5. Réponses: 8
    Dernier message: 07/09/2006, 10h08

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