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++Builder Discussion :

Histogramme d'une image BMP en niveaux de gris?


Sujet :

C++Builder

  1. #1
    Membre régulier Avatar de bahiatoon
    Inscrit en
    Juillet 2006
    Messages
    169
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juillet 2006
    Messages : 169
    Points : 74
    Points
    74
    Par défaut Histogramme d'une image BMP en niveaux de gris?
    Salut à tous ,
    si il y'a une personne entre vous qui a implémenté le programme qui donne l'histogramme d'une image BMP en niveaux de gris je lui serai reconnaissante si elle me l'explique car je n'arrête pas d'essayer et je ne trouve toujours rien
    merci par anticipation

  2. #2
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Salut
    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
     
    #include <algorithm>
     
    // buffer pour stocker l'histogramme
    unsigned int histo[256];
     
    // on met ce buffer tout à 0
    std::fill(histo, histo + 256, 0);
     
    // on recupère le bitmap à partir de l'image dont on veut faire l'histogramme*
    // (pour éviter de se trainer le "Image1->Picture->")
    Graphics::TBitmap * bmp = Image1->Picture->Bitmap;
     
    // on parcourt chaque ligne de l'image
    for(int y = 0; y < bmp->Height; y++)
    {
               // on récupère un pointeur sur le 1er pixel de la ligne
               // (attention c'est pour des bitmaps 24 bits donc chaque pixel est un triplet BGR)
               unsigned char * bgr = (unsigned char*)bmp->ScanLine[y];
     
               // on parcourt chaque pixel de la ligne
               // (on va donc de 3 bytes en 3 bytes (de triplet BGR en triplet BGR)
               for(int x = 0; x < bmp->Width; x++, bgr += 3)
                      // on incrémente de 1 dans l'histo pour le niveau de gris correspondant 
                      // (en l'occurence on regarde la composante bleue)
                      histo[ *bgr ]++; 
    }
    Voilà, c'est pas testé et fait de tête donc n'hésite pas à répondre si y a une erreur. En outre ce code fonctionne pour des bmp en niveau de gris mais codés sur 24 bits. Si ton format est du 8 bits tu feras

    au lieu de


    Si tu as encore un autre format dis nous lequel.

    Flo.

  3. #3
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut ça marche ?
    Bonjour à tous.

    Quelqu'un peut-il me confirmer que cette fonction marche ?

    Moi j'ai le code suivant:

    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
    void ConstruitHistogramme(tImage *img, tHistogramme *histo)
    {
        int x, y,i,n;
        unsigned char * pix;
     
        histo->nbPixels = (img->dimX) * (img -> dimY);
        histo-> NInf=0;
        histo-> NSup=255;
     
        for(i=0;i<255;i++) 
        {
                histo->buffer[i]=0;
        }
     
     
        for(y=0;y<(img->dimY);y++)
          { 
     
                for(x=0;x<(img->dimX);x++,pix+=3)
                { 
                        pix=getPixel(x,y,img);
                        histo->buffer[*pix]++;
     
                }
          }
     
        histo-> niveauMoyen=((histo-> NInf) + (histo-> NSup))/2;	// Niveau de gris moyen
     
    }
    Avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    unsigned char* getPixel(int x,int y, tImage *src)
    {
             unsigned char* pixel;
             pixel= (unsigned char*) (src->buffer + (y * (src->dimY)) + x);
             return pixel;         
    }
    Merci de toute réponse. Bonne journée!

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Pas d'accord pour le bitmap 8 bits (au sens où il faut faire attention) !
    Dans ce que l'on montre on fait l'histogramme des index et non des niveaux de gris !
    L'algo est valable uniquement si on a la certitude que : index = R = G = B dans toute la portée de la boucle ce qui revient à avoir une palette dont les teintes y sont stockées dans cet ordre !

    C'est au cas où ... en fonction du contexte dans lequel on développe cet algo !!!

    Utiliser :
    - le type Byte en lieu et place de unsigned char !
    - ZeroMemory(Buffer, 256) pour le RAZ de l'histogramme !

    A plus !

  5. #5
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut ..à voir...
    Citation Envoyé par henderson Voir le message
    Salut !

    Pas d'accord pour le bitmap 8 bits (au sens où il faut faire attention) !
    Dans ce que l'on montre on fait l'histogramme des index et non des niveaux de gris !
    L'algo est valable uniquement si on a la certitude que : index = R = G = B dans toute la portée de la boucle ce qui revient à avoir une palette dont les teintes y sont stockées dans cet ordre !

    Utiliser :
    - le type Byte en lieu et place de unsigned char !
    - ZeroMemory(Buffer, 256) pour le RAZ de l'histogramme !

    A plus !
    Salut et merci pour ta réponse.
    Il est vrai que j'ai oublié de préciser que je travail sur des images BMP 24 bits et sur des niveaux de gris uniquement pour l'instant. Je commence juste à apprendre le traitement d'images.

    Pour l'instant l'erreur que j'obtenais c'est que mon buffer de l'histogramme ne contenait pas 256 niveaux de gris...

    Je vais en tout cas prendre en considération ta réponse et je te redirai ce qu'il en est...

    Merci et bonne journée!

  6. #6
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut
    Re bonjour! J'ai donc suivi tes conseils et voici ma nouvelle version:

    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
    void ConstruitHistogramme(tImage *img, tHistogramme *histo)
    {
        int x, y,i;
        int total=0;
        byte* pix;
     
        histo->nbPixels =(img->dimX) * (img -> dimY);
        histo-> NInf=0;
        histo-> NSup=255;
     
        ZeroMemory(histo->buffer, 256);
     
        for(y=0;y<(img->dimY);y++)
          { 
     
                for(x=0;x<(img->dimX);x++)
                { 
                        pix=getPixel(x,y,img);
                        histo->buffer[*pix]++;
                        if((histo->buffer[*pix])< (histo->NInf))
                        {
                                  histo->NInf=histo->buffer[*pix];
                        }
                        if((histo->buffer[*pix])> (histo->NSup))
                        {
                                  histo->NSup=histo->buffer[*pix];
                        }
                        total += histo->buffer[*pix];   
                }
          }
     
        histo-> niveauMoyen= total / histo->nbPixels;	// Niveau de gris moyen
     
    }
    malheureusement, j'obtiens toujours la même erreur qui me signale que mon mon histogramme ne contient pas 256 niveaux de gris. Si quelqu'un arrive à savoir pourquoi ce code ne fonctionne pas je serai ravi de lire ses suggestions.

    Merci pour toute réponse et bonne fin de journée !

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Pour commencer :

    histo-> NInf=0;
    histo-> NSup=255;
    Je pense que c'est le contraire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    histo-> NInf=255;
    histo-> NSup=0;
    A plus !

  8. #8
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par henderson Voir le message
    Salut !

    Pour commencer :



    Je pense que c'est le contraire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    histo-> NInf=255;
    histo-> NSup=0;
    A plus !
    Salut !
    J'ai pas compris pourquoi je dois initialiser dans ce sens et pas dans l'autre ?
    Peux-tu m'expliquer ?

    Merci ! Tchao !

  9. #9
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Parce que :
    (histo->buffer[*pix]) < (histo->NInf))
    Byte -> [0 ... 255]
    Si NInf est initialisé à 0, il n'y a guère d'espoir de récupérer quelque chose qui soit plus petit que 0 !
    Idem pour NSup initialisé à 255 (on ne trouvera jamais plus grand que 255) !

    Donc pour calculer les Min et Max au départ Min vaut Max et Max vaut Min :
    si valeur < Min alors Min = valeur (décroissante car tend vers 0)
    si valeur > Max alors Max = valeur (croissante car tend vers 255)

    A plus !

  10. #10
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut
    Ah ok ! Oui effectivement je n'avais pas vu ça comme ça ! Je vais donc tester tout ça en rentrant !

    Merci!

    Je te tiens au courant de mon avancement !

  11. #11
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut
    Rebonjour !
    Bon jai testé tout ça mais le problème reste toujours le même malgré les modifications que j'ai effectué suite à tes suggestions.

    J'ai toujours une erreur comme quoi mon histogramme ne contient pas 256 niveaux de gris.

    Je n'arrive toujours pas à comprendre pourquoi ce programme ne fonctionne pas...

    J'ai essayé de faire un test en rajoutant le code ci-dessous (après l'initialisation du buffer et en enlevant le parcours sur l'image ) mais rien y fait !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for(i=0;i<255;i++)
    {histo->buffer[i]=i;
    }
    Je suis toujours preneur de tes réflexions henderson. Merci en tout cas pour ton aide...

    Tchao !

  12. #12
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Si on a à faire à un simple tableau de bytes, l'histogramme se calcule sur l'ensemble sans que l'on ait besoin de tenir compte d'un quelconque matriçage en dehors de celui du tableau (1D) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int W = ...;
    int H = ...;
    int NbBytes = W * H;
    Byte *Buffer = new Byte[NbBytes]; 
    //On aura rempli le Buffer avec ... ???
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    UINT Histogramme[ 256 ];
    ZeroMemory(Histogramme, sizeof(UINT) * 256);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Byte Min = 255;
    Byte Max = 0;
    Byte niv;
    for(int i = 0; i < NbBytes; i++)
        {
        niv = Buffer[i];
        Histogramme[niv]++;
        if(niv < Min) Min = niv;
        if(niv > Max) Max = niv;
        }
     
    // ...
    // ...
    A plus !

  13. #13
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 42
    Points : 36
    Points
    36
    Par défaut
    OK merci je cerne mieux le problème.. en fait je ne dois pas remplir mon buffer de 256 niveaux de gris mais de H x L niveaux..

    Je vais voir ça.
    Merci pour ton aide et bonne soirée.
    Je retente ça dès que possible !

  14. #14
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Voici deux images *.BMP dans le ZIP.
    La palette de Image_A est une référentielle de gris (index = R = G = B).
    La palette de Image_B a été construite par permutations et les index ont été recalculés en conséquence (index != R=G=B ... sauf exception tout à fait aléatoire).
    Comme un bitmap 8 bits se dessine indirectement via sa palette, ces deux images sont identiques à l'écran.

    En rouge, l'histogramme de Image_A, en vert celui de Image_B qui ont été calculés à partir des index (ScanLine) et non à partir des niveaux de gris (voir HPALETTE et PALETTEENTRY du coté des API Windows).

    Sans commentaires !

    A plus !

    PS ... Désolé mais les pièces jointes sont parties ailleurs... (Là où sont toutes les vérités ??? ) !!!
    Si ça intéresse quelqu'un j'apporterai du code !

Discussions similaires

  1. Comment convertir une image RGB en niveaux de gris ?
    Par Imène_23 dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 07/08/2011, 14h50
  2. Histogramme d'une image BMP - Où mon code cloche-t-il?
    Par Killerboy dans le forum Débuter
    Réponses: 4
    Dernier message: 15/07/2009, 17h53
  3. [C#] Comment convertir une image bmp en jpg !!!
    Par vandeyy dans le forum Windows Forms
    Réponses: 5
    Dernier message: 13/07/2004, 20h37
  4. inserer une image BMP dans un fichier rtf
    Par Alice9 dans le forum MFC
    Réponses: 17
    Dernier message: 06/07/2004, 10h31
  5. [BPW] Impression d'une image BMP
    Par Alcatîz dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 21/08/2003, 14h34

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