Bonjour,
dans le cadre de mon projet de fin d'année de BTS, je dois entre autres à partir d'une photo de véhicule, reconnaitre la position de la plaque d'immatriculation de ce dernier, extraire cette plaque et recréer un fichier bmp avec uniquement la plaque d'immatriculation à l'intérieur.
Les étapes que j'ai actuellement effectué se décomposent de la manière suivante :
Partie 1 :
-Stockage de l'image en mémoire dans un tableau.
-Parcours du tableau pour reconnaitre la position de la plaque au moyen des pixels bleus présents sur la ligne (on considère que toutes les plaques ont ce rectangle bleu sur la gauche).
Partie 2 :
-Stockage de toutes les lignes contenant ces pixels bleus dans un autre tableau.
-Création d'une en tête bmp et création d'un fichier bmp dans lequel j'insère l'en-tête puis l'image. (jusque là tout va bien)
Partie 3 :
-Détection du début du bleu sur la plaque afin de supprimer le côté gauche de l'image.
-Récupération de la plaque sans le coté gauche de l'image dans un tableau.
-Création d'une en tête bmp et création d'un fichier bmp dans lequel j'insère l'en-tête puis l'image.
La partie 1 et 2 marchent parfaitement, j'ai extrait le morceau d'image et recréé un fichier bmp contenant celle ci, et tout marche à merveille.
En revanche je ne peux pas en dire autant pour la partie 3, une fois les étapes terminées, j'ai bien un fichier bmp créé, avec la taille du fichier correspondante affichée, mais l'image ne se trouve pas dans le fichier. Et le gros soucis c'est que j'ai beau avoir tenté de retourner dans tous les sens le problème, je ne vois pas ce qui cloche.
Pour info, j'utilise builder C++ 6, je ne sais pas si cela peut aider, mais sait on jamais ^^".
Si une âme charitable arrivait à repérer l'erreur que j'ai commis, je lui en serais fortement reconnaissant, car là je n'en vois pas le bout.
Voilà donc mon code :
Code C/C++ :
//------------------------------------------------------------------------------
#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;
HANDLE Descripteur;
HANDLE Descripteur_Redimensionnement_Hauteur;
HANDLE Descripteur_Suppression_Cote_Gauche;
char Nom_Fichier[50];
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;
DWORD Octets_Ecrits;
unsigned int Index_Colonne;
unsigned int Index_Ligne;
unsigned int Compteur_Pixels_Bleus = 0;
unsigned int Compteur_Lignes_Bleus = 0;
unsigned int Hauteur;
unsigned int Largeur;
unsigned int Compteur_Ligne = 0;
unsigned int Nombre_Colonnes_Conservees = 0;
unsigned int Nombre_Colonnes_Conservees_Final = 0;
unsigned int Compteur_Position = 0;
unsigned int Numero_Derniere_Ligne_Plaque;
unsigned int Numero_Premiere_Ligne_Plaque;
unsigned int Position_Derniere_Colonne;
unsigned int *Tableau_Position_Plaque;
bool Premiere_Ligne_Plaque = false;
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;
Descripteur = CreateFile(Nom_Fichier, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(Descripteur, &Mon_Entete, sizeof(Entete_BMP), &Octets_Lus, NULL);
//----------Creation et sauvegarde de l'image dans le tableau-----------
Tableau = new unsigned char[Mon_Entete.Infoheader.bisizeimage];
SetFilePointer(Descripteur, Mon_Entete.Fileheader.bfoffbits, NULL, FILE_BEGIN);
ReadFile(Descripteur, Tableau, Mon_Entete.Infoheader.bisizeimage, &Octets_Lus, NULL);
//-------------------------Detection Plaque-----------------------------
Hauteur = Mon_Entete.Infoheader.biheight ;
Largeur = Mon_Entete.Infoheader.biwidth*3 ;
for(Index_Ligne = 0; Index_Ligne < Hauteur; Index_Ligne++){
for(Index_Colonne = 0; Index_Colonne < Largeur; Index_Colonne++){
Mon_Pixel.Bleu = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Mon_Pixel.Vert = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Mon_Pixel.Rouge = Tableau[(Index_Ligne * Largeur) + Index_Colonne];
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))
{Compteur_Pixels_Bleus++;
}
}//Fin boucle Index_Colonne
if((Compteur_Pixels_Bleus > 15)&&(Compteur_Pixels_Bleus < 45)){
Compteur_Lignes_Bleus++;
if(Premiere_Ligne_Plaque == false){
Premiere_Ligne_Plaque = true;
Numero_Premiere_Ligne_Plaque = Index_Ligne;
}
}
Compteur_Pixels_Bleus = 0;
}//Fin boucle Index_Ligne
//cout<<"Lignes a Conserver : "<<Compteur_Lignes_Bleus<<endl;
//PARTIE 2
//-------------------Redimenssionnement Hauteur-------------------------
Numero_Derniere_Ligne_Plaque = Numero_Premiere_Ligne_Plaque + Compteur_Lignes_Bleus;
Tableau_Hauteur_Redimensionnee = new unsigned char[Compteur_Lignes_Bleus * Largeur];
for(Index_Ligne = Numero_Premiere_Ligne_Plaque; Index_Ligne < Numero_Derniere_Ligne_Plaque; Index_Ligne++){
for(Index_Colonne = 0; Index_Colonne < Largeur; 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];
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);
CloseHandle(Descripteur);
//------------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<<"Specifier un chemin et un nom d'enregistrement pour la plaque sans le haut et le bas : ";
cin>>Nom_Fichier;
Descripteur_Redimensionnement_Hauteur = CreateFile(Nom_Fichier,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(Descripteur_Redimensionnement_Hauteur, &Mon_Entete.Fileheader, (sizeof(BITMAPFILEHEADER) - 2), &Octets_Ecrits, NULL);
//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);
WriteFile(Descripteur_Redimensionnement_Hauteur, Tableau_Hauteur_Redimensionnee, Compteur_Lignes_Bleus * Largeur, &Octets_Ecrits, NULL);
CloseHandle(Descripteur_Redimensionnement_Hauteur);
//PARTIE 3
//----------------------Detection début plaque--------------------------
Compteur_Pixels_Bleus = 0;
Tableau_Position_Plaque = new unsigned int[Mon_Entete.Infoheader.biheight];
for(Index_Ligne = 0; Index_Ligne < Mon_Entete.Infoheader.biheight; Index_Ligne++){
for(Index_Colonne = 0; Index_Colonne < Largeur; Index_Colonne++){
Mon_Pixel.Bleu = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Mon_Pixel.Vert = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];
Index_Colonne++;
Mon_Pixel.Rouge = Tableau_Hauteur_Redimensionnee[(Index_Ligne * Largeur) + Index_Colonne];
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))
{Compteur_Pixels_Bleus++;
}
if(Compteur_Pixels_Bleus > 15){
Nombre_Colonnes_Conservees++;
}
if(Compteur_Pixels_Bleus <= 15){
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){
Nombre_Colonnes_Conservees_Final = Nombre_Colonnes_Conservees;}
if(Nombre_Colonnes_Conservees_Final > Nombre_Colonnes_Conservees){
Nombre_Colonnes_Conservees_Final = Nombre_Colonnes_Conservees;}
Nombre_Colonnes_Conservees = 0;
}//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++){
Tampon_Position = Tableau_Position_Plaque[Index_Ligne];
for(Index_Colonne = 0; Index_Colonne < Nombre_Colonnes_Conservees_Final; 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];
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);
delete(Tableau_Position_Plaque);
//------------Initialisation En-Tête BMP et création fichier------------
Largeur = Nombre_Colonnes_Conservees_Final/3;
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<<"Specifier un chemin et un nom d'enregistrement pour la plaque sans cote gauche : ";
cin>>Nom_Fichier;
Descripteur_Suppression_Cote_Gauche = CreateFile(Nom_Fichier,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(Descripteur_Suppression_Cote_Gauche, &Mon_Entete.Fileheader, sizeof(BITMAPFILEHEADER) - 2, &Octets_Ecrits, NULL);
//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);
WriteFile(Descripteur_Suppression_Cote_Gauche, Tableau_Sans_Cote_Gauche, Mon_Entete.Infoheader.biheight * Nombre_Colonnes_Conservees_Final, &Octets_Ecrits, NULL);
CloseHandle(Descripteur_Suppression_Cote_Gauche);
//----------------------------------------------------------------------
getch();
return 0;
}
//----------------------------------------------------------------------
Merci d'avance =)