Lecture d'une image pixel par pixel en C
Répondre à la discussion
Affichage des résultats 1 à 18 sur 18

Lecture d'une image pixel par pixel en C



  1. #1
    invite1f0ed006

    Lecture d'une image pixel par pixel en C


    ------

    Bonjour à vous tous,

    Dans le but de réaliser un projet personnel, je souhaiterai avoir un programme qui me génère automatiquement un fichier remplis d'une matrice générée par le programme. A partir de n'importe quelle carte du monde en noire et blanc, je souhaite lire chaque pixel de ma carte et retranscrire la couleur dans mon fichier par l'intermédiaire de 0 et de 1. Ainsi un pixel noir de ma carte sera interprété par un 0 dans mon fichier et inversement.

    J'ai choisi de programmer en C (seul langage que je connaisse) et d'utiliser un code de traitement d'image (dilation d'une image) que j'ai modifié pour m'aider a commencer.
    A ce jour je pense avoir bien avancé, le programme tourne mais je suis surpris par mes résultats. En effet, a partir d'une image 200*100 j'obtiens plus de données que ce que je devrai. Ceci est peut etre du a certaine fonctionnalités du code que je n'ai pas comprise...

    Pouvez vous m'aider à interpréter mes résultats et si le coeur vous en dis à améliorer mon code pour que les valeurs trouvés correspondent.
    Merci d'avance.
    Ana

    -----
    Fichiers attachés Fichiers attachés

  2. #2
    JPL
    Responsable des forums

    Re : Lecture d'une image pixel par pixel en C

    Pour insérer du code dans le message la balise Code (#) de l'éditeur avancée permet de garder les indentations. C'est plus commode qu'un txt.
    Rien ne sert de penser, il faut réfléchir avant - Pierre Dac

  3. #3
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Code:
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include "BmpLib.h" // Cet include permet de manipuler des fichiers BMP
    
    
    
    
    
    #define BLANC 255
    
    #define NOIR 0
    
    
    
    
    
    DonneesImageRGB* make_matrix (DonneesImageRGB* image);
    
    //-------------------------------------------------------------------------
    
    
    
    int main(int argc, char **argv)
    
    {	 
    
        DonneesImageRGB* binaire2 = lisBMPRGB("binaire2.bmp");
    
        make_matrix(binaire2);    
    
    	return 0;
    
    }
    
    
    
    //-----------------------------------------------------------------------------------------------------------
    
    
    
    DonneesImageRGB* make_matrix (DonneesImageRGB* imageTEMP)
    
    {
    
        int i;  
    
        int P=0;  
    
        char word='A';
    
        // Copie image
    
        DonneesImageRGB* image = malloc(sizeof(DonneesImageRGB)); 
    
        image -> hauteurImage = imageTEMP -> hauteurImage;
    
        image -> largeurImage = imageTEMP -> largeurImage;
    
        image -> donneesRGB = malloc(sizeof(char) * image->largeurImage * image->hauteurImage * 3);
    
        
    
        for(i=0;i<image -> hauteurImage * image -> largeurImage *3;i++)
    
            image->donneesRGB[i]=imageTEMP->donneesRGB[i];
    
            
    
          
    
        // Initialisation
    
        DonneesImageRGB* imageStruct = malloc(sizeof(DonneesImageRGB));
    
        imageStruct -> hauteurImage = image -> hauteurImage;
    
        imageStruct -> largeurImage = image -> largeurImage;
    
        imageStruct->donneesRGB = malloc(sizeof(char) * imageStruct->largeurImage * imageStruct->hauteurImage * 3);
    
        
    
        
    
            // Type carre
    
            for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i++)
    
            {
    
                	if(image->donneesRGB[i]!=BLANC) 
    
                    	{
    
                        imageStruct->donneesRGB[i]=NOIR;    
    
                        word='0';
    
                        }                  
    
                    else
    
                    {
    
                        imageStruct->donneesRGB[i]=BLANC;
    
                        word='1';
    
                    }  
    
                    
    
                    // Fill in the matrix
    
                    FILE* fichier2=fopen("map.txt","a");	
    
                    	
    
                    
    
                    if (fichier2!=NULL)									
    
                        {
    
                         P=P+1;
    
                         fprintf(fichier2,"%c", word);  
    
                            if (P%201==0)
    
                            {
    
                            word='\n';
    
                            fprintf(fichier2,"%c", word);
    
                            }            	
    
                         fclose(fichier2);             									
    
                        }  		
    
            }       
    
        return(image);
    
    }
    
        
    
     
    
     
    
     
    
    //------------------------------------

  4. #4
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    Bonjour,

    En lisant ton code je remarque que tu ouvres, écris, fermes ton fichier à chaque tour de boucle : inefficace, il vaut mieux l'ouvrir avant la boucle, l'écrire dans la boucle et le fermer après la boucle.
    Ensuite tu manipules un fichier bitmap 24bit, un pixel est codé sur 3 octets chaque composante R,G et B étant codée sur 1 octet. Un pixel est blanc si les trois composantes valent 255 (je suppose que BLANC vaut 255). Un pixel est noir si ces trois composantes valent 0. Le code pour produire un fichier contenant 0 si le pixel est noir, 1 sinon devrait plus ressembler à :
    Code:
    //ici on ouvre le fichier
    for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i=i+3) {
      if ( (image->donneesRGB[i  ]==0) &&
           (image->donneesRGB[i+1]==0) &&
           (image->donneesRGB[i+2]==0) )
        word='0';
      else
        word='1';
      P=P+1
      fprintf(fichier2,"%c",word);
      // pour insérer un saut de ligne après 200 éléments
      if (P%200==0)
        fprintf(fichier2,"\n");
    }
    // ici on ferme le fichier
    Je suppose que tu n'as besoin du DonneesImageRGB* de retour ?
    Ton image bitmap est-elle réellement noir et blanc ou contient-elle des niveaux de gris ?

  5. A voir en vidéo sur Futura
  6. #5
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Bonjour Kwariz,

    Merci pour ta réponse. Je note d'interessantes remarques. En effet, j'ouvre et je ferme mon fichier à chaque tour, je dois perdre du temps de calcul à cause de ceci je pense.
    Ensuite j'ai testé mon code sur un fichier qui comporte 3 composantes au lieu d'une, ce qui n'est pas très malin de ma part car au final je vais utiliser une simple image noir et blanc. En conséquence je n'ai pas besoin de DonneesImageRGB* de retour et mon image sera réellement en noir et blanc.

    Merci encore
    Ana.

  7. #6
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    en fait ma question était plus de savoir si l'image binaire2.bmp contenait des niveaux de gris.

  8. #7
    Zartan

    Re : Lecture d'une image pixel par pixel en C

    Bonjour,

    Code:
    for(i=0;i<image -> hauteurImage * image -> largeurImage *3;i++)
    
            image->donneesRGB[i]=imageTEMP->donneesRGB[i];
    On peut utiliser

    Code:
    memcpy(image->donneesRGB, imageTEMP, image -> hauteurImage * image -> largeurImage *3) ;
    à la place.

    J'aime bien la réponse de kwariz à ce détail près :

    Code:
    if (P%200==0)
        fprintf(fichier2,"\n");
    Je propose :

    Code:
    if (P%( imageStruct -> largeurImage )==0)
        fprintf(fichier2,"\n");
    à la place.
    Dernière modification par Zartan ; 30/10/2012 à 18h48.

  9. #8
    Paraboloide_Hyperbolique

    Re : Lecture d'une image pixel par pixel en C

    Bonsoir,

    J'ai (il y a longtemps) réalisé un programme C++ lisant les données d'un fichier bitmap. Il faut faire attention au fait que ce type de fichier contient aussi une en-tête (header) reprenant notamment les dimensions de l'image et son format (couleur, niveaux de gris, compressé...)

    Je crois que le lien suivant (en anglais) peut vous aider à réaliser ce que vous cherchez: http://tipsandtricks.runicsoft.com/C...pTutorial.html

  10. #9
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Bonjour à nouveau,

    Je tiens à vous remercier pour votre aide car le code fonctionne à présent. Il peut bien sur être améliorer par ceux qui en aurait besoin, c'est pourquoi je vous le laisse à disposition. Je conseillerai notamment d'améliorer l'ouverture de fichier.

    En ce qui me concerne, ce code est suffisamment fonctionnel pour être conservé tel quel. Je noterai toutefois que je ne peux ouvrir que certains types d'images (en effet, quand je prends une image qui fonctionne et que je la coupe pour conserver une petite zone, j'observe un "segmentation fault" que je ne comprends pas.

    Merci encore pour votre soutien.
    Ana.




    Code:
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include "BmpLib.h" // Cet include permet de manipuler des fichiers BMP
    
    
    
    
    
    #define BLANC 255
    
    #define NOIR 0
    
    
    
    
    
    DonneesImageRGB* make_matrix (DonneesImageRGB* image);
    
    
    
    
    
    //-------------------------------------------------------------------------
    
    
    
    int main(int argc, char **argv)
    
    {	 
    
        DonneesImageRGB* binaire2 = lisBMPRGB("binaire2.bmp");
        make_matrix(binaire2);    
    
    	return 0;
    
    }
    
    
    
    //-----------------------------------------------------------------------------------------------------------
    
    
    
    DonneesImageRGB* make_matrix (DonneesImageRGB* imageTEMP)
    
    {
    
        int i;  
        int P=0;  
    
        char word='A';
    
        // Copie image
    
        DonneesImageRGB* image = malloc(sizeof(DonneesImageRGB)); 
    
        image -> hauteurImage = imageTEMP -> hauteurImage;
    
        image -> largeurImage = imageTEMP -> largeurImage;
    
        image -> donneesRGB = malloc(sizeof(char) * image->largeurImage * image->hauteurImage * 3);
    
        
    
        for(i=0;i<image -> hauteurImage * image -> largeurImage *3;i++)
    
            image->donneesRGB[i]=imageTEMP->donneesRGB[i];
    
            
    
          
    
        // Initialisation
    
        DonneesImageRGB* imageStruct = malloc(sizeof(DonneesImageRGB));
    
        imageStruct -> hauteurImage = image -> hauteurImage;
    
        imageStruct -> largeurImage = image -> largeurImage;
    
        imageStruct->donneesRGB = malloc(sizeof(char) * imageStruct->largeurImage * imageStruct->hauteurImage * 3);
    
        
    
        
    
           
    
    for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i=i+3) {
      if ( (image->donneesRGB[i  ]==0) &&
           (image->donneesRGB[i+1]==0) &&
           (image->donneesRGB[i+2]==0) )
        word='0';
      else
        word='1';
        FILE* fichier2=fopen("map.txt","a");
        	if (fichier2!=NULL)									
            {
     		 P=P+1;
     		 fprintf(fichier2,"%c",word);
      			if (P%( imageStruct -> largeurImage )==0)
        		fprintf(fichier2,"\n");// pour insérer un saut de ligne 
             fclose(fichier2); }
    	}        
    
        return(image);
    
    }

  11. #10
    Chanur

    Re : Lecture d'une image pixel par pixel en C

    Bonjour Anastasiadu83, et bienvenue sur Futura
    Citation Envoyé par Anastasiadu83 Voir le message
    quand je prends une image qui fonctionne et que je la coupe pour conserver une petite zone, j'observe un "segmentation fault" que je ne comprends pas.
    Je ne peux pas être certain que ton problème vienne de là, mais il y a une chose que tu n'as pas prise en compte : les lignes de fichiers BMP ont toujours une longueur multiple de 8 octets.
    En général, la largeur (en pixels) est multiple de 8 et tout va bien.
    Dans le cas contraire, des octets supplémentaires sont ajoutés à la fin de chaque ligne.
    Code:
    for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i=i+3)
    ne fonctionnera que si imageStruct -> largeurImage est multiple de 8.

    Une solution facile pour contourner ce problème est d'utiliser des BMP en 32 bits. Vue la taille actuelle des disques dur ...
    A+
    Dernière modification par Chanur ; 03/11/2012 à 17h40.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  12. #11
    invite0f0afca1

    Re : Lecture d'une image pixel par pixel en C

    Citation Envoyé par Chanur Voir le message
    Je ne peux pas être certain que ton problème vienne de là, mais il y a une chose que tu n'as pas prise en compte : les lignes de fichiers BMP ont toujours une longueur multiple de 8 octets.
    En général, la largeur (en pixels) est multiple de 8 et tout va bien.
    [CODE]
    for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i=i+3)
    Salut,

    Il me semble que c'est plutôt un multiple de 4. C'est vrai qu'avec les CPU 64 bits qui se généralisent, ce serait mieux d'avoir un alignement sur 8. Je suis plus trop sûr, mais je crois qu'il y a un champ dans le header qui définit le padding.

    En 32 bits, on a en plus un "alpha channel", qu'on utilise ou pas. L'intérêt, c'est de pouvoir lire chaque pixel en une seule instruction machine, donc un net gain de vitesse

  13. #12
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    Bonsoir,

    apparemment la fonction [codeinline]lisBMPRGB[/codeinline] gère ce genre de détails d'alignements et de padding (enfin je suppose). De plus la fonction proposée par Anastasiadu83 nécessite une grosse refonte comme redéfinir le prototype pour s'affranchir de la valeur de retour, passer un paramètre pour le nom du fichier (au minimum) et ne pas ouvrir/fermer le fichier à chaque tour de boucle. Apparemment Anastasiadu83 n'avait besoin que d'un truc rapide pour obtenir le fichier et rien de plus.

  14. #13
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Bonsoir,

    J'avance doucement dans mon projet et je me rends compte que tous mes fichiers sont retournés!
    J'ai finis par comprendre d'où cela vient, il semble qu'une image se lit de bas en haut et que mon fichier de haut en bas. Je souhaites donc a présent simplement renverser horizontalement mon fichier pour obtenir un fichier que je puisse facilement comparer

    J'ai donc changé cette ligne
    for(i=0;i<imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i=i+3) {
    par celle-ci
    //for(i=imageStruct -> hauteurImage * imageStruct -> largeurImage *3;i>0;i=i-3) {
    L'image est à présent retourné horizontalement, mais verticalement aussi! Ce que je ne voulais pas.

    Quelqu'un aurait il une idée simple? Pour remettre à l'endroit mon fichier svp?
    Merci d'avance.
    Ana

  15. #14
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    Bonjour,
    Il faut que tu comprennes la structure que tu utilises : tu définis un tableau 1D (un indice i) que tu interprètes comme un tableau 3D (3 indices x,y et composante). Pour te simplifier la vie, je ne peux que te conseiller d'écrire quelques fonctions comme celle qui à partir d'un indice i dans le tableau 1D te donne les 3 indices dans le tableau 3D, celle qui fait l'inverse. Si tu réussis à les écrire ce que tu cherches à faire devient trivial :
    Code:
    (for x=hauteur-1;x>=0;--x) // on parcours les lignes à l'envers
      for(y=0;y<largeur;++y) // on parcours les colonnes dans l'ordre
        for(c=0;c<3;++c) // on parcours les composantes RGB dans l'ordre
          i=transforme_3D_vers_1D(x,y,c);
          faire ce que tu veux avec tableau[i]
    ATTENTION AUX LIMITES : un tableau en C est indicé à partir de 0 : ta boucle proposée est fausse, compare la avec celle que je donne ci-dessus. Tu vois ton erreur ?

    Évidemment cette approche n'est pas optimisée, mais à mon avis elle te permettra de mieux visualiser ce que tu fais, de toute façon une optimisation prématurée est la source de tous les maux (Knuth je crois).

    Une fois que tu seras à l'aise avec les représentations, tu pourras éventuellement te passer de ces fonctions si le gain est réel.

  16. #15
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Merci pour cette réponse, j'ai réussi à intégrer les dernières corrections dû à mes erreurs de parcourt de boucles mais je pense que je dois peut être utiliser la valeur du c dans le calcul de i:

    Code:
    for (x=imageStruct -> hauteurImage-1;x>=0;--x) // on parcours les lignes à l'envers
    {
      for(y=0;y<imageStruct -> largeurImage;++y) // on parcours les colonnes dans l'ordre
      {
        for(c=0;c<3;++c) // on parcours les composantes RGB dans l'ordre
          i=y * x * 3 ;
          {
      if ( (image->donneesRGB[i  ]==0) &&
           (image->donneesRGB[i+1]==0) &&
           (image->donneesRGB[i+2]==0) )
        word='0';
      else
        word='1';
        FILE* fichier2=fopen("map2.txt","a");
        	if (fichier2!=NULL)									
            {
     		 P=P+1;
     		 fprintf(fichier2,"%c",word);
     		 //word=' ';
     		 //fprintf(fichier2,"%c",word);
      			if (P%( imageStruct -> largeurImage )==0)
        		fprintf(fichier2,"\n");// pour insérer un saut de ligne 
             fclose(fichier2); }
    	}       
    	}
    	}
    Conclusion, cette méthode semble être la solution à mes problèmes toutefois une erreur semble provenir de mon calcul de i.
    Je continue mes recherches...
    Merci encore de votre aide.
    Ana

  17. #16
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    Effectivement, la calcul de i n'est pas correct ... il devrait être dépendant de largeur et de hauteur et du nombre de compoasantes ... Essaye de faire un schéma du genre "en 3D ça ressemble à" :


    0 1 ... largeur
    0 (rgb) => (0,1,2) (rgb)=>(3,4,5) ... (largeur-3,largeur-2,largeur-1)
    1 (largeur,largeur+1,largeur+2) (largeur+3, largeur+4, largeur+5) (largeur+largeur-3, largeur+largeur-2,largeur+largeur1)
    ...
    n (n*largeur+0, n*largeur+1,n*largeur+2) ....
    ...

  18. #17
    invite1f0ed006

    Re : Lecture d'une image pixel par pixel en C

    Cela fonctionne!

    Code:
    for (x=imageStruct -> hauteurImage-1;x>=0;--x) // on parcours les lignes à l'envers
    {
      for(y=0;y<imageStruct -> largeurImage;++y) // on parcours les colonnes dans l'ordre
      {
        //for(c=0;c<3;++c) // on parcours les composantes RGB dans l'ordre
        
          {
          i=(x*imageStruct -> largeurImage + y) * 3 ;
      if ( (image->donneesRGB[i  ]==0) &&
           (image->donneesRGB[i+1]==0) &&
           (image->donneesRGB[i+2]==0) )
        word='0';

  19. #18
    kwariz

    Re : Lecture d'une image pixel par pixel en C

    Oui ... un dessin ça aide parfois, même si le mien était faux (désolé je ne viens que de m'en rendre compte maintenant).

Discussions similaires

  1. Pixel
    Par assianounette dans le forum Physique
    Réponses: 4
    Dernier message: 21/09/2012, 18h05
  2. pixel
    Par mathier dans le forum Physique
    Réponses: 6
    Dernier message: 10/10/2011, 06h53
  3. logiciel de mesure par pixel
    Par invite67c90ce3 dans le forum Logiciel - Software - Open Source
    Réponses: 6
    Dernier message: 25/09/2010, 10h46
  4. Pixel
    Par invitec095aaf5 dans le forum Mathématiques du collège et du lycée
    Réponses: 2
    Dernier message: 11/11/2008, 20h15
  5. pixel mort
    Par invite775c4143 dans le forum Matériel - Hardware
    Réponses: 6
    Dernier message: 21/06/2007, 15h12