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 :

transformée de Census


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut transformée de Census
    je cherche à coder la transformée de Census avec C

    En effet,Je prends une image , j'ajoute des 0 aux bords pour avoir des fenêtres 3x3 complets. je prends chaque bloc, je compare la valeur du voisinage du pixel central ( pixel à apparier), si c'est inférieur la valeur sera 1 et si c'est supérieur donc c'est zéro. puisqu'il y a 8 voisins, j'aboutis à un vecteur de 8 valeurs binaires

    prière de m'aider

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Tu utilises quelle librairie pour charger ton image ?

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut
    j'utilise la bibliothèque SDL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ImageDroite = SDL_LoadBMP("lacD.bmp");

  4. #4
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Dans la SDL_SURFACE tu peux récupérer le pointeur sur l'image chargée. Ensuite tout dépend du format de l'image au départ.
    Si on part du principe que tu travailles avec une image codée sur 24 bits (3 couleurs) Chaque "paquet" de 3 octets représente un pixel (codé sous la forme BGR et non RGB). À partir de là ce n'est qu'une petite gymnastique mathématique pour obtenir des coordonnées cartésiennes pour chaque pixel.

    Où est exactement ton problème ?

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut
    si je prends l'image en niveau de gris, comment prendre un voisinage 3*3 ? comment ajouter les 0 à la frontière et enfin après les comparaisons comment enregistrer les valeurs des 8 cases dans un seul vecteur pour chaque pixel de l'image de départ ?
    et merci bien

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Donc si ton image est en niveau de gris on considère que chaque pixel est codé sur un seul octet.

    La structure de la SDL_SURFACE (ici) te donne accès au pointeur void *pixels;. Ce pointeur correspond au premier octet du tableau de l'image décompressée en mémoire.

    Ainsi pixel[0] te donne accès au premier octet de l'image (en haut à gauche).

    Pour pouvoir ajouter des 0 à la frontière tu ne pourras pas le faire directement avec ce pointeur. Il va te falloir déterminer et allouer un nouveau tableau qui aura la bonne taille dans lequel tu vas recopier l'original avec les 0 supplémentaires nécessaires.

    Remarque :

    Dans ce nouveau tableau tu pourras affecter directement le résultat de ton calcul pour chaque matrice 3x3.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut
    pourquoi on considère que chaque pixel est codé sur un octet ?
    je veux prendre chaque pixel un bit et le voisinage du pixel pris est composé de 8 pixels donc chacun un bit et par suite ils forment un octet .
    je cherche alors comment prendre ce voisinage pour former un seul octet

  8. #8
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Ah ! C'est différent alors. Ton image est en noir et blanc si je te suis bien. Un octet correspond à 8 pixels, c'est ca ?

    En même temps je ne connais pas d'image codée de cette manière. Maintenant ca peut sûrement exister...

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut
    oui même si mon image de départ est couleur je la converti en niveau de gris puis je travaille
    donc comment procéder SVP ?

  10. #10
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Excuse-moi mais je ne suis pas sûr que chaque pixel soit codé sur un bit ! Puisque tu me dis qu'au départ ton image est en couleur puis que tu la convertis en niveau de gris j'ai bien peur que chaque pixel soit codé sur un octet (voir 3 d'ailleurs).

    Es-tu vraiment sûr du format avant d'aller plus loin ?

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2013
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2013
    Messages : 221
    Points : 31
    Points
    31
    Par défaut
    En effet c'est la transformée de Census : C'est une forme de transformation locale non-paramétrique (ie repose sur l'ordre relatif des valeurs d'intensité locales, et non pas sur l'intensité se Valeurs) utilisé dans le traitement d'image pour cartographier les valeurs d'intensité des pixels dans une fenêtre carrée , capturant ainsi la structure d'image . La valeur d'intensité de pixel du centre, est remplacé par la chaîne de bits composé d'ensemble de comparaisons booléennes telles que, dans une fenêtre carrée, se déplaçant de gauche à droite,

    Si (CurrentPixelIntensity <CentrePixelIntensity) booléen bit = 0
    si non bit booléen = 1

    Pour chaque comparaison, le bit est déplacé vers la gauche, formant une chaîne de 8 bits pour une fenêtre de recensement de la taille de 3 x 3 .

  12. #12
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Bon tu peux travailler en premier lieu sur un octet par pixel. Une fois que tu auras initialisé tous les octets à 1 ou à 0 dans ton nouveau tableau il te "suffira" de lire ce nouveau tableau pour créer de nouveaux octets en fonction.

    Pour résumé voila à peu prés les étapes à suivre :
    • Déclarer un nouveau tableau d'une taille permettant la division par 3
    • Initialiser ce nouveau tableau en fonction de chaque matrice de l'image originale
    • Lire le nouveau tableau initialisé pour le convertir en bit puis en octet. Le résultat pourra lui aussi être inscrit dans un tableau final. (Pas sûr que je sois très clair sur ce coup là)


    Ce que tu peux déjà faire c'est de nous montrer le code qui tu as écrit étape par étape. On pourra alors mieux t'aider sur les problèmes que tu rencontres.

  13. #13
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    En ce moment je travaille sur de la manipulation de pixel pour mon projet open source MFNode.

    Ne connaisant pas la transformée de Census, j'ai trouvé un code C++ ici :

    http://hangyinuml.wordpress.com/2012...mplementation/

    Ici il y a un code Matlab :

    http://siddhantahuja.wordpress.com/2...ge-processing/

    Dans le code Matlab, l'image est d'abord transformée en grayscale, mais pas dans le premier code C++ (bizarre).

    Je n'ai pas OpenCV chez moi, alors j'ai essayé de transcrire le code en Win32. Ce n'est pas du C, mais du C++/Win32 (mais ce code est facilement transposable en C pur). Le code gère une image bmp en rgb24. Ce code ne gère pas les erreurs...

    Cela ne marche pas, même en définissant GRAY_SCALE_BEFORE. Je n'ai pas les nuances de gris. Par contre l'algo fonctionne, je pense (au vu de l'image résultante).

    A creuser...

    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
     
     
    //-----------------------------------------------------------------------------------------------
    // Main.cpp
    //-----------------------------------------------------------------------------------------------
    #include <windows.h>
    #include <math.h>
     
    //#define GRAY_SCALE_BEFORE
     
    #define INPUT_FRAME_WIDTH         640
    #define INPUT_FRAME_HEIGHT        480
     
    #define BMP_SIZE_HEADER 54
     
    #define INPUT_FRAME_WIDTH_RGB24   (INPUT_FRAME_WIDTH * 3)
    #define TOTAL_FRAME_SIZE          (INPUT_FRAME_WIDTH_RGB24 * INPUT_FRAME_HEIGHT)
    #define INPUT_FILE_STRING         L"C:\\projet\\media\\rgb24\\imageBmp.bmp"
    #define OUTPUT_FILE_STRING         L"C:\\projet\\media\\rgb24\\Census.bmp"
     
    void CreateBmpFile(BYTE**, const UINT);
     
    // I = (R + G + B) / 3
    // Gray scale intensity = 0.333R + 0.333G + 0.333B
    // Gray scale intensity = 0.30R + 0.59G + 0.11B
    // gray = (0.299*r + 0.587*g + 0.114*b);
    // INT gray = ceil(0.3*R + 0.59*G + 0.11*B);
     
    void main(){
     
    		HANDLE hFileInPut = INVALID_HANDLE_VALUE;
    		DWORD dwRead;
    		DWORD dwFileSize;
    		BYTE* pDataIn = NULL;
    		BYTE* pTmp;
     
    		BYTE** pDataInCensus = NULL;
    		BYTE** pDataOutCensus = NULL;
     
    		hFileInPut = CreateFile(INPUT_FILE_STRING, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
     
    		dwFileSize = GetFileSize(hFileInPut, NULL);
     
    		pDataIn = new BYTE[dwFileSize];
     
    		ReadFile(hFileInPut, (LPVOID)pDataIn, dwFileSize, &dwRead, 0);
     
    		pDataInCensus = new BYTE*[INPUT_FRAME_HEIGHT];
    		pDataOutCensus = new BYTE*[INPUT_FRAME_HEIGHT];
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				pDataInCensus[i] = new BYTE[INPUT_FRAME_WIDTH_RGB24];
    				pDataOutCensus[i] = new BYTE[INPUT_FRAME_WIDTH_RGB24];
    		}
     
    		pTmp = pDataIn + BMP_SIZE_HEADER;
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				memcpy(pDataInCensus[i], pTmp, INPUT_FRAME_WIDTH_RGB24);
    				pTmp += INPUT_FRAME_WIDTH_RGB24;
    		}
     
    		#ifdef GRAY_SCALE_BEFORE
     
    		int iGrayScale;
    		BYTE r;
    		BYTE g;
    		BYTE b;
     
    		// GrayScale
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				pTmp = pDataInCensus[i];
     
    				for(int j = 0; j < INPUT_FRAME_WIDTH_RGB24; j += 3){
     
    						r = pTmp[0];
    						g = pTmp[1];
    						b = pTmp[2];
     
    						//iGrayScale = static_cast<int>(floor((0.3f * r + 0.59f * g + 0.11f * b) + 0.5f));
    						iGrayScale = static_cast<int>((r + g + b) / 3.0f);
     
    						pTmp[0] = static_cast<BYTE>(iGrayScale);
    						pTmp[1] = static_cast<BYTE>(iGrayScale);
    						pTmp[2] = static_cast<BYTE>(iGrayScale);
     
    						pTmp += 3;
    				}
    		}
     
    		#endif
     
    		unsigned int census = 0;
    		unsigned int bit = 0;
    		int m = 3;
    		int n = 3;//window size
    		int i,j,x,y;
    		int shiftCount = 0;
     
    		for(x = m / 2; x < INPUT_FRAME_HEIGHT - m / 2; x++){
     
    				for(y = n / 2; y < INPUT_FRAME_WIDTH_RGB24 - n / 2; y++){
     
    						census = 0;
    						shiftCount = 0;
     
    						for(i = x - m / 2; i <= x + m / 2; i++){
     
    								for(j = y - n / 2; j <= y + n / 2; j++){
     
    										//skip the center pixel
    										if(shiftCount != m * n / 2){
     
    												census <<= 1;
     
    												//compare pixel values in the neighborhood
    												if(pDataInCensus[i][j] < pDataInCensus[x][y])
    														bit = 1;
    												else
    														bit = 0;
     
    												census = census + bit;
    										}
     
    										shiftCount++;
    								}
    						}
     
    						pDataOutCensus[x][y] = census;
    				}
    		}
     
    		CreateBmpFile(pDataOutCensus, TOTAL_FRAME_SIZE);
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				delete[] pDataInCensus[i];
    				delete[] pDataOutCensus[i];
    		}
     
    		delete[] pDataInCensus;
    		delete[] pDataOutCensus;
    		delete[] pDataIn;
    }
     
    void CreateBmpFile(BYTE** ppData, const UINT uiFrameSize){
     
    		HANDLE hFile = INVALID_HANDLE_VALUE;
    		DWORD dwWritten;
     
    		BYTE header24[54] = {0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
    		                     0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    																	  				0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    																			  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
     
    		DWORD dwSizeFile = TOTAL_FRAME_SIZE;
    		dwSizeFile += 54;
    		header24[2] = dwSizeFile & 0x000000ff;// 0x36
    		header24[3] = static_cast<BYTE>((dwSizeFile & 0x0000ff00) >> 8);// 0x10
    		header24[4] = static_cast<BYTE>((dwSizeFile & 0x00ff0000) >> 16);// 0x0e
    		header24[5] = (dwSizeFile & 0xff000000) >> 24;// 0x00
    		dwSizeFile -= 54;
    		header24[18] = INPUT_FRAME_WIDTH & 0x000000ff;// 0x80
    		header24[19] = (INPUT_FRAME_WIDTH & 0x0000ff00) >> 8;// 0x02
    		header24[20] = static_cast<BYTE>((INPUT_FRAME_WIDTH & 0x00ff0000) >> 16);// 0x00
    		header24[21] = (INPUT_FRAME_WIDTH & 0xff000000) >> 24;// 0x00
     
    		header24[22] = INPUT_FRAME_HEIGHT & 0x000000ff;// 0x0e
    		header24[23] = (INPUT_FRAME_HEIGHT & 0x0000ff00) >> 8;// 0x01
    		header24[24] = static_cast<BYTE>((INPUT_FRAME_HEIGHT & 0x00ff0000) >> 16);// 0x00
    		header24[25] = (INPUT_FRAME_HEIGHT & 0xff000000) >> 24;// 0x00
     
    		// 000E1036
    		header24[34] = dwSizeFile & 0x000000ff;// 0x00
    		header24[35] = (dwSizeFile & 0x0000ff00) >> 8;// 0x10
    		header24[36] = static_cast<BYTE>((dwSizeFile & 0x00ff0000) >> 16);// 0x0e
    		header24[37] = static_cast<BYTE>((dwSizeFile & 0xff000000) >> 24);// 0x00
     
    		hFile = CreateFile(OUTPUT_FILE_STRING, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
     
    		WriteFile(hFile, (LPCVOID)header24, 54, &dwWritten, 0);
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				WriteFile(hFile, (LPCVOID)ppData[i], INPUT_FRAME_WIDTH_RGB24, &dwWritten, 0);
    		}
     
    		CloseHandle(hFile);
    }

  14. #14
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    Voici une version fonctionnelle. Dans le code précédent j'appliquais la transformée octet par octet et non pixel par pixel.

    L'idée donc, c'est juste de prendre un pixel, de calculer son intensité, et de la comparer avec l'intensité des pixels voisins. Il y a une version avec matrice 3x3 ou 5x5. On obtient un nombre que l'on duplique dans les trois composantes du buffer final, ce qui nous donne une image en niveau de gris.

    J'ai aussi ajouter la gestion de bitmap 32bits (sans gestion de l'alpha).

    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
     
     
    //-----------------------------------------------------------------------------------------------
    // Main.cpp
    //-----------------------------------------------------------------------------------------------
    #include <windows.h>
     
    #define USE_RGB24
    //#define USE_RGB32
     
    #define INPUT_FRAME_WIDTH         1024
    #define INPUT_FRAME_HEIGHT         768
     
    #ifdef USE_RGB24
      #define BMP_BYTE_SIZE            0x18
      #define NUMBER_BYTE              3
      #define INPUT_FRAME_WIDTH_BYTE   (INPUT_FRAME_WIDTH * 3)
      #define TOTAL_FRAME_SIZE         (INPUT_FRAME_WIDTH_BYTE * INPUT_FRAME_HEIGHT)
      #define INPUT_FILE_STRING        L"C:\\projet\\media\\rgb24\\imageBmp24.bmp"
    #endif
     
    #ifdef USE_RGB32
      #define BMP_BYTE_SIZE            0x20
      #define NUMBER_BYTE              4
      #define INPUT_FRAME_WIDTH_BYTE   (INPUT_FRAME_WIDTH * 4)
      #define TOTAL_FRAME_SIZE         (INPUT_FRAME_WIDTH_BYTE * INPUT_FRAME_HEIGHT)
      #define INPUT_FILE_STRING        L"C:\\projet\\media\\rgb24\\imageBmp32.bmp"
    #endif
     
    #define CENSUS_MATRIX               5// 3 or 5
    #define SIZE_HEADER                54
    #define OUTPUT_FILE_STRING         L"C:\\projet\\media\\rgb24\\Census.bmp"
     
    void CreateBmpFile(BYTE**, const UINT);
     
    void main(){
     
    		HANDLE hFileInPut = INVALID_HANDLE_VALUE;
    		DWORD dwRead;
    		DWORD dwFileSize;
    		BYTE* pDataIn = NULL;
    		BYTE* pTmp;
     
    		BYTE** pDataInCensus = NULL;
    		BYTE** pDataOutCensus = NULL;
     
    		hFileInPut = CreateFile(INPUT_FILE_STRING, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
     
    		dwFileSize = GetFileSize(hFileInPut, NULL);
     
    		pDataIn = new BYTE[dwFileSize];
     
    		ReadFile(hFileInPut, (LPVOID)pDataIn, dwFileSize, &dwRead, 0);
     
    		pDataInCensus = new BYTE*[INPUT_FRAME_HEIGHT];
    		pDataOutCensus = new BYTE*[INPUT_FRAME_HEIGHT];
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				pDataInCensus[i] = new BYTE[INPUT_FRAME_WIDTH_BYTE];
    				pDataOutCensus[i] = new BYTE[INPUT_FRAME_WIDTH_BYTE];
    		}
     
    		pTmp = pDataIn + SIZE_HEADER;
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				memcpy(pDataInCensus[i], pTmp, INPUT_FRAME_WIDTH_BYTE);
    				pTmp += INPUT_FRAME_WIDTH_BYTE;
    		}
     
    		unsigned int census = 0;
    		unsigned int bit = 0;
    		int m = CENSUS_MATRIX;
    		int n = CENSUS_MATRIX;//window size
    		int i,j,x,y;
    		int shiftCount = 0;
     
    		int iGrayScaleRef;
    		int iGrayScaleCurrent;
    		float r;
    		float g;
    		float b;
     
    		for(x = m / 2; x < INPUT_FRAME_HEIGHT - m / 2; x++){
     
    				for(y = n / 2 * NUMBER_BYTE; y < INPUT_FRAME_WIDTH_BYTE - (n / 2 * NUMBER_BYTE); y += NUMBER_BYTE){
     
    						census = 0;
    						shiftCount = 0;
     
    						r = pDataInCensus[x][y];
    						g = pDataInCensus[x][y + 1];
    						b = pDataInCensus[x][y + 2];
     
    						iGrayScaleRef = static_cast<int>((r + g + b) / 3.0f);
     
    						for(i = x - m / 2; i <= x + m / 2; i++){
     
    								for(j = y - (n / 2 * NUMBER_BYTE); j <= y + (n / 2 * NUMBER_BYTE); j += NUMBER_BYTE){
     
    										//skip the center pixel
    										if(shiftCount != m * n / 2){
     
    												census <<= 1;
     
    												r = pDataInCensus[i][j];
    												g = pDataInCensus[i][j + 1];
    												b = pDataInCensus[i][j + 2];
     
    												iGrayScaleCurrent = static_cast<int>((r + g + b) / 3.0f);
     
    												//compare pixel values in the neighborhood
    												if(iGrayScaleCurrent < iGrayScaleRef)
    														bit = 1;
    												else
    														bit = 0;
     
    												census = census + bit;
    										}
     
    										shiftCount++;
    								}
    						}
     
    						pDataOutCensus[x][y] = census;
    						pDataOutCensus[x][y + 1] = census;
    						pDataOutCensus[x][y + 2] = census;
    				}
    		}
     
    		CreateBmpFile(pDataOutCensus, TOTAL_FRAME_SIZE);
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				delete[] pDataInCensus[i];
    				delete[] pDataOutCensus[i];
    		}
     
    		delete[] pDataInCensus;
    		delete[] pDataOutCensus;
    		delete[] pDataIn;
    }
     
     
     
    void CreateBmpFile(BYTE** ppData, const UINT uiFrameSize){
     
    		HANDLE hFile = INVALID_HANDLE_VALUE;
    		DWORD dwWritten;
     
    		BYTE header24[54] = {0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
    		                     0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    																	  				0x01, 0x00, BMP_BYTE_SIZE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    																			  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
     
    		DWORD dwSizeFile = TOTAL_FRAME_SIZE;
    		dwSizeFile += 54;
    		header24[2] = dwSizeFile & 0x000000ff;// 0x36
    		header24[3] = static_cast<BYTE>((dwSizeFile & 0x0000ff00) >> 8);// 0x10
    		header24[4] = static_cast<BYTE>((dwSizeFile & 0x00ff0000) >> 16);// 0x0e
    		header24[5] = (dwSizeFile & 0xff000000) >> 24;// 0x00
    		dwSizeFile -= 54;
    		header24[18] = INPUT_FRAME_WIDTH & 0x000000ff;// 0x80
    		header24[19] = (INPUT_FRAME_WIDTH & 0x0000ff00) >> 8;// 0x02
    		header24[20] = static_cast<BYTE>((INPUT_FRAME_WIDTH & 0x00ff0000) >> 16);// 0x00
    		header24[21] = (INPUT_FRAME_WIDTH & 0xff000000) >> 24;// 0x00
     
    		header24[22] = INPUT_FRAME_HEIGHT & 0x000000ff;// 0x0e
    		header24[23] = (INPUT_FRAME_HEIGHT & 0x0000ff00) >> 8;// 0x01
    		header24[24] = static_cast<BYTE>((INPUT_FRAME_HEIGHT & 0x00ff0000) >> 16);// 0x00
    		header24[25] = (INPUT_FRAME_HEIGHT & 0xff000000) >> 24;// 0x00
     
    		// 000E1036
    		header24[34] = dwSizeFile & 0x000000ff;// 0x00
    		header24[35] = (dwSizeFile & 0x0000ff00) >> 8;// 0x10
    		header24[36] = static_cast<BYTE>((dwSizeFile & 0x00ff0000) >> 16);// 0x0e
    		header24[37] = static_cast<BYTE>((dwSizeFile & 0xff000000) >> 24);// 0x00
     
    		hFile = CreateFile(OUTPUT_FILE_STRING, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
     
    		WriteFile(hFile, (LPCVOID)header24, 54, &dwWritten, 0);
     
    		for(int i = 0; i < INPUT_FRAME_HEIGHT; i++){
     
    				WriteFile(hFile, (LPCVOID)ppData[i], INPUT_FRAME_WIDTH_BYTE, &dwWritten, 0);
    		}
     
    		CloseHandle(hFile);
    }
    L'arrière-plan de windows en 5x5 :
    Images attachées Images attachées  

  15. #15
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Ce dimanche passé sur ma machine à comprendre la transformée de Census je pense être arrivé à un premier résultat.

    Je suis parti de la photo originale.jpg (en pièce jointe). Après conversion de celle-ci en niveau de gris j'ai appliqué la transformée (Final.jpg).

    Le résultat correspond-il à la transformée de census ?
    Images attachées Images attachées   

  16. #16
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    J'ai testé l'image, j'obtiens cela (à gauche 3x3 et à droite 5x5) :
    Images attachées Images attachées   

  17. #17
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Ce que je ne sais pas c'est quel est l'agencement des bits par rapport à la matrice 3x3.

    En partant d'une matrice de ce type :

    A B C
    E F G j'ai créé l'octet : A B C E G H I J
    H I J

    Est-ce la bonne méthode ?

  18. #18
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour gerald3d.

    J'ai pris un peu de temps pour lire l'algorithme (oui je fonctionne comme cela. Je me jette dans le code et quand ça marche pas, je vais lire la doc...) :

    http://www.cs.duke.edu/courses/sprin...ill%201994.pdf

    On est loin du compte je pense...

    Il y a deux parties "rank transform" et "census transform".

    Le rank transform, c'est le calcul de l'intensité du pixel. Le document parle de "L1 corrélation" pour ce calcul. Je suis allé voir vite fait ce que c'était, j'ai lâché l'affaire...

    Ensuite, dans le code C++ que j'ai transposé, il y a des erreurs. Le document dit que le dernier pixel de test sera 1 s'il est inférieur à 128 et 0 sinon.

    Ensuite, il doit manquer des informations dans ce document. Il ne précise pas par exemple comment sont remplis les pixels du bord de l'image. En effet on ne peut pas les comparer avec les pixels précédents (ils n'existent pas). Mais si on regarde les images qu'ils donnent en démo, il n 'y a pas de cadre. Bizarre.

    De plus dans la documentation :


    {1, 1, 0, 1, 0, 1, 0, a} The rank transform will give 5 if A < 128, and otherwise 4
    Bref, à ce moment du document, je pensais que ça parlé de census, et non de rank.
    De plus ça de parle de 4 ou 5 en valeur. Alors que l'on a 8 bits...

    Bref, reste plus quà trouver une implémentation qui fonctionne. Je me suis rendu compte que le bloggeur du code C++ disait que son code ne marchait pas...

    Sinon, je pense avoir compris que ce genre d'algo pouvait servir à calculer plus efficacement les "motion vector" lors d'une compression vidéo.

    Il faudrait certainement l'aide d'un statiticien/mathématicien, pour implémenter cet algo.

    A vrai dire, cet algo me laisse perplexe.

  19. #19
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Let P be a pixel, I (P ) its intensity (usually an 8-bit integer), and N (P ) the
    set of pixels in some square neighborhood of diameter d surrounding P . All non-
    parametric transforms depend upon the comparative intensities of P versus the
    pixels in the neighborhood N (P ). The transforms we will discuss only depend
    on the sign of the comparison. Define (P P ) to be 1 if I (P' ) < I (P ) and 0
    otherwise.
    De part cette description je viens de m'apercevoir que je faisais l'inverse. Je mettais à 0 si I(P') < I(P) !

    Par contre je confirme le mode de lecteur de la matrice pour construire l'octet résultant.

    Apparement le "Rank" correspond au nombre de bits à 1 dans la matrice résultante. L'exemple donné dans le PDF est le suivant :
    Le "Rank" est ici de 4 (avec a=0) ou 5 (si a=1).

    D'après ce que je comprends la transformée de Census et la transformée de Rank (pas sûr que ce soit un nom propre !) sont deux manières de calculer l'image résultante.

    Si j'extrapole la transformée de Rank, pour une matrice 3x3 => R € [0,7]. Donc pour créer une image en niveau de gris il suffirait de faire la transposée sur l'échelle [0,255]. À vérifier...

  20. #20
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Après avoir rectifié mon algorithme et ajouté la transformée de Rank voila le résultat avec les deux méthodes (pièces jointes).
    Images attachées Images attachées   

Discussions similaires

  1. [PERL] transformation de fichier
    Par bob20000 dans le forum Langage
    Réponses: 6
    Dernier message: 27/07/2006, 11h13
  2. transformer un jour en JJ/MM/AA
    Par gemini_010 dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 08/11/2002, 22h55
  3. Transformer un caractère en type énuméré
    Par HT dans le forum Langage
    Réponses: 3
    Dernier message: 22/10/2002, 20h46
  4. FFT(Fast Fourier Transform)
    Par IngBen dans le forum Traitement du signal
    Réponses: 6
    Dernier message: 23/05/2002, 16h35

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