Appliquer un filtre à une image

Soyez le premier à donner votre avis sur cette source.

Vue 18 197 fois - Téléchargée 1 735 fois

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

Ajouter un commentaire Commentaires
Messages postés
1
Date d'inscription
lundi 5 mars 2007
Statut
Membre
Dernière intervention
5 mars 2007

votre code est bon
mais moi j'ai besoin de code en java
merci
Messages postés
2
Date d'inscription
mardi 2 mars 2004
Statut
Membre
Dernière intervention
26 janvier 2005

salut,

j'ai le meme probleme que sliver22.....

Ton code m'interrese ennormement, je voudrais en utiliser une partie pour y coller des filtres comme notamment l'amincissement homotopique (squelette),erosion, dilatation, seuillage manuel ou autre dont je dispose en magasin (si qq'un en veux).

Le seul soucis c'est que le traitement d'image associé est en java et que bof, c'est bien mais c'est lourd...

Merci
Messages postés
1
Date d'inscription
lundi 7 juillet 2003
Statut
Membre
Dernière intervention
17 juin 2004

j'ai un pb avec ta source, je la recompile avec dev/C++
et au moment de générer le fichier tempo.bmp il me créé un fichier
bitmap qui fait 0ko en taille tu avais compilé avec quel EDI ?
Messages postés
62
Date d'inscription
dimanche 22 octobre 2000
Statut
Membre
Dernière intervention
8 octobre 2006

Etant donné que j'ai indiqué plus haut que ce code fonctionnait pour une image en 256 niveaux de gris, il n'y a pas de composantes RGB pour un pixel. Il y a juste 1 pixel qui indique quel gris est utilisé dans la palette.

a+
Messages postés
1
Date d'inscription
vendredi 14 novembre 2003
Statut
Membre
Dernière intervention
16 novembre 2003

salut,
juste un petit pb je pense dans ton code, tu appliques tes filtres sur le pixel globalement et non sur chacune des composantes RGB du pixel. Fais un essai de ton programme avec une image noir et blanc (typiquement un quadrillage) et appliques un filtrage moyenneur (1 à tous les coeff et facteur de division de 9) tu verras alors ke l'image obtenue n'est pas le résultat escompté.
Mais globalement ton code est une bonne base de départ ;)
a+
Afficher les 6 commentaires

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.