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 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
| //------------------------------------------------------------------------------
#pragma hdrstop
#include <stdlib.h>
#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;
//------------------------------------------------------------------------------
#pragma pack(push,1)
typedef struct {
WORD bftype;
DWORD bfsize;
WORD bfreserved1;
WORD bfreserved2;
DWORD bfoffbits;
} FILEHEADER;
typedef struct {
DWORD bisize;
DWORD biwidth;
DWORD biheight;
WORD biplanes;
WORD bibitcount;
DWORD bicompression;
DWORD bisizeimage;
DWORD bixpelspermeter;
DWORD biypelspermeter;
DWORD biclrused;
DWORD biclrimportant;
} INFOHEADER;
typedef struct {
FILEHEADER Fileheader;
INFOHEADER Infoheader;
} Entete_BMP;
typedef struct {
unsigned char Bleu;
unsigned char Vert;
unsigned char Rouge;
} T_PIXEL;
#pragma pack(pop)
//------------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
Entete_BMP Mon_Entete;//Structure contenant toutes les informations relatives à l'en tête bmp
HANDLE Descripteur;//Descripteur de l'image originale
HANDLE Descripteur_Redimensionnement_Hauteur;//Descripteur de l'image avec la hauteur réajustée
HANDLE Descripteur_Suppression_Cote_Gauche;//Descripteur de l'image avec le côté gauche supprimé
char Nom_Fichier[50];//Variable qui stock le chemin d'ouverture ou d'enregistrement d'un fichier bmp
unsigned char *Tableau;//Tableau contenant l'image originale
unsigned char *Tableau_Hauteur_Redimensionnee;//Tableau contenant uniquement les lignes où se trouve la plaque
unsigned char *Tableau_Sans_Cote_Gauche;//Tableau contenant la plaque avec seulement le cote droit de la voiture
DWORD Octets_Lus;//Permet d'enregistrer les informations contenues dans un fichier, dans un tableau
DWORD Octets_Ecrits;//Permet d'enregistrer les informations contenues dans un tableau, dans un fichier
unsigned int Index_Colonne;//Index parcourant les colonnes de l'image
unsigned int Index_Ligne;//Index parcourant les lignes de l'image
unsigned int Compteur_Pixels_Bleus;//Permet de compter le nombre de pixels bleus "plaque" sur une même ligne
unsigned int Compteur_Lignes_Bleus = 0;//Permet de compter le nombre de lignes possedant le nombre de pixels bleus adequat
unsigned int Hauteur;//Permet de memoriser la hauteur de l'image
unsigned int Largeur;//Permet de memoriser la largeur de l'image
unsigned int Compteur_Ligne = 0;
unsigned int Nombre_Colonnes_Conservees = 0;//Permet de connaitre le nombre de colonnes à conserver dans une ligne
unsigned int Nombre_Colonnes_Conservees_Final = 0;//Permet de connaitre le nombre de colonnes à conserver pour toutes les lignes
unsigned int Compteur_Position = 0;//Permet de definir la position actuelle dans une colonne
unsigned int Numero_Derniere_Ligne_Plaque;//Permet de connaitre le numero de la derniere ligne contenant une partie de la plaque
unsigned int Numero_Premiere_Ligne_Plaque;//Permet de connaitre le numero de la premiere ligne contenant une partie de la plaque
unsigned int Position_Derniere_Colonne;
unsigned int *Tableau_Position_Plaque;//Tableau memorisant la colonne contenant le début de la plaque pour toutes les lignes de l'image
bool Premiere_Ligne_Plaque = false;//Permet de savoir si la premiere ligne contenant une partie de la plaque à été parcourue ou non
T_PIXEL Pixel_Bleu_Clair = {139, 89, 28}; //Issu d'une recherche de nuances sous paint
T_PIXEL Pixel_Bleu_Fonce = {117, 63, 0}; //Issu d'une recherche de nuances sous paint
T_PIXEL Mon_Pixel;//Variable qui recupère les 3 valeurs correspondantes aux couleurs qui composent chaque pixel
//PARTIE 1
//-----------------Ouverture de l'image originale-----------------------
cout<<"Taper le nom du fichier a ouvrir"<<endl;
cin>>Nom_Fichier;//Saisi du chemin et du nom du fichier à ouvrir
Descripteur = CreateFile(Nom_Fichier, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//Ouverture du fichier et memorisation de la position grace au Descripteur
ReadFile(Descripteur, &Mon_Entete, sizeof(Entete_BMP), &Octets_Lus, NULL);//Lecture de l'En-tete du fichier et sauvegarde de celle ci dans une structure de type Entete_BMP
//----------------------------------------------------------------------
/*cout<<"Type de fichier : "<<Mon_Entete.Fileheader.bftype<<endl;
cout<<"Taille totale du fichier : "<<Mon_Entete.Fileheader.bfsize<<endl;
cout<<"Taille de l'entete : "<<Mon_Entete.Infoheader.bisize<<endl;
cout<<"Largeur de l'image : "<<Mon_Entete.Infoheader.biwidth<<endl;
cout<<"Hauteur de l'image : "<<Mon_Entete.Infoheader.biheight<<endl;
cout<<"Profondeur de l'image : "<<Mon_Entete.Infoheader.bibitcount<<endl;
cout<<"Taille totale de l'image : "<<Mon_Entete.Infoheader.bisizeimage<<endl;
cout <<"Offset : " << Mon_Entete.Fileheader.bfoffbits << endl;
cout<<endl;*/
//----------Creation et sauvegarde de l'image dans le tableau-----------
Tableau = new unsigned char[Mon_Entete.Infoheader.bisizeimage];//Creation d'un tableau de la taille de l'image contenue dans le fichier ouvert predemment
SetFilePointer(Descripteur, Mon_Entete.Fileheader.bfoffbits, NULL, FILE_BEGIN);//Positionnement du Descripteur au début de l'image dans le fichier
ReadFile(Descripteur, Tableau, Mon_Entete.Infoheader.bisizeimage, &Octets_Lus, NULL);//Lecture de l'image et sauvegarde de celle-ci dans un tableau en mémoire
//-------------------------Detection Plaque-----------------------------
Hauteur = Mon_Entete.Infoheader.biheight ;//Definition de la hauteur
Largeur = Mon_Entete.Infoheader.biwidth*3 ;//Definition de la largeur (on multiplie par 3 car il faut 3 octets pour coder un pixel)
Compteur_Pixels_Bleus = 0;//On réinitialise le compteur
for(Index_Ligne = 0; Index_Ligne < Hauteur; Index_Ligne++){//Debut boucle Index_Ligne
for(Index_Colonne = 0; Index_Colonne < Largeur; Index_Colonne++){//Debut boucle Index_Colonne
Mon_Pixel.Bleu = Tableau[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel bleu dans un T_PIXEL
Index_Colonne++;
Mon_Pixel.Vert = Tableau[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel vert dans un T_PIXEL
Index_Colonne++;
Mon_Pixel.Rouge = Tableau[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel rouge dans un T_PIXEL
//On obtient ainsi toutes les composantes d'un pixel
if((Mon_Pixel.Bleu >= Pixel_Bleu_Fonce.Bleu)&& (Mon_Pixel.Bleu <= Pixel_Bleu_Clair.Bleu)
&&(Mon_Pixel.Vert >= Pixel_Bleu_Fonce.Vert)&&(Mon_Pixel.Vert <= Pixel_Bleu_Clair.Vert)
&&(Mon_Pixel.Rouge >= Pixel_Bleu_Fonce.Rouge)&&(Mon_Pixel.Rouge <= Pixel_Bleu_Clair.Rouge))//On compare afin de savoir si la nuance du pixel
//est comprise dans une tranche de couleurs correspondante
//à la couleur du bleu d'une plaque d'immatriculation
{Compteur_Pixels_Bleus++;//On indique qu'un pixel bleu "plaque" à été repéré
}
}//Fin boucle Index_Colonne
if((Compteur_Pixels_Bleus > 15)&&(Compteur_Pixels_Bleus < 45)){//Si dans une même ligne il y a plus de 15 et moins de 45 pixels bleus "plaque"
Compteur_Lignes_Bleus++;
if(Premiere_Ligne_Plaque == false){//Dans le cas où la première ligne n'a pas encoré été rencontrée
Premiere_Ligne_Plaque = true;//Cette ligne est la première
Numero_Premiere_Ligne_Plaque = Index_Ligne;//On retient le numero de la première ligne de la plaque
}
}
Compteur_Pixels_Bleus = 0;//Reinitialisation du nombre de pixel bleus
}//Fin boucle Index_Ligne
//PARTIE 2
//-------------------Redimenssionnement Hauteur-------------------------
Numero_Derniere_Ligne_Plaque = Numero_Premiere_Ligne_Plaque + Compteur_Lignes_Bleus;//On definit le numero de la derniere ligne de l'image contenant la plaque
Tableau_Hauteur_Redimensionnee = new unsigned char[Compteur_Lignes_Bleus * Largeur];//Creation d'un tableau ayant une taille egale
//au nombre de lignes contenant la plaque multiplié par la lageur
for(Index_Ligne = Numero_Premiere_Ligne_Plaque; Index_Ligne < Numero_Derniere_Ligne_Plaque; Index_Ligne++){//Debut de la boucle Index_Ligne
for(Index_Colonne = 0; Index_Colonne < Largeur; Index_Colonne++){//Debut de la boucle Index_Colonne
//On copie dans le nouveau tableau, toutes les lignes contenant la plaque
Tableau_Hauteur_Redimensionnee[(Compteur_Ligne * Largeur) + Index_Colonne] = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Tableau_Hauteur_Redimensionnee[(Compteur_Ligne * Largeur) + Index_Colonne] = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Tableau_Hauteur_Redimensionnee[(Compteur_Ligne * Largeur) + Index_Colonne] = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
}//Fin boucle Index_Colonne
Compteur_Ligne++;
}//Fin boucle Index_Ligne
delete(Tableau);//Suppression du tableau contenant l'image originale
CloseHandle(Descripteur);//Fermeture du Descripteur pointant sur le fichier contenant l'image originale
//------------Initialisation En-Tête BMP et création fichier------------
Mon_Entete.Fileheader.bfsize = 54 + (Largeur * Compteur_Lignes_Bleus);//Taille totale du fichier en octet
Mon_Entete.Infoheader.biheight = Compteur_Lignes_Bleus;//Hauteur de l'image en pixel
Mon_Entete.Infoheader.bisizeimage = Largeur * Compteur_Lignes_Bleus;//Taille de l'image en octet
//-------------------------------
/*cout<<"Type de fichier : "<<Mon_Entete.Fileheader.bftype<<endl;
cout<<"Taille totale du fichier : "<<Mon_Entete.Fileheader.bfsize<<endl;
cout<<"Taille de l'entete : "<<Mon_Entete.Infoheader.bisize<<endl;
cout<<"Largeur de l'image : "<<Mon_Entete.Infoheader.biwidth<<endl;
cout<<"Hauteur de l'image : "<<Mon_Entete.Infoheader.biheight<<endl;
cout<<"Profondeur de l'image : "<<Mon_Entete.Infoheader.bibitcount<<endl;
cout<<"Taille totale de l'image : "<<Mon_Entete.Infoheader.bisizeimage<<endl;
cout <<"Offset : " << Mon_Entete.Fileheader.bfoffbits << endl;*/
cout<<endl;
//-----------------------------
cout<<"Specifier un chemin et un nom d'enregistrement pour la plaque sans le haut et le bas : ";
cin>>Nom_Fichier;//Chemin et nom du fichier bmp qui contiendra l'image réajustée
Descripteur_Redimensionnement_Hauteur = CreateFile(Nom_Fichier,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);//Creation du fichier
WriteFile(Descripteur_Redimensionnement_Hauteur, &Mon_Entete.Fileheader, (sizeof(BITMAPFILEHEADER) - 2), &Octets_Ecrits, NULL);//Inscription de la premiere en tete dans le fichier
//La soustraction par 2 est necessaire
//à cause d'un problème lié à Borland 6, qui indique un valeur
//erronée de 2 par rapport à la taille originale
WriteFile(Descripteur_Redimensionnement_Hauteur, &Mon_Entete.Infoheader, sizeof(BITMAPINFOHEADER), &Octets_Ecrits, NULL);//Inscription de la seconde en tete dans le fichier
WriteFile(Descripteur_Redimensionnement_Hauteur, Tableau_Hauteur_Redimensionnee, Compteur_Lignes_Bleus * Largeur, &Octets_Ecrits, NULL);//Inscription de l'image dans le fichier
CloseHandle(Descripteur_Redimensionnement_Hauteur);//Fermeture du Descripteur pointant sur le fichier
//PARTIE 3
//----------------------Detection début plaque--------------------------
Compteur_Pixels_Bleus = 0;//Reinitialisation du compteur
Tableau_Position_Plaque = new unsigned int[Mon_Entete.Infoheader.biheight];//Creation d'un nouveau tableau d'une taille equivalent au nombre de lignes de l'image
for(Index_Ligne = 0; Index_Ligne < Mon_Entete.Infoheader.biheight; Index_Ligne++){//Debut boucle Index_Ligne
for(Index_Colonne = 0; Index_Colonne < Largeur; Index_Colonne++){//Debut boucle Index_Colonne
Mon_Pixel.Bleu = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel bleu dans un T_PIXEL
Index_Colonne++;
Mon_Pixel.Vert = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel vert dans un T_PIXEL
Index_Colonne++;
Mon_Pixel.Rouge = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];//On recupère la valeur du pixel rouge dans un T_PIXEL
if((Mon_Pixel.Bleu >= Pixel_Bleu_Fonce.Bleu)&& (Mon_Pixel.Bleu <= Pixel_Bleu_Clair.Bleu)
&&(Mon_Pixel.Vert >= Pixel_Bleu_Fonce.Vert)&&(Mon_Pixel.Vert <= Pixel_Bleu_Clair.Vert)
&&(Mon_Pixel.Rouge >= Pixel_Bleu_Fonce.Rouge)&&(Mon_Pixel.Rouge <= Pixel_Bleu_Clair.Rouge))//On compare afin de savoir si la nuance du pixel
//est comprise dans une tranche de couleurs correspondante
//à la couleur du bleu d'une plaque d'immatriculation
{Compteur_Pixels_Bleus++;
}
if(Compteur_Pixels_Bleus > 15){//S'il y a plus de 15 pixels bleus
Nombre_Colonnes_Conservees++;
}
if(Compteur_Pixels_Bleus <= 15){//S'il y a 15 pixels bleus ou moins
Compteur_Position++;
}
}//Fin boucle Index_Colonne
Compteur_Position = (Compteur_Position - 15) * 3;//Memorise la position du debut de la plaque sur la ligne
Tableau_Position_Plaque[Index_Ligne] = Compteur_Position;//On memorise la position dans un tableau
Compteur_Position = 0;//Remise à 0 du compteur pour la prochaine ligne
Compteur_Pixels_Bleus = 0;//Remise à 0 du nombre de bleu pour la prochaine ligne
if(Index_Ligne == 0){//Si on se trouve sur la premiere ligne
Nombre_Colonnes_Conservees_Final = Nombre_Colonnes_Conservees;}//Le nombre de colonnes conservees pour toutes les lignes
//sera egal au nombre de colonnes conservees dans la premiere ligne
if(Nombre_Colonnes_Conservees_Final > Nombre_Colonnes_Conservees){//Si dans une ligne le nombre de colonnes conservees est moins important que le nombre de colonnes
//conservees au final
Nombre_Colonnes_Conservees_Final = Nombre_Colonnes_Conservees;}//Le nombre de colonnes conservees pour toutes les lignes
//sera egal au nombre de colonnes conservees dans la ligne actuelle
Nombre_Colonnes_Conservees = 0;//On reinitialise le nombre de colonnes conservees
}//Fin boucle Index_Ligne
//------------------Suppression côté gauche plaque----------------------
Nombre_Colonnes_Conservees_Final = (Nombre_Colonnes_Conservees_Final + 15) * 3;//Car on veut prendre en compte le bleu de la plaque donc 15 pixels de 3 octets chacuns
Tableau_Sans_Cote_Gauche = new unsigned char[Mon_Entete.Infoheader.biheight * Nombre_Colonnes_Conservees_Final];
int Tampon_Position;//Memorise les positions des premiers pixels qui sont conservées dans Tableau_Position_Plaque
for(Index_Ligne = 0; Index_Ligne < Mon_Entete.Infoheader.biheight; Index_Ligne++){//Debut boucle Index_Ligne
Tampon_Position = Tableau_Position_Plaque[Index_Ligne];//Tampon_Position memorise la position de la colonne où se trouve le
//premier pixel de la plaque sur la ligne
for(Index_Colonne = 0; Index_Colonne < Nombre_Colonnes_Conservees_Final; Index_Colonne++){//Debut boucle Index_Colonne
//On copie dans le nouveau tableau, toutes les lignes contenant la plaque sans le coté gauche
Tableau_Sans_Cote_Gauche[(Index_Ligne * Nombre_Colonnes_Conservees_Final) + Index_Colonne] = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne + Tampon_Position];
Index_Colonne++;
Tableau_Sans_Cote_Gauche[(Index_Ligne * Nombre_Colonnes_Conservees_Final) + Index_Colonne] = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne + Tampon_Position];
Index_Colonne++;
Tableau_Sans_Cote_Gauche[(Index_Ligne * Nombre_Colonnes_Conservees_Final) + Index_Colonne] = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne + Tampon_Position];
}//Fin boucle Index_Colonne
}//Fin boucle Index_Ligne
delete(Tableau_Hauteur_Redimensionnee);//Suppression du tableau précédent
delete(Tableau_Position_Plaque);//Suppression du tableau contenant les positions du debut de plaque
//------------Initialisation En-Tête BMP et création fichier------------
Largeur = Nombre_Colonnes_Conservees_Final/3;//Definition de la largeur
Mon_Entete.Fileheader.bfsize = 54 + (Mon_Entete.Infoheader.biheight * Nombre_Colonnes_Conservees_Final);//Taille totale du fichier en octet
Mon_Entete.Infoheader.biwidth = Largeur;//Largeur de l'image en pixel
Mon_Entete.Infoheader.bisizeimage = Mon_Entete.Infoheader.biheight * Nombre_Colonnes_Conservees_Final;//Taille de l'image en octet
cout<<"Type de fichier : "<<Mon_Entete.Fileheader.bftype<<endl;
cout<<"Taille totale du fichier : "<<Mon_Entete.Fileheader.bfsize<<endl;
cout<<"Taille de l'entete : "<<Mon_Entete.Infoheader.bisize<<endl;
cout<<"Largeur de l'image : "<<Mon_Entete.Infoheader.biwidth<<endl;
cout<<"Hauteur de l'image : "<<Mon_Entete.Infoheader.biheight<<endl;
cout<<"Profondeur de l'image : "<<Mon_Entete.Infoheader.bibitcount<<endl;
cout<<"Taille totale de l'image : "<<Mon_Entete.Infoheader.bisizeimage<<endl;
cout <<"Offset : " << Mon_Entete.Fileheader.bfoffbits << endl;
cout<<endl;
//-------------------------
cout<<"Specifier un chemin et un nom d'enregistrement pour la plaque sans cote gauche : ";
cin>>Nom_Fichier;//On determine le chemin et le nom du fichier qui va contenir l'image
Descripteur_Suppression_Cote_Gauche = CreateFile(Nom_Fichier,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);//Creation du fichier
WriteFile(Descripteur_Suppression_Cote_Gauche, &Mon_Entete.Fileheader, (sizeof(BITMAPFILEHEADER) - 2), &Octets_Ecrits, NULL);//On inscrit la premiere en tete dans le fichier
//La soustraction par 2 est necessaire
//à cause d'un problème lié à Borland 6, qui indique un valeur
//erronée de 2 par rapport à la taille originale d'un fileheader
WriteFile(Descripteur_Suppression_Cote_Gauche, &Mon_Entete.Infoheader, sizeof(BITMAPINFOHEADER), &Octets_Ecrits, NULL);//On inscrit la deuxieme en tete dans le fichier
WriteFile(Descripteur_Suppression_Cote_Gauche, Tableau_Sans_Cote_Gauche, Mon_Entete.Infoheader.biheight * Nombre_Colonnes_Conservees_Final, &Octets_Ecrits, NULL);//On inscrit l'image dans le fichier
CloseHandle(Descripteur_Suppression_Cote_Gauche);//Fermeture du Descripteur
//----------------------------------------------------------------------
getch();
return 0;
}
//---------------------------------------------------------------------- |
Partager