Précédent   Forum du club des développeurs et IT Pro > C et C++ > C
C Forum d'entraide technique sur le langage C. Avant de poster -> F.A.Q. C, Avant de poster.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 05/05/2007, 15h56   #1
romain1986
Invité de passage
 
Inscription : 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;
		   }
	}
}
romain1986 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/05/2007, 19h07   #2
diogene
Responsable Modération
 
Avatar de diogene
 
Homme Patrick Gonord
Enseignant Chercheur
Inscription : juin 2005
Messages : 5 434
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 434
Points : 12 955
Points : 12 955
- 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.
diogene est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/05/2007, 02h18   #3
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 581
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 581
Points : 11 903
Points : 11 903
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/05/2007, 19h52   #4
romain1986
Invité de passage
 
Inscription : 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
romain1986 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/05/2007, 15h50   #5
diogene
Responsable Modération
 
Avatar de diogene
 
Homme Patrick Gonord
Enseignant Chercheur
Inscription : juin 2005
Messages : 5 434
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 434
Points : 12 955
Points : 12 955
- 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)
diogene est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 05h50   #6
kromartien
Membre émérite
 
Inscription : juin 2006
Messages : 1 117
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : juin 2006
Messages : 1 117
Points : 900
Points : 900
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'
kromartien est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 10h53   #7
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 581
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 581
Points : 11 903
Points : 11 903
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 13h53   #8
kromartien
Membre émérite
 
Inscription : juin 2006
Messages : 1 117
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : juin 2006
Messages : 1 117
Points : 900
Points : 900
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 ?
kromartien est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 14h41   #9
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 581
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 581
Points : 11 903
Points : 11 903
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 15h55   #10
kromartien
Membre émérite
 
Inscription : juin 2006
Messages : 1 117
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : juin 2006
Messages : 1 117
Points : 900
Points : 900
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)
kromartien est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 16h04   #11
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 581
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 581
Points : 11 903
Points : 11 903
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 16h22   #12
kromartien
Membre émérite
 
Inscription : juin 2006
Messages : 1 117
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : juin 2006
Messages : 1 117
Points : 900
Points : 900
? 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.
kromartien est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 16h36   #13
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 581
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 581
Points : 11 903
Points : 11 903
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2007, 16h41   #14
kromartien
Membre émérite
 
Inscription : juin 2006
Messages : 1 117
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : juin 2006
Messages : 1 117
Points : 900
Points : 900
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.
kromartien est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 05h07.


 
 
 
 
Partenaires

Hébergement Web