Appliquer un filtre à une image

Description

Ce programme fonctionne pour des image bmp en 256 couleurs. Il est préférable d'utilise des image en niveaux de gris le résultat est plus parlant. Un filtre est simplement une matrice 3x3( dans la plupart des cas). Pour calculer la nouvelle valeur du pixel X : on prend les pixels voisins X, ce qui fait une matrice 3x3 (si le filtre est 3x3). On multiplie la matrice contenant les données par la matrice du filtre. De la matrice que l'on obtient on additionne toute les valeurs de celle-ci, ce qui donne la nouvelle valeur du pixel. Il faut faire ça pour chaque pixel. Les seuls pixel ne pouvant pas être calculer sont ceux situé au bord de l'image, car X n'aura pas tous les voisins nécessaires.

Le fichier zip contient le fichier cpp, le fichier h, et le fichier filtre.flt qui contient les caractéristique de plusieurs filtres. Le fichier h contient les prototypes des fonctions et les 2 structures utilisées.

Source / Exemple :


/*****************************************************************
                        nom: version1.cpp
                        programmé par Draven
                        le 01/07/2003

                                                                                                                                  • /
#include <stdio.h> #include <windows.h> /* BITMAPFILEHEADER, BITMAPINFOHEADER */ #include <stdlib.h> /* exit(), calloc(), free()*/ #include "filtre.h" void main() { int choix=1; /* On sort de la boucle qu'après avoir appliqué un filtre à une image ou après avoir choisi l'option Fin */ while(choix==1 || choix==3) { printf("\n1- Créer un nouveau filtre\n2- Appliquer un filtre à une image\n3- Editer un filtre\n4- Fin\n"); printf("\nChoix: "); scanf("%d",&choix); if(choix==1) creer(); else if(choix==2) appliquer(); else if(choix==3) editer(); } printf("FIN"); } /****************************************************************** nom: creer role: saisir les caractéristique d'un filtre et les placer ds un fichier
                                                                                                                                        • /
void creer(void) { int i,j,cpt; FILE * fichier; FILTRE mesfiltres; /* ouvrir le fichier en lecture ecriture, si le fichier n'existe pas, alors on le créer, et on initialise le compteur à 0*/ if((fichier=fopen("filtre.flt","rb+"))==NULL) { fichier=fopen("filtre.flt","wb+"); cpt=0; } /*si le fichier existe deja on lit le 1er octet qui contient le nombre de filtres present dans ce fichier */ else cpt=fgetc(fichier); printf("cpt = %d",cpt++); /* incrémenter le compteur */ rewind(fichier); /* revenir au début de fichier */ fputc(cpt,fichier); /* ecrire "cpt" en debut de fichier */ fseek(fichier,0x00, SEEK_END ); /*se positionner en fin de fichier*/ /* Remplir la structure "FILTRE" */ printf("Entrez le nom du filtre : "); scanf("%s",mesfiltres.nom); /*structure "FILTRE" présente dans "filtre.h"*/ for(j=0;j<3;j++) { for(i=0;i<3;i++) { printf("Entrez la valeur de la ligne %d et de colonne %d : ",j+1,i+1); scanf("%d",&mesfiltres.filtre[j][i]); } } do { /* "facteur_division" étant un coefficient de division cette valeur ne doit pas valoir 0*/ printf("Entrez la valeur du facteur de division(la plupart du tps cette valeur est à 1): "); scanf("%d",&mesfiltres.facteur_division); if(mesfiltres.facteur_division==0) printf("Valeur impossible, cela produit une division par 0\n"); } while(mesfiltres.facteur_division==0); printf("Entrez la valeur du Bias (la plupart du tps cette valeur est à 0) : "); scanf("%d",&mesfiltres.bias); /* écrire la structure remplie dans le fichier */ fwrite(&mesfiltres,sizeof(FILTRE),1,fichier); /*fermer le fichier*/ fclose(fichier); } /***************************************************************** nom: appliquer role: appliquer un filtre sur une image
                                                                                                                                      • /
void appliquer(void) { int cpt,nbr_filtre,choix; char nom_fichier[25]; FILE * source; /* fichier de l'image d'origine*/ FILE * destination; /* fichier de l'image traitée */ FILE * fichier; /* fichier contenant les filtres */ HEADER header; FILTRE mes_filtres[50]; /*tester si l'ouverture du fichier*/ if((fichier=fopen("filtre.flt","r"))==NULL) { printf("Aucun filtre créé\n"); } else { /* ouvrir le fichier contenant l'image d'origine */ printf("\nEntrez le nom du fichier bmp dont vous souhaitez appliquer un filtre: "); scanf("%s",nom_fichier); if((source=fopen(nom_fichier,"rb"))==NULL) { printf("erreur à l'ouverture du fichier\n"); exit(-1); } /* créer un fichier de destination pour recopier une partie du fichier source*/ if((destination=fopen("tempo.bmp","wb"))==NULL) { printf("erreur à l'ouverture du fichier\n"); exit(-1); } /* lire le 1er caractère contenant le nombre de filtres dans le fichier */ nbr_filtre=fgetc(fichier); printf("nbr_filtre = %d\n\n",nbr_filtre); /* récupérer les données des filtres */ for(cpt=0;cpt<nbr_filtre;cpt++) fread(&mes_filtres[cpt],sizeof(FILTRE),1,fichier); /* afficher le nom des filtres */ for(cpt=0;cpt<nbr_filtre;cpt++) printf("%d- %s\n",cpt+1,mes_filtres[cpt].nom); printf("\nEntrez le numéro du filtre à appliquer sur l'image : "); scanf("%d",&choix); choix=choix-1; /* on soustrait 1 à "choix" car comme tjs en informatique on débute à 0*/ /************* debut du traitement des fichiers images **********/ header=en_tete(source,header,nom_fichier); changer(source,destination,header); traitement(source,destination, header,mes_filtres[choix]); printf("traitement terminé\n"); /* fermer les fichiers */ fclose(source); fclose(destination); fclose(fichier); /* le nom du fichier traité sera tempo.bmp je n'ai pas voulu supprimer le fichier d'origne car avec certain filtre l'image sera toute noir ou toute blanche. Ca serait bête de perdre l'image d'origine*/ } } /****************************************************************** nom: editer role: modifier les paramètres d'un filtre dans la liste
                                                                                                                                    • /
void editer(void) { int i,j,cpt; int choix,nbr_filtre; FILE * fichier; FILTRE mesfiltres[50]; /* ouverture en lecture/écriture */ if((fichier=fopen("filtre.flt","rb+"))==NULL) { printf("Aucun filtre à modifier\n"); } else { nbr_filtre=fgetc(fichier); printf("nbr_filtre = %d\n\n",nbr_filtre); /* lecture des filtres du fichier et afficher leurs noms */ for(i=0;i<nbr_filtre;i++) fread(&mesfiltres[i],sizeof(FILTRE),1,fichier); for(i=0;i<nbr_filtre;i++) printf("%d- %s\n",i+1,mesfiltres[i].nom); printf("Entrez le numero du filtre à modifier : "); scanf("%d",&choix); choix=choix-1; /* on soustrait 1 à "choix" car comme tjs en informatique on débute à 0*/ /* saisir les nouvelles caractéristiques du filtre */ printf("Entrez le nom du filtre : "); scanf("%s",mesfiltres[choix].nom); for(j=0;j<3;j++) { for(i=0;i<3;i++) { printf("Entrez la valeur de la ligne %d et de colonne %d : ",j+1,i+1); scanf("%d",&mesfiltres[choix].filtre[j][i]); } } do { printf("Entrez la valeur du facteur de division(la plupart du tps cette valeur est à 1): "); scanf("%d",&mesfiltres[choix].facteur_division); if(mesfiltres[choix].facteur_division==0) printf("Valeur impossible, cela produit une division par 0\n"); } while(mesfiltres[choix].facteur_division==0); printf("Entrez la valeur du Bias (la plupart du tps cette valeur est à 0) : "); scanf("%d",&mesfiltres[choix].bias); /*se positionner à l'endroit ou sont stockés les anciennes caractériste du filtre*/ fseek(fichier,sizeof(FILTRE)*choix+1,SEEK_SET ); /* écrire par dessus les nouvelles caractéristique de ce filtre */ fwrite(&mesfiltres[choix],sizeof(FILTRE),1,fichier); fclose(fichier); } } /***************************************************************** nom: en_tete role: lire l'en-tete du fichier bitmap passé en parametre
                                                                                                                                  • /
HEADER en_tete(FILE* fd,HEADER header,char *nom_fichier) { fread(&header,sizeof(HEADER),1,fd); /* lire les 54 premiers octets qui constitue l'en-tete */ /* tester si les 2 premiers octets sont B et M */ if(header.file.bfType!=0x4D42) { printf("%s n'est pas un fichier bitmap\n",nom_fichier); fclose(fd); exit(-1); } /* tester si l'image est en 256 couleurs */ if(header.info.biBitCount!=8) { printf("Le fichier %s n'est pas en 256 couleurs\n",nom_fichier); fclose(fd); exit(-1); } printf("Lecture header terminée\n"); return header; } /****************************************************************** nom: changer role: modifier l'en-tête du fichier destination, et recopier la palette
                                                                                                                                      • /
void changer(FILE *source,FILE* destination,HEADER header) { int i,tempo; /*modification de l'en-tête on réduit la largeur et la hauteur de l'image de 2 car on ne peut pas calculer la nouvelle valeur des pixels du contour de l'image */ header.info.biHeight=header.info.biHeight-2; header.info.biWidth=header.info.biWidth-2; /* copie de l'entete bmp (54 premiers octets) de le fichier "tempo.bmp" */ fwrite(&header,sizeof(HEADER),1,destination); /* recopie de la palette soit en niveaux de gris soit en 256 couleurs*/ for(i=0;i<256*4;i++) { tempo=fgetc(source); fputc(tempo,destination); } printf("Header et palette terminés\n"); } /***************************************************************** nom: traitement role: calcul la nouvelle valeur des pixels
                                                                                                                                    • /
void traitement(FILE *source ,FILE *destination, HEADER header, FILTRE mon_filtre) { int hauteur,largeur,largeur_source,largeur_destination; int bourrage_source,bourrage_destination; int ligne1,ligne2,ligne3,nouv_valeur; int l_filtre; int i,j,h; int **donnee; printf("Debut traitement\n"); largeur=(int)header.info.biWidth; hauteur=(int)header.info.biHeight; fseek(source,0x436,SEEK_SET); fseek(destination,0,SEEK_END); /* calcul du bourrage pour l'image d'origine*/ largeur_source=largeur; while((largeur_source%4)!=0) largeur_source++; bourrage_source=largeur_source-largeur; /* calcul du bourrage pour l'image modifiée*/ largeur_destination=largeur-2; while((largeur_destination%4)!=0) largeur_destination++; bourrage_destination=largeur_destination-(largeur-2); /**************** créer la matrice de données ******************/ /* "donnee" pourrait être définit comme une matrice qui contiendra la donnée de l'image*/ donnee=(int **)calloc(hauteur,largeur); for(i=0;i<hauteur;i++) { donnee[i]=(int *)calloc(largeur,sizeof(int)); for(j=0;j<largeur;j++) donnee[i][j]=fgetc(source); /* récupérer la donnée dans le fichier et la placer dans la matrice */ /* avancer du nombre d'octet de bourrage de l'image en 16 millions de couleurs*/ fseek(source,bourrage_source,SEEK_CUR); } /* afficher la hauteur et la largeur de l'image d'origine */ printf("largeur= %d\nhauteur=%d\n",largeur,hauteur); /************** debut du traitement *************************/ for(h=0;h<(hauteur-2);h++) /* faire pour chaque ligne de la matrice */ { for(i=0;i<(largeur-2);i++) /* faire pour chaque colonne de la matrice */ { /* réinitialiser ces variables */ l_filtre=0; ligne1=0; ligne2=0; ligne3=0; /**********calcul de la nouvelle valeur du pixel************/ for(j=i;j<(i+3);j++) { ligne1=donnee[h][j]*mon_filtre.filtre[0][l_filtre]+ligne1; ligne2=donnee[h+1][j]*mon_filtre.filtre[1][l_filtre]+ligne2; ligne3=donnee[h+2][j]*mon_filtre.filtre[2][l_filtre]+ligne3; l_filtre++; } /*"nouv_valeur" contient la nouvelle valeur du pixel */ nouv_valeur=(ligne1+ligne2+ligne3)/mon_filtre.facteur_division-mon_filtre.bias; /*la valeur d'un pixel ne peut être compris qu'entre 0 et 255 */ if(nouv_valeur<0) nouv_valeur=0; else if(nouv_valeur>0xFF) nouv_valeur=0xFF; /* écrire cette nouvelle valeur dans le fichier */ fputc(nouv_valeur,destination); } /* écrire les bourrages de 0 dans le fichier */ for(i=0;i<bourrage_destination;i++) fputc(0x00,destination); } free(donnee); /* libérer l'espace alloué en mémoire */ }

Conclusion :


Si vous connaissez d'autre filtres, ça serait sympas de me les communiquer car les seuls que je connaisse sont dans le fichier filtre.flt

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.