Comparateur d'images de console monochrome de base et création d'un fichier de différence.

Description

"Extrait de ce qui est demandé dans le cadre de ce projet:

A Spécifications
A.1 Entrée
Le programme à réaliser possède deux entrées, plus précisément deux images.
Ces deux images sont contenues dans deux fichiers. Le premier fichier est
nommé ref.img et le second app.img. Ces fichiers sont conformes à la spécification
des fichiers .img à la section A.2.
A.2 Format des fichiers .img
Les fichiers .img sont des fichiers texte (ANSI) qui contiennent sur leur première
ligne la taille de la matrice qui se trouve aux lignes suivantes. Le premier
entier correspond à la taille verticale et le second entier correspond à la taille
horizontale. Les images à comparer n'auront jamais plus de 64 lignes et jamais
plus de 64 colonnes. La taille minimale d'une image est 1 ligne et 1 colonne.
La matrice contenant l'image est écrite, une ligne à la fois et les valeurs des
pixels sont séparés par des espaces.
Voici un exemple de fichier :
3 2
0 1 1
0 0 1
Tous les fichiers qui seront utilisés lors de l'évaluation du programme seront
bien formés (ne contiendront rien qui déroge à la spécification). Rappel : la
première ligne donne le nombre de colonnes et le nombre de lignes.
A.3 Sortie
Deux scénarios sont possibles lors de l'exécution du programme. D'une part,
les images peuvent être de même taille ce qui rend la comparaison possible.
D'autre part, les images n'ont pas la même taille et la comparaison n'est pas à
effectuer.
A.3.1 Tailles identiques
Si les tailles sont identiques plusieurs sorties sont attendues. D'abord, en ce
qui concerne la console le message Image analysis is starting... doit
15
apparaître. Par la suite, sur une deuxième ligne Reference: doit être affiché
suivi, sur les lignes subséquentes, de l'image de référence. Sur une nouvelle
ligne à nouveau, le message Image: doit précéder l'image à analyser. Finalement,
les résultats doivent être affichés soit le nombre de pixels identiques,
le nombre de pixels différents et le coefficient de ressemblance. Les deux premiers
doivent être affichés avec des valeurs entières et le coefficient de ressemblance
doit être affiché avec exactement quatre chiffres après la virgule.
Le format d'affichage pour les images à la console est un peu particulier, les
pixels noirs sont représentés par la lettre M majuscule et les pixels blancs par
un point.
Finalement, un fichier de sortie diff.img est attendu. Ce fichier doit bien sûr
respecter la spécification de la section A.2. Les pixels de cette nouvelle image
doivent être blancs 0 ou 1 si les pixels correspondants aux deux images sont
identiques ; dans le cas d'une différence, il faut afficher la lettre D majuscule.
Finalement le message Image analysis is done. doit apparaître.
Un exemple d'utilisation est présenté à la section A.5.
A.3.2 Tailles différentes
Dans le cas où les tailles sont différentes, la sortie de votre programme doit
être la suivante :
Image analysis is starting...
ABORT: Sizes do not match!
Aucun fichier de sortie n'est attendu.
A.4 Squelette
Il est également nécessaire d'utiliser le fichier squelette.cpp qui servira de
base à votre programme. La fonction main ne doit en aucun cas être modifiée.
De plus, vos fonctions doivent absolument se trouver dans la zone 2 située
après la fonction main, mais vous devez également placer quelques lignes de
code dans la zone 1 soit avant la fonction main.

Source / Exemple :


// Génie Informatique, Université de Sherbrooke, session 1
// APP 3
// Fichier source
//
// Auteur: 
// Nom: Pascal Guay
// Website: http://pascalnet.net

//
// Zone1 : quelques lignes de C++  (maximum 25 lines)
//
//Inclut les librairies au préprocesseur.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
using namespace std; //utilisation de l'espace de nom std.
//Déclaration des prototypes des fonctions utilisés.
void Init();
void LoadImg(char [],int [],int &,int &);
bool DimMatch(int, int, int, int);
void PrintImg(int [],int,int);
void Fail();
int DiffImg(int [], int [],char [],int, int);
int ComputeTotal(int,int);
void PrintResults(int,int);
void SaveImg(char [], char [], int, int);
void Finish();

const int MAX_SIZE = 64; //Grandeur maximale des colonnes et lignes de l'image.

//
// Fin de la Zone 1
//

//
// ZONE INTERDITE (AUCUNE MODIFICATION PERMISE)
//

int main()
{
    int r = 0; //Variable de retour, retourne 1 en cas d'erreur.

    int aRef[MAX_SIZE*MAX_SIZE] = {0}; //Déclaration du tableau de l'image de référence.
    int cRowRef = 0, cColRef = 0; //Déclaration des lignes et colonnes de l'image de référence.

    int aApp[MAX_SIZE*MAX_SIZE] = {0}; //Déclaration du tableau de l'image à comparer.
    int cRowApp = 0, cColApp = 0; //Déclaration des lignes et colonnes de l'image à comparer.

    char aDif[MAX_SIZE*MAX_SIZE] = {0}; //Déclaration du tableau différentiel de la comparaison des deux images.
    int cIP = 0, cTotal = 0; //Déclaration de la variable des pixels identiques et des pixels totaux afin de trouver le coefficient de ressemblance.
 //L'explication de chaque fonction est fournie plus bas.
    Init(); // f1

    LoadImg("ref.img", aRef, cRowRef, cColRef); // f2
    LoadImg("app.img", aApp, cRowApp, cColApp); // f2
    
    if (!DimMatch(cColRef, cRowRef, cColApp, cRowApp)) // f3
    {
        Fail(); // f4
        r = 1;
    }
    else
    {
        cout << "Reference:" << endl;
        PrintImg(aRef, cRowRef, cColRef); // f5

        cout << "Image:" << endl;
        PrintImg(aApp, cRowApp, cColApp); // f5

        cIP = DiffImg(aRef, aApp, aDif, cRowRef, cColRef); // f6
        cTotal = ComputeTotal(cRowRef, cColRef); // f7

        PrintResults(cIP, cTotal); // f8

        SaveImg("diff.img", aDif, cRowRef, cColRef); // f9

        Finish(); // f10 
    }

    return r;
}
//
// Fin de la ZONE INTERDITE
// 

//
// Zone2 : vous pouvez mettre vos fonctions ici
//

/*Explication de la fonction F1 Init();
Cette fonction sert à afficher un message d'initialisation afin d'indiquer le début de l'analyse de l'image.

  • /
void Init(){ cout << "Image analysis is starting..." << endl; } /* Explication de la fonction F2 LoadImg(...); Cette fonction utilise le paramètre FileName[] qui est un tableau de type Char afin de stocker le nom du fichier, elle utilise aussi le tableau unidimensionnel Table[] de type int afin de stocker les valeurs des pixels de l'image du fichier FileName. Finalement les variables &Row et &Col sont déclaré comme faisant référence aux variables cRow.. et cCol.. cela permet de les modifier dans la fonction pour que leurs changements s'inscrivent dans les variables déclarées en main();, cela est possible, car les variables références utilises la même adresse mémoire que leur variable et par conséquent permette même de sauver l'utilisation de la mémoire dans le programme. Le programme crée un objet ifstream appelé InputFile qui sert à ouvrir le fichier image. Il fait ensuite la lecture des premiers octets de l'image qui correspondent au nombre de colonnes, suivi de la lecture du nombre de lignes. Ensuite il inscrit toutes les valeurs des pixels de l'image dans le tableau Table[].
  • /
void LoadImg(char FileName[], int Table[], int &Row, int &Col){ // Passage par référence pour Row et Col afin que leur valeur devienne la même pour les variables déclarées en main(); ifstream InputFile; //Création de l'objet pour lecture InputFile.open(FileName); //ouverture du fichier .img if(!InputFile){ //Si le fichier n'est pas trouvé par exemple cout << "Error opening file." << endl; //Si le fichier n'est pas trouvé par exemple exit(0); } InputFile >> Col; //Lecture du fichier .img et inscription de la valeur colonne dans la variable Col. InputFile >> Row; //Lecture du fichier .img et inscription de la valeur ligne dans la variable Row. if(Col > 64 || Row > 64){ //Vérifie si les dimensions de l'image dépasse les limites permises. cout << "The size of the image must not be over 64x64." << endl; exit(0); //quitte le programme }else if(Col < 1 || Row < 1){ //Vérifie si les dimensions de l'image sont inférieures aux limites permises. cout << "The size of the image must not be under 1x1." << endl; exit(0); //quitte le programme } for(int i =0;i<Row*Col; i++){ InputFile >> Table[i]; //inscrit les valeurs de chaque pixel de l'image dans le tableau unidimensionnel Table[]. } InputFile.close(); //fermeture du fichier .img } /* Explication de la fonction F3 DimMatch(...); Cette fonction sert à vérifier si les deux images à comparer sont de la même taille. Si les colonnes et les lignes sont identiques entre elles alors la fonction booléenne retourne vraie, sinon elle retourne faux.
  • /
bool DimMatch(int ColRef, int RowRef, int ColApp, int RowApp){ if(ColRef == ColApp && RowRef == RowApp){ //comparaisons entre les colonnes et lignes respectives de l'image. return true; }else{ return false; } } /* Explication de la fonction F4 PrintImg(...); Cette fonction sert à afficher les images dans la console. Dans cet affichage, "M" correspond à un pixel noir et "." à un pixel blanc. Afin de vérifier la fin de chaque colonne, un modulo est utilisé pour vérifier.
  • /
void PrintImg(int Image[], int Row, int Col){ for(int i = 0; i<Row*Col; i++){ if(Image[i] == 1){ cout << "M"; //Pixel noir }else{ cout << "."; //Pixel blanc } if((i+1) % Col == 0){ //Vérification de fin de colonne. cout << "\n"; //Saute à une autre colonne. } } } /* Explication de la fonction F5 DiffImg(...); Cette fonction sert à extraire les différences entre les deux images tout en construisant les pixels de différences dans le tableau ImgDif[], Elle retourne aussi le nombre de pixels identiques afin qu'ils soient stockés dans la variable cIP dans le main();
  • /
int DiffImg(int ImgRef[], int ImgApp[], char ImgDif[],int Row, int Col){ int ICount = 0; //initialise ICount afin de stocké le nombre identique de pixel dans l'image. for(int i = 0; i<Row*Col; i++){ if(ImgRef[i] != ImgApp[i]){ ImgDif[i] = 'D'; //Inscrit la lettre D à l'endroit ou le pixel est différent. }else{ ICount++; //Incrémente la variable ICount. ImgDif[i] = (char)(ImgRef[i] + 48); //Tranforme la valeur 0 qui est un caractère ASCII 48 en variable de type char. 0 + 48 = "0", 1+48 = 49 = "1" } } return ICount; //Retourne le nombre de pixels identiques. } /* Explication de la fonction F6 ComputeTotal(...); Cette fonction retourne le nombre de pixels total dans l'image en multipliant Row par Col.
  • /
int ComputeTotal(int Row, int Col){ return Row * Col; //Retourne le nombre total de pixels à la variable cTotal dans le main();. } /* Explication de la fonction F7 PrintResults(...); Cette fonction sert à afficher le nombre de pixels identiques dans l'image (IP), le nombre de pixels différents (DP), ainsi que le coefficient de ressemblance (C). Il est à noter la transformation des variables en type double afin de permettre l'affichage de chiffre à virgule.
  • /
void PrintResults(int IP, int Total){ cout << showpoint << fixed << setprecision(4); //Format pour obtenir quatre chiffres après la virgule. cout << "Results: IP=" << IP << " DP=" << Total - IP << " C=" << static_cast<double>(IP)/static_cast<double>(Total) << endl; } /*Explication de la fonction F8 SaveImg(...); Cette fonction sert à sauvegarder le fichier de différence. Il inscrit dans le fichier les données du tableau ImgDif.
  • /
void SaveImg(char FileName[],char ImgDif[], int Row, int Col){ ofstream OutputFile; //Création de l'objet pour écrire. OutputFile.open(FileName); //Ouvre le fichier où l'on veut écrire. OutputFile << Col << " " << Row << "\n"; //Inscrit le nombre de colonnes et de lignes de l'image. for(int i = 0; i<Row*Col; i++){ OutputFile << ImgDif[i] << " "; //Inscrit les pixels et les différences qui étaient stockés dans le tableau ImgDif[] à l'intérieur du fichier. if((i+1) % Col == 0){ OutputFile << "\n"; //Change de ligne à la fin d'une colonne. } } cout << "The differences file called: " << FileName << " has been created with success." << endl; //Message qui affiche la création du fichier. OutputFile.close(); //Fermeture du fichier. } /*Explication de la fonction F9 Finish(); Cette fonction affiche un message lorsque le traitement de l'image est complété.
  • /
void Finish(){ cout << "Image analysis is done." << endl; } /*Explication de la fonction F10 Fail(); Cette fonction affiche un message lorsque les tailles des images ne sont pas compatibles.
  • /
void Fail(){ cout << "ABORT: Sizes do not match!" << endl; } // // Fin de la zone2 //

Conclusion :


Le programme fonctionne bien, les demandes furent atteintes avec succès.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.