Accueil > > > TRAITEMENTS D'IMAGES AU FORMAT PGM AVEC LES ALGORITHMES DE CONVOLUTION, DE K-MEANS ET DE OTSU
TRAITEMENTS D'IMAGES AU FORMAT PGM AVEC LES ALGORITHMES DE CONVOLUTION, DE K-MEANS ET DE OTSU
Information sur la source
Description
La source ici présenté est constituée, notamment de : - un fichier algorithmes.h : qui regroupent en son sein les différentes méthodes de gestion de l'interface et les algorithmes de convolution, de k-means et autres; - un fichier application.c représentant l'application qui est lancé à partir d'un makefile - un Readme et un dossier images contenant quelques images pgm pour les tests
Source
- --- Le fichier algorithmes.h ---
- // Charles MOUTE --> 03X202
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <math.h>
- #include <curses.h>
-
-
- #define taille 256
- #define diese '#'
- #define p5 "P5"
- #define p6 "P6"
-
-
- /* Types */
-
-
- /*Constantes pour interfaces */
-
- #define KEY_ESCAPE 27 /* Représente le bouton echape */
- #define MAX_STRING 1024 /* Longueur maximale d'une réponse */
- //#define MAX_NAMEFILE 80 /* Longueur max d'un chemin menant à un fichier image */
- #define MESSAGE_ROW 6 /* Ligne affichant des messages divers */
- #define ERROR_ROW 22 /* Ligne signalant les messages */
- #define QUESTION_ROW 20 /* Ligne pour les questions */
- #define PROMPT_ROW 18 /* LIGNE de prompt */
-
-
- // Type definissant les proprietes d'une image.
- typedef struct image_properties {
- int width ; // largeur de l'image.
- int height ; // hauteur de l'image.
- char* format; // Format de l'image.
- int valuePixel; // valuer maximale des pixels de l'image.
- char* nameFile; // nom du fichier image.
- unsigned char* image; // contenu de l'image.
- } properties ;
-
-
- // Type definissant la structure d'un element dans l'algorithme de k-means.
- typedef struct item_kmeans {
- int numCluster ; // Represente le numero de cluster au quel l'elt est affecte.
- int distance ; // Represente la distance de l'elt au centre du cluster auquel il appartient.
- } item ;
-
- // Type definissant la structure d'un cluster dans l'algorithme de k-means.
- // Le centre d'un cluster est la moyenne des valuers des pixels qu'il contient.
- typedef struct cluster_kmeans {
- int centroide; //Represente le centre du cluster.
- int size; //Represente le nombre d'elt contenu dans le cluster.
- } cluster ;
-
- /* Variables */
-
- properties info ; // proprietes d'une image de nom info.nameFile.
- int* histogramme ; // est l'histogramme de info.nameFile. de taille valuePixel.
- int* image; // image est la representation sous forme matricielle de info.image.
- int* result;// result est l'image resultante de l'application d'une operation sur info.image.
-
-
- int otsuSeuil ; //represente le seuil donnee par l'algorithme de otsu.
-
- int K ; // Represente le nombre de cluster que k-means doit definr.
- int variance_limit = 100; //Represente la limite en dessous de laquelle k-means ne doit effectue de traitement.
- int min_modif;//Represente le min de modification de clusters en dessus du quel on les considere instables.
- cluster* clusters; // Represente les k clusters que k-means devra definir.
- item* items; //Representent les pixels de l'image regroupés en cluster.
-
-
- char* nameFile ; //Nom donne a l'image resultante des operations subies par info.image.
-
-
- /* Operations */
-
-
- // Initialise toutes les variables par des valeurs par defaut.
- void default_init() {
-
- int i,j;
-
- /*pour info*/
- info.width = -1 ;
- info.height = -1 ;
- info.format = NULL ;
- info.valuePixel = -1 ;
- info.nameFile = NULL ;
- info.image = NULL ;
- //info.image = (unsigned char*)malloc(taille*taille);
-
- /*pour histogramme de l'image */
- histogramme = NULL ;
-
- // pour le nom de fichier
- nameFile = NULL ;
-
- //pour la representation matricielle de info.image
- image = NULL ;
-
- //pour le resultat matricielle d'une operation subie par info.image
- result = NULL ;
-
- //pour seuil de otsu
- otsuSeuil = -1 ;
-
- //Pour l'algorithme de k-means
- K = -1 ;
- clusters = NULL ;
- items = NULL ;
-
- }
-
-
- // Libere les espaces memoires alloues
- void free_memory() {
-
- if (items!=NULL) { free(items); items = NULL; }
- if (image!=NULL) { free(image); image = NULL; }
- if (result!=NULL) { free(result); result = NULL; }
- if (clusters!=NULL) { free(clusters); clusters = NULL; }
- if (nameFile!=NULL) { free(nameFile); nameFile = NULL; }
- if (info.format!=NULL) { free(info.format); info.format = NULL; }
- if (info.image!=NULL) { free(info.image); info.image = NULL ; }
- if (histogramme!=NULL) { free(histogramme); histogramme = NULL ; }
- if (info.nameFile!=NULL) { free(info.nameFile); info.nameFile = NULL; }
-
- }
-
- // Retourne la largeur de l'image courrante.
- int getImageWidth() { return info.width ; }
-
- //Retourne la hauteur de l'image courante.
- int getImageHeight() { return info.height ; }
-
- //Retourne la valeur maximale des pixels de l'image.
- int getImageMaxValuePixel() { return info.valuePixel; }
-
- //Retourne le format de l'image courante.
- char* getImageFormat() { return info.format ; }
-
- //Retourne le nom de l'image courante.
- char* getImageName() { return info.nameFile ; }
-
- //Retourne le contenu de l'image courante.
- unsigned char* getImageContent() { return info.image ; }
-
- //Retourne le nom de l'image modifiee.
- char* getNameFile() {return nameFile; }
-
- //Retourne le resultat effectue sur l'image.
- int* getOperationResult() { return result; }
-
- //Retourne le seuil de Ostu.
- int getOtsuSeuil() { return otsuSeuil; }
-
- //Obient les proprietes du fichier passee en parametre
- void getPropertiesOf(char* file) {
-
- FILE *f;
- char *row =(char*)malloc(taille),*param=(char*)malloc(taille);
-
- f = fopen(file,"r");
-
- if(f) {
-
- // Recherche format de l'image
- fgets(row,taille,f);
- info.format = (char*) malloc((sizeof(char))*(strlen(row))) ;
- strcpy(info.format,row);
- info.format[(strlen(row))-1] = '\0';
-
- if (strcmp(p5,info.format)==0 || strcmp(p6,info.format)==0 ) {
-
- if(!feof(f)){
-
- fgets(row,taille,f);
-
- //Effacement des eventuels commentaires dans le fichier
- while(row[0]==diese&&!feof(f)){
- fgets(row,taille,f);
- }
-
- // Recherche des dimensions de l'image
- if(row[0]!=diese){
- row[strlen(row)]='\0';
- info.width = atoi(strtok(row," "));
- info.height = atoi(strtok(NULL," "));
-
- // Recherche de la valeur maximale des pixels
- if(!feof(f)){
- fgets(row,taille,f);
- row[strlen(row)]='\0';
- info.valuePixel = atoi(strtok(row," "));
-
- info.nameFile = (char*)malloc( (sizeof(char))* (strlen(file)) );
- strcpy(info.nameFile,file);
-
- if(!feof(f)){
- info.image = (unsigned char*)malloc(info.width*info.height);
- fread(info.image,sizeof(unsigned char),info.width*info.height,f);
- }
- }
- }
- }
- } else{
- mvprintw(ERROR_ROW,5,"Le fichier %s n'est pas au format P5 ou P6",file);
- free_memory();
- }
- fclose(f);
- }else {
- mvprintw(ERROR_ROW,5,"Impossible d'ouvrir %s",file);
- free_memory();
-
- }
- free(row);
- free(param);
- }
-
-
- //Initialise le nom que l'on donnera a l'image resultante d'une operation sur info.image
-
- void initNameFile(char* nameUser){
-
- //En cas de PB enlever les commentaires et les mettre ou ils doivent se trouvent
-
- char* file,*nomFichier,*extension,str[]="_modified",point[]=".",*name,ext[]=".pgm";
-
- if(nameFile!=NULL) { free(nameFile); nameFile = NULL; }
-
- if(info.nameFile!=NULL) {
-
- name = (char*)malloc(strlen(info.nameFile)+1);
- sprintf(name,"%s\0",info.nameFile);
-
- file = (strrchr(name,'/')+1);
-
- if(file==NULL) file = (strrchr(name,'\\')+1);
-
- if(file==NULL) file = name ;
-
- //extension = strrchr(file,'.')+1;
- nomFichier = strtok(file,".");
-
- if(nameUser!=NULL){
-
- char ext_name [strlen(nameUser)+1];
- sprintf(ext_name,"%s",nameUser);
-
- nameFile=(char*)malloc(strlen(nomFichier)+strlen(ext_name)+strlen(ext)+1);
- sprintf(nameFile,"%s%s%s",nomFichier,ext_name,ext);
-
- //nameFile=(char*)malloc(strlen(nomFichier)+strlen(ext_name)+strlen(point)+strlen(extension)+1);
- //sprintf(nameFile,"%s%s%s%s",nomFichier,ext_name,point,extension);
-
- }else{
-
- nameFile = (char*)malloc(strlen(nomFichier)+strlen(str)+strlen(ext)+1);
- sprintf(nameFile,"%s%s%s",nomFichier,str,ext);
-
- //nameFile = (char*)malloc(strlen(nomFichier)+strlen(str)+strlen(point)+strlen(extension)+1);
- //sprintf(nameFile,"%s%s%s%s",nomFichier,str,point,extension);
- }
- free(name);
- }
- }
-
- //Obtient l'histogramme de l'image courante
- void getImageHistogramme() {
-
- if(info.image!=NULL){
- int i ,length ;
- int max = taille;
- //int max = info.valuePixel+1;
- if(max!=-1){
- histogramme =(int*)malloc((sizeof(int))*max);
- for(i=0;i<max;i++) histogramme[i] = 0;
- length = strlen(info.image);
- for(i=0;i<length;i++) histogramme[info.image[i]]++;
- }
-
- }
-
- }
-
- // Creer la forme matricielle de l'image courante
- void createImageMatrix() {
-
- int i,j,k=0 ;
-
- if(info.image!=NULL) {
-
- image = (int*)malloc((sizeof(int))*(info.height*info.width));
- int* matrix = image ;
-
- for(i=0;i<info.height;i++) for(j=0;j<info.width;j++) {*matrix = 0 ; matrix++;}
-
- matrix = image ;
- for(i=0;i<info.height;i++) {
- for(j=0;j<info.width;j++) {
- *matrix = (int) info.image[k];
- matrix++;
- k++;
- }
- }
-
- }
-
- }
-
-
- //Obtient d'une representation matricielle le contenu d'une image.
- unsigned char* getImageOf(const int* matrix) {
-
- if(info.image!=NULL){
- unsigned char* _image = (unsigned char*)malloc(info.height*info.width);
- int i,j,k=0,val;
- for(i=0;i<info.height;i++){
- for(j=0;j<info.width;j++){
-
- val = (unsigned char) (*matrix);
- if(val>info.valuePixel) val = info.valuePixel ;
- if(val<0) val = 0 ;
-
- _image[k] = val ;
- k++;
- matrix++;
- }
- }
- return _image ;
- }else return NULL ;
-
- }
-
- // Obtient de la matrice courante, le contenue de l'image originelle
- unsigned char* getImageOfCurrent() {
- return getImageOf(image) ;
- }
-
-
- /* Obtient de la matrice resultante d'une operation sur l'image originelle.
- Le contenue de l'image originelle modifiee par l'application de l'operation.
- */
-
- unsigned char* getImageOfResult() {
- return getImageOf(result) ;
- }
-
-
- //Initialise toutes les variables en regroupant les fonctioons adequates
- void init_variables(char* file){
-
- default_init();
- getPropertiesOf(file);
- initNameFile(NULL);
- getImageHistogramme();
- createImageMatrix();
- }
-
-
- // Affiche a l'ecran les proprietes de l'image courante, celle stockee dans info.image
- void displayImageProperties(){
-
- mvprintw(MESSAGE_ROW,5,"Image :%s",info.nameFile);
- mvprintw(MESSAGE_ROW+2,5,"----- Proprietes de l'image -----");
- mvprintw(MESSAGE_ROW+4,5," Format de l'image :%s",info.format);
- mvprintw(MESSAGE_ROW+5,5," Largeur de l'image :%d",info.width);
- mvprintw(MESSAGE_ROW+6,5," Hauteur de l'image :%d",info.height);
- mvprintw(MESSAGE_ROW+7,5," Valeur Max des pixels de l'image :%d",info.valuePixel);
-
- }
-
-
- void displayContent(const unsigned char * _image){
-
- int i,size ;
-
- if(_image==NULL)
- mvprintw(MESSAGE_ROW+2,5," Contenue de l'image : [ Empty Image ] ");
- else {
- mvprintw(MESSAGE_ROW+2,5," Contenue de l'image : ");
- size = strlen(_image);
- mvprintw(MESSAGE_ROW+3,5,"[");
- for(i=0;i<size;i++){
- if(i==(size-1 )) printw("%d",_image[i]);
- else printw("%d, ",_image[i]);
- }
- printw("]");
- }
-
- }
-
- //Affiche a l'ecran le contenu de l'image :
- void displayImageContent() {
- mvprintw(MESSAGE_ROW,5,"----- Image originelle -----");
- displayContent(info.image);
- }
-
-
- // Affiche a l'ecran l'histogramme de l'image courante, celle stockee dans info.image
- void displayImageHistogramme(){
- int j,length ;
- mvprintw(MESSAGE_ROW,5,"----- Histogramme de %s -----",info.nameFile);
- if(histogramme==NULL) printw(" [ Empty Histogramme-Aucune Image de selectionnee ]");
- else {
- length = info.valuePixel+1;
- printw("[");
- for(j=0;j<length;j++){
- if(j==(length-1)) printw("%d",histogramme[j]);
- else printw("%d, ",histogramme[j]);
- }
- printw("]");
- }
- }
-
-
-
- // Affiche a l'ecran le contenu de la representation matricielle, _image, du fichier file.
- void displayMatrix(char* file, int* _image){
- int i,j;
- mvprintw(MESSAGE_ROW+1,5," Matrice de %s : ",file);
- if(_image==NULL) printw("[ Empty Matrix ]");
- else {
- int* matrix = _image ;
- printw("[");
- for(i=0;i<info.height;i++){
- printw("[");
- for(j=0;j<info.width;j++){
- if(j==(info.width-1)) printw("%d",*matrix);
- else printw("%d,",*matrix);
- matrix++;
- }
- if(i==(info.height-1)) printf("]");
- else printw("],\n");
- }
- printw("]");
- }
- }
-
-
- /* Affiche a l'ecran le contenu de la matrice de l'image courante. Celle contenu dans info.image */
- void displayImageMatrix() {
- mvprintw(MESSAGE_ROW,5,"----- Image originelle -----");
- displayMatrix(info.nameFile,image);
- }
-
-
- /* Affiche a l'ecran le contenu de la matrice resultante d'une operation sur l'image courante.*/
- void displayResult() {
- mvprintw(MESSAGE_ROW,5,"----- Resulat Operation sur image originelle -----");
- displayMatrix(nameFile,result);
- }
-
-
- /* Cree une image de nom nameFile, de largeur info.width, de hauteur info.height et
- de valeur maximale de pixel info.valuePixel a partir du contenu de la representation matricielle d'une
- image, nomee matrix.
-
- */
- void rewriteImage(int* matrix){
-
- FILE *f;
- if(nameFile!=NULL && matrix!=NULL) {
- f = fopen(nameFile,"w");
- if(!f) mvprintw(ERROR_ROW,5,"Erreur::Impossible de creer le fichier %s",nameFile);
- else {
-
- //fputs("P5\n",f);
- fprintf(f,"%s\n",info.format);
- fputs("#File modified by Moute Charles. Matricule 0x202\n",f);
- fprintf(f,"%d %d\n",info.width,info.height);
- fprintf(f,"%d\n",info.valuePixel);
- fwrite(getImageOf(matrix),sizeof(unsigned char),info.width*info.height,f);
- fclose(f);
- }
- }else mvprintw(ERROR_ROW,5,"Erreur::L'image ayant subie les modifications n'a pas pu etre creee.");
- }
-
-
- /* Traitement avec la convolution */
-
-
- /* Retourne une valeur de pixel de la matrice image de largeur witdh et de hauteur height. Tout en
- s'assurant que les coordonnees du pixel soient bien dans l'image. */
-
- int getValuePixel(int x,int y, int* _image,int width,int height){
- if(x<=0) x = 0;
- if(x>=width) x= width-1;
- if(y<=0) y = 0;
- if(y>=height) y= height-1;
- if(_image!=NULL) return (*(_image+(x+y*width)));
- else return 0.0 ;
- }
-
-
- /* Effectue une convolution sur l'image image de largeur witdh et de hauteur height, avec le filtre kernel
- de largeur kw et de hauteur kh tout s'assurant si le resultat,result, de la convolution est normalise
- , normalized!=0 , ou pas , normalized==0
- */
- void convolve(int* _kernel,int kw ,int kh,int _normalized){
-
-
- if (image==NULL)
- mvprintw(ERROR_ROW,5,"Erreur::La forme matricielle de l'image n'est pas initialisee.");
- if (_kernel==NULL) mvprintw(ERROR_ROW,5,"Erreur::Le noyau de Convolution n'est pas initialise.");
-
- if(image!=NULL && _kernel!=NULL){
-
- if(result!=NULL) { free(result); result=NULL; }
-
- if( (info.width<1) || (info.height<1) )
- mvprintw(ERROR_ROW,5,"La dimension %d x %d representant celle de l'image est incorrecte",info.width,info.height);
- else if( ( (kw%2)==0)|| ( (kh%2) ==0) )
- mvprintw(ERROR_ROW+1,5," La dimension du noyau de convolution %dx%d ne doit avoir que des nombres impaires",kw,kh);
- else{
- int x,y,u,v,uc,vc,i,j;
- int limitX,limitY ;
- float scale = 1;
- int *k= _kernel,sum=0;
-
- result = (int*)malloc( (sizeof(int))*(info.width*info.height) );
- for(i=0;i<info.height;i++) for(j=0;j<info.width;j++) *(result+i+j) = 0 ;
-
- if(_normalized!=0){
- for(i=0;i<kw;i++) for(j=0;j<kh;j++){ sum+=(*k); k++; }
- if(sum!=0) scale/=sum ;
- sum = 0 ;
- }
-
- uc = kw/2;
- vc = kh/2;
- limitX = info.width - uc ;
- limitY = info.height - vc ;
-
- for(y=0;y<info.height;y++){
- for(x=0;x<info.width;x++){
- k = _kernel ;
- sum = 0;
- int edgePixel =( (y<vc) || (y>=limitY) || (x<uc) || (x>=limitX) ) ;
- for(v=-vc;v<=vc;v++){
- int offset = x+(y+v)*info.width;
- for(u=-uc;u<=uc;u++){
- if(edgePixel==1) sum+=getValuePixel(x+u,y+v,image,info.width,info.height) * (*k);
- else sum+= (*(image+offset+u))*(*k);
- k++;
- }
- }
- if(sum<0) sum = 0 ;
- if(sum>255) sum =255 ;
- *(result+(x+y*info.width)) = (sum*scale) ; //(float) (sum*scale) ;
- }
- }
- }
-
- }
- }
-
-
- //Permet de visualiser sur kview l'image passee en parametre.
- void visualize(char* fileImage) {
-
- pid_t pid ;
-
- if(fileImage!=NULL){
-
- char file[strlen(fileImage)+1] ;
- sprintf(file,"%s",fileImage);
- pid = fork();
- if(pid==-1)
- mvprintw(ERROR_ROW,5,"Erreur:: L'image %s ne peut etre visualisee. Faite le manuellement.",file);
- else if(pid==0){
- mvprintw(MESSAGE_ROW,5,"Visualisation de %s",file);
- //recouvre le code executable herite du pere par celui de la commande kview nameFile
- execlp("kview","kview",file,NULL);
- }else{
- wait();
- mvprintw(MESSAGE_ROW+1,5,"Arret de la Visualisation");
- }
-
- }
-
- }
-
- /* Segmentation avec l'Algorithme d'Otsu */
-
-
- // Calcule la somme du sous-partie de l'histogramme
- double computePartOfHistogramme(int indexBegin,int indexEnd){
-
- double soe = 0 ;
- int i ;
- if(histogramme!=NULL && indexBegin>=0 && indexEnd<=info.valuePixel && indexBegin<=indexEnd){
- for(i=indexBegin;i<=indexEnd;i++) soe+= (double)histogramme[i];
- }
- return soe ;
-
- }
-
-
- // Calcule une partie de la variance d"une sous partie de l'histogramme
- double computePartOfVariance(int indexBegin,int indexEnd,double moyenne){
-
- double soe = 0 ;
- int i ;
- if(histogramme!=NULL && indexBegin>=0 && indexEnd<=info.valuePixel && indexBegin<=indexEnd){
- for(i=indexBegin;i<=indexEnd;i++) soe+= pow( ((double) histogramme[i]) - moyenne,2.0);
- }
- return soe ;
-
- }
-
-
- // Calcule du seuil par l'algorithme d'Otsu
- void OtsuAlgorithm() {
-
- int T ;
- double part1,part2,u1,u2,var1,var2,p1,p2,aux,var,dim = info.height*info.width ;
- otsuSeuil = -1 ;
- if(image!=NULL) {
-
- int valeur = (info.valuePixel > 255)? 255:info.valuePixel ;
-
- for(T=1;T<=valeur;T++){
-
- part1 = computePartOfHistogramme(0,T-1);
- part2 = computePartOfHistogramme(T,255);
-
- u1 = part1/T ;
- u2 = part2/(256-T);
-
- var1 = computePartOfVariance(0,T-1,u1);
- var2 = computePartOfVariance(T,255,u2);
-
- p1 = part1/dim ;
- p2 = part2/dim;
-
- aux = (p1*var1)+(p2*var2);
-
- if(T==1) { var = aux; otsuSeuil = T; }
-
- if(aux<var) { var = aux; otsuSeuil = T; }
-
- }
- }
- }
-
-
- // Modifie l'image selon le seuil trouvé par l'algoritme d'otsu.
- void applyOtsuOnImage() {
-
- if(result!=NULL) { free(result); result=NULL; }
-
- if(otsuSeuil!=-1 && image!=NULL) {
- int i,j;
- result = (int*)malloc( (sizeof(int))*(info.height*info.width) );
- for(i=0;i<info.height;i++){
- for(j=0;j<info.width;j++){
- if( (* (image+j+i*info.width) ) < otsuSeuil ) *(result+j+i*info.width) = 0 ;
- else *(result+j+i*info.width) = 255 ;
- }
- }
- }
-
- }
-
-
- // L'algorithme d'Ostu de facon atomique
- void Otsu() {
-
- char ext_name [] = "_Otsu";
- initNameFile(ext_name);
- OtsuAlgorithm();
- applyOtsuOnImage();
- }
-
-
-
- /* Segmentation avec k-means */
-
-
- // Attribue un niveau de gris pseudo-aléatoire au centre du cluster i. 0 < i < k+1
- int ramdomGrayLevel(int i) {
-
- int couleur = 0 ;
- int valeur ;
-
- if(K>0){
-
- if(i>0 && i<=K){
-
- valeur = 256/K ;
- if(valeur==0) couleur = K%256;
- else {
- if(i==1) couleur=0;
- else { couleur = valeur*i ; if(couleur>255) couleur = 255; }
- }
-
- }else mvprintw(ERROR_ROW,5,"Erreur : Le numero de l'element n'est pas correcte");
-
- }else mvprintw(ERROR_ROW,5,"Erreur : Le nombre de cluster n'est pas correcte");
-
- return couleur ;
-
-
- }
-
-
- //Initialise les clusters existants en leur attribuant de facon pseudo-aleatoire des elts.
- void initItems() {
-
- int i,j,length,count,_cluster,add;
- if(items!=NULL) { free(items); items= NULL; }
-
- if(image!=NULL && clusters!=NULL && K >0) {
-
- length = info.height*info.width;
- count = length/K;
- _cluster = 0 ;
- add = 0 ;
-
- items = (item*) malloc((sizeof(item))*length);
- for(i=0;i<info.height;i++){
- for(j=0;j<info.width;j++){
- item* elt = (items+j+i*info.width);
- elt->numCluster = _cluster;
- elt->distance = -1;
- clusters[_cluster].size++;
- add++;
- if(_cluster<(K-1) && add>count) { add = 0; _cluster++;}
- }
- }
- }
- }
-
-
- //calcule le centre des differents clusters
- void computeCentroideOfClusters() {
-
- int i,j;
- double dim,count ;
-
- if(K>0 && clusters!=NULL&&items!=NULL){
-
-
- for(i=0;i<K;i++) (clusters+i)->centroide = 0 ;
-
- for(i=0;i<info.height;i++){
- for(j=0;j<info.width;j++){
- item elt = *(items+j+i*info.width) ;
- cluster* c = clusters+elt.numCluster;
- c->centroide += *(image+j+i*info.width);
- }
- }
-
- for(i=0;i<K;i++) {
- cluster* c = clusters+i;
- if(c->size!=0) c->centroide /= c->size ;
- }
- }
- }
-
-
- /* Affectation des donnees au cluster dont le centre est le plus proche.
- On appele redistributeItems si le nombre de permutation est >= min_modif
- avec min_modif = (K/2)+(K%2).
- */
-
- int distributeItems() {
-
- int i,j,k,count_modif=0,old;
- double aux ;
-
- if(K>0 && items!=NULL && clusters!=NULL){
-
- int b[K];// Ensemble de booleen signalant si un cluster a subi une modification ou pas.
-
-
- for(i=0;i<K;i++) b[i] = 0 ;
-
- for(i=0;i<info.height;i++) {
- for(j=0;j<info.width;j++){
- item* elt = (items+j+i*info.width);
- int pixel = *(image+j+i*info.width);
-
- if(elt->distance == -1) //premier iteration
- elt->distance = abs( clusters[elt->numCluster].centroide - pixel ) ;
-
- old = elt->numCluster;
- for(k=0;k<K;k++){
- if(k==old) continue;
- cluster c = clusters[k];
- aux = abs(c.centroide - pixel);
- if(aux<elt->distance){
- elt->distance = aux ;
- elt->numCluster = k ;
- }
- }
-
- if(old!=elt->numCluster) {
- cluster *c = clusters+old ;
- c->size-=1;
- c = clusters+elt->numCluster;
- c->size+=1;
- b[old]=1;
- b[elt->numCluster]=1;
- }
- }
- }
-
- for(i=0;i<K;i++) count_modif+=b[i];
-
- }
- return count_modif;
- }
-
- //Initialise l'algorithme des k-means pour son premier calcule.
- void initKmeans(){
-
- int i;
-
- if(clusters!=NULL) { free(clusters); clusters!=NULL; }
-
- if(K>0){
- clusters = (cluster*)malloc(sizeof(cluster)*K);
- for(i=0;i<K;i++) {
- cluster* c = clusters+i ;
- c->size=0;
- c->centroide = ramdomGrayLevel(i+1);
- }
- initItems();
- }
- }
-
-
- // Determine les differents cluster
- void kmeansAlgorithm() {
- if(K>0 && image!=NULL){
- min_modif = (K/2)+(K%2);
- int count_modif ;
- initKmeans();
- do{
- computeCentroideOfClusters();
- count_modif = distributeItems();
- }while(count_modif>=min_modif);
-
- }
- }
-
- //Applique les niveaux de gris a chaque cluster.
- void applyKmeansOnImage() {
-
- int i,j;
- if(result!=NULL) { free(result); result=NULL; }
-
- if(K>0 && items!=NULL && clusters!=NULL) {
- result = (int*) malloc( sizeof(int)*info.height*info.width);
- for(i=0;i<info.height;i++){
- for(j=0;j<info.width;j++){
- *(result+j+i*info.width) = clusters[(*(items+j+i*info.width)).numCluster].centroide;
- }
- }
-
- }
-
- }
-
- // Algorithme k-means atomique.
- void kmeans(int k){
-
- char ext_name [] = "_Kmeans";
- initNameFile(ext_name);
- K = k ;
- kmeansAlgorithm();
- applyKmeansOnImage();
- }
-
- --- Le fichier application.c ---
-
- // Charles MOUTE --> 03X202
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <curses.h>
- #include "algorithmes.h"
-
-
- /*Variables Globales d'interface */
-
-
- //int kwidth=5; //largeur ou nombre de colonne du filtre que l'on applique a info.image
- //int kheight=5; //hauteur ou nombre de ligne que l'on applique a info.image
- int normalized=1; //booleen signalant si le resultat d'une operation sur une image doit etre normalisee ou pas
-
-
-
- //kernel_* represente un filtre que l'on appliquera a info.image
- int kernel [5][5] = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}};
- int kernel_moyenne_passe_bas[3][3] = {{1,1,1},{1,1,1},{1,1,1}}; // filtre moyenne-passe-bas.
- int kernel_sobel_1 [3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}};//sobel filter.
- int kernel_sobel_2 [3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}}; // sobel filter 2.
- int kernel_prewitt_1 [3][3] = {{-1,-1,-1},{0,0,0},{1,1,1}}; // filtre de Prewitt 1.
- int kernel_prewitt_2 [3][3] = {{-1,0,1},{-1,0,1},{-1,0,1}}; // filtre de Prewitt 2
-
- //int kernel[3][3] = {{1,2,1},{2,4,2},{1,2,1}};
- //int kernel[5][5] = {{1,4,6,6,1},{4,16,24,16,4},{6,24,36,24,6},{4,16,24,16,4},{1,4,6,6,1}};
- //int kernel[5][5] = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}};
-
-
- char file_current [MAX_STRING] ="\0"; //variable représentant le fichier courant
- int isFirst = 1 ;
- //Menu principale lorsque l'on entre dans le programme pour la première fois.
- char* main_menu [] = {
- "1. Choisir une image.",
- "2. Quitter.",
- 0
- };
-
- //Représente le menu principal lorsqu'une image a déjà était choisie.
- char* extend_menu [] = {
- "1. Choisir une image.",
- "2. Visualiser image.",
- "3. Proprietes image.",
- "4. Histogramme image.",
- "5. Traitements sur image.",
- "6. Quitter",
- 0
- };
-
-
- //Donne la liste des opérations applicables sur une image.
- char* traitement_submenu [] = {
- "1. Convolution.",
- "2. Segmentation.",
- "3. Precedent",
- 0
- };
-
-
- //Représente les différents filtres applicables pour une convolution.
- char* convolution_submenu [] = {
- "1. Filre moyenne-passe-bas.",
- "2. Filtre de Sobel 1.",
- "3. Filtre de Sobel 2.",
- "4. Filtre de Prewitt 1.",
- "5. Filtre de Prewitt 2.",
- "6. Filtre Quelconque.",
- "7. Visualiser image.",
- "8. Precedent.",
- 0
- };
-
-
- // Représente les différents options pour une segmentation.
- char* segmentation_submenu [] = {
- "1. K-means.",
- "2. Otsu.",
- "3. Visualiser image.",
- "4. Precedent.",
- 0
- };
-
-
- /* Permet de mettre en surbrillance le choix d'un utilisateur en attendant sa validation.
- Les paramétres, une liste d'option, l'option en mettre en surbrillance dans la liste des
- colonnes, la ligne et colonne de début où commencer à afficher les options à l'écran.
- */
-
- /* Demande une saisie qu'elle lit à la position courante du curseur. Elle supprime tout saut
- de ligne présent à la fin de la ligne*/
- void getString(char* chaine) {
-
- int length ;
- wgetnstr(stdscr,chaine,MAX_STRING);
- length = strlen(chaine);
- if(length >0 && chaine[length-1]== '\n') chaine[length-1]='\0';
-
- }
-
- /* Demande confirmation à l'utilisateur pour une action */
- int showMessageConfirm() {
-
- int confirm = 0 ;
- char answer ;
-
- mvprintw(QUESTION_ROW,5,"Etes-vous sur ? ");
- clrtoeol();
- refresh();
- cbreak();
- answer = getch();
- if(answer=='o' || answer== 'y' || answer=='O' || answer=='Y') confirm = 1 ;
- nocbreak();
-
- if(!confirm){
- mvprintw(QUESTION_ROW,1," Annulation");
- clrtoeol();
- refresh();
- sleep(1);
- }
- return confirm ;
- }
-
- /* Nettoie l'écran et affiche l'objectif de notre application sous forme de titre. */
- void clear_screen() {
- clear();
- //attron(A_UNDERLINE);
- mvprintw(2,20,"Application de Traitements d'Image");
- //attroff(A_UNDERLINE);
- if(file_current[0])
- mvprintw(PROMPT_ROW-2,0,"Le fichier actif est : %s\n",file_current);
- refresh();
- }
-
- /* Permet d'afficher le menu avec un element en subrillance */
- void display_menu(char* options[],int surbrill_item,int row_begin,int columm_begin){
-
- int row_current = 0 ;
- char** option;
- char* txt;
- option = options ;
- while(*option){
- if(row_current==surbrill_item) mvaddch(row_begin+row_current,columm_begin-3,ACS_RARROW);
- else mvaddch(row_begin+row_current,columm_begin-3,' ');
- txt = options[row_current];
- mvprintw(row_begin+row_current,columm_begin,"%s",txt);
- row_current++;
- option++;
- }
- mvprintw(row_begin+row_current+5,columm_begin,"Déplacez la surbrillance puis appuyer sur entrée ");
- refresh();
- }
-
-
- /* Permet d'obtenir le choix effectue par l'utilisateur à partir d'un ensemble d'options.*/
- int select_item(char* prompt,char* options[]){
-
- static int row_selected = 0 ;
- int row_max = 0;
- int row_begin = MESSAGE_ROW, col_begin = 10 ;
- char** option;
- int selected;
- int touche = 0 ;
-
- option = options ;
-
- while(*option) {
- row_max++;
- option++;
- }
-
- if (row_selected >= row_max) row_selected = 0;
- clear_screen();
- mvprintw(row_begin-2,col_begin,prompt);
-
- keypad(stdscr,TRUE);
- cbreak();
- noecho();
-
- touche = 0 ;
-
- while( touche!='q' && touche!=KEY_ENTER && touche!='\n') {
-
- if(touche==KEY_UP){
- if(row_selected==0) row_selected = row_max -1 ;
- else row_selected--;
- }
-
- if(touche==KEY_DOWN){
- if(row_selected==(row_max-1)) row_selected = 0 ;
- else row_selected++;
- }
-
- selected = *options[row_selected];
- display_menu(options,row_selected,row_begin,col_begin);
- touche = getch();
- }
-
- keypad(stdscr,FALSE);
- nocbreak();
- echo();
-
- if(touche =='q') selected = 'q';
- return (selected);
- }
-
- void chooseFile(){
-
- int row_begin = MESSAGE_ROW,col_begin = 10 ;
- clear_screen();
- mvprintw(row_begin-2,1,"{ Path : Home - Select a file }");
- mvprintw(row_begin,col_begin,"Donnez le chemin d'un fichier image : ");
- getString(file_current);
- free_memory();
- if(file_current[0]){ isFirst = 0; init_variables(file_current); }
- else isFirst = 1 ;
- }
-
-
- /* Menu principal dans le cas du traitement d'une segmentation */
- //1-4
- void main_segmentation() {
-
- int select ;
- do{
- select = select_item ("{ Path : Home - Traitements- Segmentation }",segmentation_submenu);
- switch(select) {
- case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
- case '4' : select ='q'; break;//mvprintw(ERROR_ROW-4,5,segmentation_submenu[3]);break;
- case '1' : clear_screen();
- mvprintw(MESSAGE_ROW,5,"Donnez le nombre de cluster : ");
- int k = getch();
- kmeans(k);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee avec %d clusters",segmentation_submenu[0]+2,k);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,segmentation_submenu[0]);break;
- case '2': clear_screen();
- Otsu();
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee avec un seuil de %d",segmentation_submenu[1]+2,getOtsuSeuil());
- getch();
- break;
-
- //mvprintw(ERROR_ROW-4,25,segmentation_submenu[1]);break;
- case '3' : clear_screen();
- visualize(getNameFile());
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,segmentation_submenu[2]);break;
- }
- refresh();
- }while(select!='q');
- }
-
-
- /* Menu principal dans le cas du traitement d'une convolution */
- void main_convolution() {
-
- int select ;
- do{
- select = select_item ("{ Path : Home - Traitements }",convolution_submenu);
- switch(select) {
- case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
- case '8' : select ='q'; break;//mvprintw(ERROR_ROW-4,5,convolution_submenu[7]);break;
- case '1' : clear_screen();
- initNameFile("_Filre_Moyenne_Passe_Bas");
- convolve((int*)kernel_moyenne_passe_bas,3,3,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[0]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[0]);break;
- case '2' : clear_screen();
- initNameFile("_Filre_Sobel_1");
- convolve((int*)kernel_sobel_1,3,3,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[1]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[1]);break;
- case '3' : clear_screen();
- initNameFile("_Filre_Sobel_2");
- convolve((int*)kernel_sobel_2,3,3,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[2]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[2]);break;
- case '4' : clear_screen();
- initNameFile("_Filre_Prewitt_1");
- convolve((int*)kernel_prewitt_1,3,3,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[3]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[3]);break;
- case '5' : clear_screen();
- initNameFile("_Filre_Prewitt_2");
- convolve((int*)kernel_prewitt_2,3,3,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[4]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[4]);break;
- case '6' : clear_screen();
- initNameFile("_Filre_Quelconque");
- convolve((int*)kernel,5,5,normalized);
- rewriteImage(getOperationResult());
- mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[5]+2);
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[5]);break;
- case '7' : clear_screen();
- visualize(getNameFile());
- getch();
- break;
- //mvprintw(ERROR_ROW-4,25,convolution_submenu[6]);break;
- }
- refresh();
- }while(select!='q');
- }
-
-
- /* Menu principal dans le cas du sous-menu traitement */
- void main_traitement() {
-
- int select ;
- do{
- select = select_item ("{ Path : Home - Traitements }",traitement_submenu);
- switch(select) {
- case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
- case '3' : select ='q'; break; //mvprintw(ERROR_ROW-4,5,traitement_submenu[2]);break;
- case '1' : main_convolution(); break;//mvprintw(ERROR_ROW-4,25,traitement_submenu[0]);
- case '2' : main_segmentation(); break;//mvprintw(ERROR_ROW-4,25,traitement_submenu[1]);
- }
- refresh();
- }while(select!='q');
- initNameFile(NULL);
- }
-
- int main() {
-
- int select;
- initscr();
- start_color();
- do{
-
- select = select_item ("{ Path : Home }",file_current[0]?extend_menu:main_menu);
- switch(select) {
- case 'q' : //mvprintw(ERROR_ROW-3,5,"Quitter");
- break;
- case '6' : //mvprintw(ERROR_ROW-3,5,extend_menu[5]);
- select = 'q';
- break;
- case '2' :
- if(isFirst) select = 'q';
- else{
- clear_screen();
- visualize(getImageName());
- getch();
- }
- break ;
- case '1' : chooseFile();
- //mvprintw(ERROR_ROW-3,5,main_menu[0]);
- break ;
- case '3' : clear_screen();
- displayImageProperties();
- getch();
- //mvprintw(ERROR_ROW-3,5,extend_menu[2]);
- break ;
- case '4' : //mvprintw(ERROR_ROW-3,5,extend_menu[3]);
- clear_screen();
- displayImageHistogramme();
- getch();
- break ;
- case '5' : main_traitement();
- break ;//ivprintw(ERROR_ROW-3,5,extend_menu[4]);
- }
- refresh();
- }while(select!='q');
- endwin();
- free_memory();
- exit(EXIT_SUCCESS);
- }
-
- --- le fichier MakeFile ---
-
- SOURCE=./
- CC=gcc
- CFLAGS= -lcurses
- CMD=application
-
-
- all: exe
-
- exe: $(CMD).c
- $(CC) -I $(SOURCE) -o $(CMD).exe $(CMD).c $(CFLAGS)
-
- test: $(CMD).exe
- ./$(CMD).exe
-
- clean:
- rm -rf $(CMD).exe
--- Le fichier algorithmes.h ---
// Charles MOUTE --> 03X202
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <curses.h>
#define taille 256
#define diese '#'
#define p5 "P5"
#define p6 "P6"
/* Types */
/*Constantes pour interfaces */
#define KEY_ESCAPE 27 /* Représente le bouton echape */
#define MAX_STRING 1024 /* Longueur maximale d'une réponse */
//#define MAX_NAMEFILE 80 /* Longueur max d'un chemin menant à un fichier image */
#define MESSAGE_ROW 6 /* Ligne affichant des messages divers */
#define ERROR_ROW 22 /* Ligne signalant les messages */
#define QUESTION_ROW 20 /* Ligne pour les questions */
#define PROMPT_ROW 18 /* LIGNE de prompt */
// Type definissant les proprietes d'une image.
typedef struct image_properties {
int width ; // largeur de l'image.
int height ; // hauteur de l'image.
char* format; // Format de l'image.
int valuePixel; // valuer maximale des pixels de l'image.
char* nameFile; // nom du fichier image.
unsigned char* image; // contenu de l'image.
} properties ;
// Type definissant la structure d'un element dans l'algorithme de k-means.
typedef struct item_kmeans {
int numCluster ; // Represente le numero de cluster au quel l'elt est affecte.
int distance ; // Represente la distance de l'elt au centre du cluster auquel il appartient.
} item ;
// Type definissant la structure d'un cluster dans l'algorithme de k-means.
// Le centre d'un cluster est la moyenne des valuers des pixels qu'il contient.
typedef struct cluster_kmeans {
int centroide; //Represente le centre du cluster.
int size; //Represente le nombre d'elt contenu dans le cluster.
} cluster ;
/* Variables */
properties info ; // proprietes d'une image de nom info.nameFile.
int* histogramme ; // est l'histogramme de info.nameFile. de taille valuePixel.
int* image; // image est la representation sous forme matricielle de info.image.
int* result;// result est l'image resultante de l'application d'une operation sur info.image.
int otsuSeuil ; //represente le seuil donnee par l'algorithme de otsu.
int K ; // Represente le nombre de cluster que k-means doit definr.
int variance_limit = 100; //Represente la limite en dessous de laquelle k-means ne doit effectue de traitement.
int min_modif;//Represente le min de modification de clusters en dessus du quel on les considere instables.
cluster* clusters; // Represente les k clusters que k-means devra definir.
item* items; //Representent les pixels de l'image regroupés en cluster.
char* nameFile ; //Nom donne a l'image resultante des operations subies par info.image.
/* Operations */
// Initialise toutes les variables par des valeurs par defaut.
void default_init() {
int i,j;
/*pour info*/
info.width = -1 ;
info.height = -1 ;
info.format = NULL ;
info.valuePixel = -1 ;
info.nameFile = NULL ;
info.image = NULL ;
//info.image = (unsigned char*)malloc(taille*taille);
/*pour histogramme de l'image */
histogramme = NULL ;
// pour le nom de fichier
nameFile = NULL ;
//pour la representation matricielle de info.image
image = NULL ;
//pour le resultat matricielle d'une operation subie par info.image
result = NULL ;
//pour seuil de otsu
otsuSeuil = -1 ;
//Pour l'algorithme de k-means
K = -1 ;
clusters = NULL ;
items = NULL ;
}
// Libere les espaces memoires alloues
void free_memory() {
if (items!=NULL) { free(items); items = NULL; }
if (image!=NULL) { free(image); image = NULL; }
if (result!=NULL) { free(result); result = NULL; }
if (clusters!=NULL) { free(clusters); clusters = NULL; }
if (nameFile!=NULL) { free(nameFile); nameFile = NULL; }
if (info.format!=NULL) { free(info.format); info.format = NULL; }
if (info.image!=NULL) { free(info.image); info.image = NULL ; }
if (histogramme!=NULL) { free(histogramme); histogramme = NULL ; }
if (info.nameFile!=NULL) { free(info.nameFile); info.nameFile = NULL; }
}
// Retourne la largeur de l'image courrante.
int getImageWidth() { return info.width ; }
//Retourne la hauteur de l'image courante.
int getImageHeight() { return info.height ; }
//Retourne la valeur maximale des pixels de l'image.
int getImageMaxValuePixel() { return info.valuePixel; }
//Retourne le format de l'image courante.
char* getImageFormat() { return info.format ; }
//Retourne le nom de l'image courante.
char* getImageName() { return info.nameFile ; }
//Retourne le contenu de l'image courante.
unsigned char* getImageContent() { return info.image ; }
//Retourne le nom de l'image modifiee.
char* getNameFile() {return nameFile; }
//Retourne le resultat effectue sur l'image.
int* getOperationResult() { return result; }
//Retourne le seuil de Ostu.
int getOtsuSeuil() { return otsuSeuil; }
//Obient les proprietes du fichier passee en parametre
void getPropertiesOf(char* file) {
FILE *f;
char *row =(char*)malloc(taille),*param=(char*)malloc(taille);
f = fopen(file,"r");
if(f) {
// Recherche format de l'image
fgets(row,taille,f);
info.format = (char*) malloc((sizeof(char))*(strlen(row))) ;
strcpy(info.format,row);
info.format[(strlen(row))-1] = '\0';
if (strcmp(p5,info.format)==0 || strcmp(p6,info.format)==0 ) {
if(!feof(f)){
fgets(row,taille,f);
//Effacement des eventuels commentaires dans le fichier
while(row[0]==diese&&!feof(f)){
fgets(row,taille,f);
}
// Recherche des dimensions de l'image
if(row[0]!=diese){
row[strlen(row)]='\0';
info.width = atoi(strtok(row," "));
info.height = atoi(strtok(NULL," "));
// Recherche de la valeur maximale des pixels
if(!feof(f)){
fgets(row,taille,f);
row[strlen(row)]='\0';
info.valuePixel = atoi(strtok(row," "));
info.nameFile = (char*)malloc( (sizeof(char))* (strlen(file)) );
strcpy(info.nameFile,file);
if(!feof(f)){
info.image = (unsigned char*)malloc(info.width*info.height);
fread(info.image,sizeof(unsigned char),info.width*info.height,f);
}
}
}
}
} else{
mvprintw(ERROR_ROW,5,"Le fichier %s n'est pas au format P5 ou P6",file);
free_memory();
}
fclose(f);
}else {
mvprintw(ERROR_ROW,5,"Impossible d'ouvrir %s",file);
free_memory();
}
free(row);
free(param);
}
//Initialise le nom que l'on donnera a l'image resultante d'une operation sur info.image
void initNameFile(char* nameUser){
//En cas de PB enlever les commentaires et les mettre ou ils doivent se trouvent
char* file,*nomFichier,*extension,str[]="_modified",point[]=".",*name,ext[]=".pgm";
if(nameFile!=NULL) { free(nameFile); nameFile = NULL; }
if(info.nameFile!=NULL) {
name = (char*)malloc(strlen(info.nameFile)+1);
sprintf(name,"%s\0",info.nameFile);
file = (strrchr(name,'/')+1);
if(file==NULL) file = (strrchr(name,'\\')+1);
if(file==NULL) file = name ;
//extension = strrchr(file,'.')+1;
nomFichier = strtok(file,".");
if(nameUser!=NULL){
char ext_name [strlen(nameUser)+1];
sprintf(ext_name,"%s",nameUser);
nameFile=(char*)malloc(strlen(nomFichier)+strlen(ext_name)+strlen(ext)+1);
sprintf(nameFile,"%s%s%s",nomFichier,ext_name,ext);
//nameFile=(char*)malloc(strlen(nomFichier)+strlen(ext_name)+strlen(point)+strlen(extension)+1);
//sprintf(nameFile,"%s%s%s%s",nomFichier,ext_name,point,extension);
}else{
nameFile = (char*)malloc(strlen(nomFichier)+strlen(str)+strlen(ext)+1);
sprintf(nameFile,"%s%s%s",nomFichier,str,ext);
//nameFile = (char*)malloc(strlen(nomFichier)+strlen(str)+strlen(point)+strlen(extension)+1);
//sprintf(nameFile,"%s%s%s%s",nomFichier,str,point,extension);
}
free(name);
}
}
//Obtient l'histogramme de l'image courante
void getImageHistogramme() {
if(info.image!=NULL){
int i ,length ;
int max = taille;
//int max = info.valuePixel+1;
if(max!=-1){
histogramme =(int*)malloc((sizeof(int))*max);
for(i=0;i<max;i++) histogramme[i] = 0;
length = strlen(info.image);
for(i=0;i<length;i++) histogramme[info.image[i]]++;
}
}
}
// Creer la forme matricielle de l'image courante
void createImageMatrix() {
int i,j,k=0 ;
if(info.image!=NULL) {
image = (int*)malloc((sizeof(int))*(info.height*info.width));
int* matrix = image ;
for(i=0;i<info.height;i++) for(j=0;j<info.width;j++) {*matrix = 0 ; matrix++;}
matrix = image ;
for(i=0;i<info.height;i++) {
for(j=0;j<info.width;j++) {
*matrix = (int) info.image[k];
matrix++;
k++;
}
}
}
}
//Obtient d'une representation matricielle le contenu d'une image.
unsigned char* getImageOf(const int* matrix) {
if(info.image!=NULL){
unsigned char* _image = (unsigned char*)malloc(info.height*info.width);
int i,j,k=0,val;
for(i=0;i<info.height;i++){
for(j=0;j<info.width;j++){
val = (unsigned char) (*matrix);
if(val>info.valuePixel) val = info.valuePixel ;
if(val<0) val = 0 ;
_image[k] = val ;
k++;
matrix++;
}
}
return _image ;
}else return NULL ;
}
// Obtient de la matrice courante, le contenue de l'image originelle
unsigned char* getImageOfCurrent() {
return getImageOf(image) ;
}
/* Obtient de la matrice resultante d'une operation sur l'image originelle.
Le contenue de l'image originelle modifiee par l'application de l'operation.
*/
unsigned char* getImageOfResult() {
return getImageOf(result) ;
}
//Initialise toutes les variables en regroupant les fonctioons adequates
void init_variables(char* file){
default_init();
getPropertiesOf(file);
initNameFile(NULL);
getImageHistogramme();
createImageMatrix();
}
// Affiche a l'ecran les proprietes de l'image courante, celle stockee dans info.image
void displayImageProperties(){
mvprintw(MESSAGE_ROW,5,"Image :%s",info.nameFile);
mvprintw(MESSAGE_ROW+2,5,"----- Proprietes de l'image -----");
mvprintw(MESSAGE_ROW+4,5," Format de l'image :%s",info.format);
mvprintw(MESSAGE_ROW+5,5," Largeur de l'image :%d",info.width);
mvprintw(MESSAGE_ROW+6,5," Hauteur de l'image :%d",info.height);
mvprintw(MESSAGE_ROW+7,5," Valeur Max des pixels de l'image :%d",info.valuePixel);
}
void displayContent(const unsigned char * _image){
int i,size ;
if(_image==NULL)
mvprintw(MESSAGE_ROW+2,5," Contenue de l'image : [ Empty Image ] ");
else {
mvprintw(MESSAGE_ROW+2,5," Contenue de l'image : ");
size = strlen(_image);
mvprintw(MESSAGE_ROW+3,5,"[");
for(i=0;i<size;i++){
if(i==(size-1 )) printw("%d",_image[i]);
else printw("%d, ",_image[i]);
}
printw("]");
}
}
//Affiche a l'ecran le contenu de l'image :
void displayImageContent() {
mvprintw(MESSAGE_ROW,5,"----- Image originelle -----");
displayContent(info.image);
}
// Affiche a l'ecran l'histogramme de l'image courante, celle stockee dans info.image
void displayImageHistogramme(){
int j,length ;
mvprintw(MESSAGE_ROW,5,"----- Histogramme de %s -----",info.nameFile);
if(histogramme==NULL) printw(" [ Empty Histogramme-Aucune Image de selectionnee ]");
else {
length = info.valuePixel+1;
printw("[");
for(j=0;j<length;j++){
if(j==(length-1)) printw("%d",histogramme[j]);
else printw("%d, ",histogramme[j]);
}
printw("]");
}
}
// Affiche a l'ecran le contenu de la representation matricielle, _image, du fichier file.
void displayMatrix(char* file, int* _image){
int i,j;
mvprintw(MESSAGE_ROW+1,5," Matrice de %s : ",file);
if(_image==NULL) printw("[ Empty Matrix ]");
else {
int* matrix = _image ;
printw("[");
for(i=0;i<info.height;i++){
printw("[");
for(j=0;j<info.width;j++){
if(j==(info.width-1)) printw("%d",*matrix);
else printw("%d,",*matrix);
matrix++;
}
if(i==(info.height-1)) printf("]");
else printw("],\n");
}
printw("]");
}
}
/* Affiche a l'ecran le contenu de la matrice de l'image courante. Celle contenu dans info.image */
void displayImageMatrix() {
mvprintw(MESSAGE_ROW,5,"----- Image originelle -----");
displayMatrix(info.nameFile,image);
}
/* Affiche a l'ecran le contenu de la matrice resultante d'une operation sur l'image courante.*/
void displayResult() {
mvprintw(MESSAGE_ROW,5,"----- Resulat Operation sur image originelle -----");
displayMatrix(nameFile,result);
}
/* Cree une image de nom nameFile, de largeur info.width, de hauteur info.height et
de valeur maximale de pixel info.valuePixel a partir du contenu de la representation matricielle d'une
image, nomee matrix.
*/
void rewriteImage(int* matrix){
FILE *f;
if(nameFile!=NULL && matrix!=NULL) {
f = fopen(nameFile,"w");
if(!f) mvprintw(ERROR_ROW,5,"Erreur::Impossible de creer le fichier %s",nameFile);
else {
//fputs("P5\n",f);
fprintf(f,"%s\n",info.format);
fputs("#File modified by Moute Charles. Matricule 0x202\n",f);
fprintf(f,"%d %d\n",info.width,info.height);
fprintf(f,"%d\n",info.valuePixel);
fwrite(getImageOf(matrix),sizeof(unsigned char),info.width*info.height,f);
fclose(f);
}
}else mvprintw(ERROR_ROW,5,"Erreur::L'image ayant subie les modifications n'a pas pu etre creee.");
}
/* Traitement avec la convolution */
/* Retourne une valeur de pixel de la matrice image de largeur witdh et de hauteur height. Tout en
s'assurant que les coordonnees du pixel soient bien dans l'image. */
int getValuePixel(int x,int y, int* _image,int width,int height){
if(x<=0) x = 0;
if(x>=width) x= width-1;
if(y<=0) y = 0;
if(y>=height) y= height-1;
if(_image!=NULL) return (*(_image+(x+y*width)));
else return 0.0 ;
}
/* Effectue une convolution sur l'image image de largeur witdh et de hauteur height, avec le filtre kernel
de largeur kw et de hauteur kh tout s'assurant si le resultat,result, de la convolution est normalise
, normalized!=0 , ou pas , normalized==0
*/
void convolve(int* _kernel,int kw ,int kh,int _normalized){
if (image==NULL)
mvprintw(ERROR_ROW,5,"Erreur::La forme matricielle de l'image n'est pas initialisee.");
if (_kernel==NULL) mvprintw(ERROR_ROW,5,"Erreur::Le noyau de Convolution n'est pas initialise.");
if(image!=NULL && _kernel!=NULL){
if(result!=NULL) { free(result); result=NULL; }
if( (info.width<1) || (info.height<1) )
mvprintw(ERROR_ROW,5,"La dimension %d x %d representant celle de l'image est incorrecte",info.width,info.height);
else if( ( (kw%2)==0)|| ( (kh%2) ==0) )
mvprintw(ERROR_ROW+1,5," La dimension du noyau de convolution %dx%d ne doit avoir que des nombres impaires",kw,kh);
else{
int x,y,u,v,uc,vc,i,j;
int limitX,limitY ;
float scale = 1;
int *k= _kernel,sum=0;
result = (int*)malloc( (sizeof(int))*(info.width*info.height) );
for(i=0;i<info.height;i++) for(j=0;j<info.width;j++) *(result+i+j) = 0 ;
if(_normalized!=0){
for(i=0;i<kw;i++) for(j=0;j<kh;j++){ sum+=(*k); k++; }
if(sum!=0) scale/=sum ;
sum = 0 ;
}
uc = kw/2;
vc = kh/2;
limitX = info.width - uc ;
limitY = info.height - vc ;
for(y=0;y<info.height;y++){
for(x=0;x<info.width;x++){
k = _kernel ;
sum = 0;
int edgePixel =( (y<vc) || (y>=limitY) || (x<uc) || (x>=limitX) ) ;
for(v=-vc;v<=vc;v++){
int offset = x+(y+v)*info.width;
for(u=-uc;u<=uc;u++){
if(edgePixel==1) sum+=getValuePixel(x+u,y+v,image,info.width,info.height) * (*k);
else sum+= (*(image+offset+u))*(*k);
k++;
}
}
if(sum<0) sum = 0 ;
if(sum>255) sum =255 ;
*(result+(x+y*info.width)) = (sum*scale) ; //(float) (sum*scale) ;
}
}
}
}
}
//Permet de visualiser sur kview l'image passee en parametre.
void visualize(char* fileImage) {
pid_t pid ;
if(fileImage!=NULL){
char file[strlen(fileImage)+1] ;
sprintf(file,"%s",fileImage);
pid = fork();
if(pid==-1)
mvprintw(ERROR_ROW,5,"Erreur:: L'image %s ne peut etre visualisee. Faite le manuellement.",file);
else if(pid==0){
mvprintw(MESSAGE_ROW,5,"Visualisation de %s",file);
//recouvre le code executable herite du pere par celui de la commande kview nameFile
execlp("kview","kview",file,NULL);
}else{
wait();
mvprintw(MESSAGE_ROW+1,5,"Arret de la Visualisation");
}
}
}
/* Segmentation avec l'Algorithme d'Otsu */
// Calcule la somme du sous-partie de l'histogramme
double computePartOfHistogramme(int indexBegin,int indexEnd){
double soe = 0 ;
int i ;
if(histogramme!=NULL && indexBegin>=0 && indexEnd<=info.valuePixel && indexBegin<=indexEnd){
for(i=indexBegin;i<=indexEnd;i++) soe+= (double)histogramme[i];
}
return soe ;
}
// Calcule une partie de la variance d"une sous partie de l'histogramme
double computePartOfVariance(int indexBegin,int indexEnd,double moyenne){
double soe = 0 ;
int i ;
if(histogramme!=NULL && indexBegin>=0 && indexEnd<=info.valuePixel && indexBegin<=indexEnd){
for(i=indexBegin;i<=indexEnd;i++) soe+= pow( ((double) histogramme[i]) - moyenne,2.0);
}
return soe ;
}
// Calcule du seuil par l'algorithme d'Otsu
void OtsuAlgorithm() {
int T ;
double part1,part2,u1,u2,var1,var2,p1,p2,aux,var,dim = info.height*info.width ;
otsuSeuil = -1 ;
if(image!=NULL) {
int valeur = (info.valuePixel > 255)? 255:info.valuePixel ;
for(T=1;T<=valeur;T++){
part1 = computePartOfHistogramme(0,T-1);
part2 = computePartOfHistogramme(T,255);
u1 = part1/T ;
u2 = part2/(256-T);
var1 = computePartOfVariance(0,T-1,u1);
var2 = computePartOfVariance(T,255,u2);
p1 = part1/dim ;
p2 = part2/dim;
aux = (p1*var1)+(p2*var2);
if(T==1) { var = aux; otsuSeuil = T; }
if(aux<var) { var = aux; otsuSeuil = T; }
}
}
}
// Modifie l'image selon le seuil trouvé par l'algoritme d'otsu.
void applyOtsuOnImage() {
if(result!=NULL) { free(result); result=NULL; }
if(otsuSeuil!=-1 && image!=NULL) {
int i,j;
result = (int*)malloc( (sizeof(int))*(info.height*info.width) );
for(i=0;i<info.height;i++){
for(j=0;j<info.width;j++){
if( (* (image+j+i*info.width) ) < otsuSeuil ) *(result+j+i*info.width) = 0 ;
else *(result+j+i*info.width) = 255 ;
}
}
}
}
// L'algorithme d'Ostu de facon atomique
void Otsu() {
char ext_name [] = "_Otsu";
initNameFile(ext_name);
OtsuAlgorithm();
applyOtsuOnImage();
}
/* Segmentation avec k-means */
// Attribue un niveau de gris pseudo-aléatoire au centre du cluster i. 0 < i < k+1
int ramdomGrayLevel(int i) {
int couleur = 0 ;
int valeur ;
if(K>0){
if(i>0 && i<=K){
valeur = 256/K ;
if(valeur==0) couleur = K%256;
else {
if(i==1) couleur=0;
else { couleur = valeur*i ; if(couleur>255) couleur = 255; }
}
}else mvprintw(ERROR_ROW,5,"Erreur : Le numero de l'element n'est pas correcte");
}else mvprintw(ERROR_ROW,5,"Erreur : Le nombre de cluster n'est pas correcte");
return couleur ;
}
//Initialise les clusters existants en leur attribuant de facon pseudo-aleatoire des elts.
void initItems() {
int i,j,length,count,_cluster,add;
if(items!=NULL) { free(items); items= NULL; }
if(image!=NULL && clusters!=NULL && K >0) {
length = info.height*info.width;
count = length/K;
_cluster = 0 ;
add = 0 ;
items = (item*) malloc((sizeof(item))*length);
for(i=0;i<info.height;i++){
for(j=0;j<info.width;j++){
item* elt = (items+j+i*info.width);
elt->numCluster = _cluster;
elt->distance = -1;
clusters[_cluster].size++;
add++;
if(_cluster<(K-1) && add>count) { add = 0; _cluster++;}
}
}
}
}
//calcule le centre des differents clusters
void computeCentroideOfClusters() {
int i,j;
double dim,count ;
if(K>0 && clusters!=NULL&&items!=NULL){
for(i=0;i<K;i++) (clusters+i)->centroide = 0 ;
for(i=0;i<info.height;i++){
for(j=0;j<info.width;j++){
item elt = *(items+j+i*info.width) ;
cluster* c = clusters+elt.numCluster;
c->centroide += *(image+j+i*info.width);
}
}
for(i=0;i<K;i++) {
cluster* c = clusters+i;
if(c->size!=0) c->centroide /= c->size ;
}
}
}
/* Affectation des donnees au cluster dont le centre est le plus proche.
On appele redistributeItems si le nombre de permutation est >= min_modif
avec min_modif = (K/2)+(K%2).
*/
int distributeItems() {
int i,j,k,count_modif=0,old;
double aux ;
if(K>0 && items!=NULL && clusters!=NULL){
int b[K];// Ensemble de booleen signalant si un cluster a subi une modification ou pas.
for(i=0;i<K;i++) b[i] = 0 ;
for(i=0;i<info.height;i++) {
for(j=0;j<info.width;j++){
item* elt = (items+j+i*info.width);
int pixel = *(image+j+i*info.width);
if(elt->distance == -1) //premier iteration
elt->distance = abs( clusters[elt->numCluster].centroide - pixel ) ;
old = elt->numCluster;
for(k=0;k<K;k++){
if(k==old) continue;
cluster c = clusters[k];
aux = abs(c.centroide - pixel);
if(aux<elt->distance){
elt->distance = aux ;
elt->numCluster = k ;
}
}
if(old!=elt->numCluster) {
cluster *c = clusters+old ;
c->size-=1;
c = clusters+elt->numCluster;
c->size+=1;
b[old]=1;
b[elt->numCluster]=1;
}
}
}
for(i=0;i<K;i++) count_modif+=b[i];
}
return count_modif;
}
//Initialise l'algorithme des k-means pour son premier calcule.
void initKmeans(){
int i;
if(clusters!=NULL) { free(clusters); clusters!=NULL; }
if(K>0){
clusters = (cluster*)malloc(sizeof(cluster)*K);
for(i=0;i<K;i++) {
cluster* c = clusters+i ;
c->size=0;
c->centroide = ramdomGrayLevel(i+1);
}
initItems();
}
}
// Determine les differents cluster
void kmeansAlgorithm() {
if(K>0 && image!=NULL){
min_modif = (K/2)+(K%2);
int count_modif ;
initKmeans();
do{
computeCentroideOfClusters();
count_modif = distributeItems();
}while(count_modif>=min_modif);
}
}
//Applique les niveaux de gris a chaque cluster.
void applyKmeansOnImage() {
int i,j;
if(result!=NULL) { free(result); result=NULL; }
if(K>0 && items!=NULL && clusters!=NULL) {
result = (int*) malloc( sizeof(int)*info.height*info.width);
for(i=0;i<info.height;i++){
for(j=0;j<info.width;j++){
*(result+j+i*info.width) = clusters[(*(items+j+i*info.width)).numCluster].centroide;
}
}
}
}
// Algorithme k-means atomique.
void kmeans(int k){
char ext_name [] = "_Kmeans";
initNameFile(ext_name);
K = k ;
kmeansAlgorithm();
applyKmeansOnImage();
}
--- Le fichier application.c ---
// Charles MOUTE --> 03X202
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <curses.h>
#include "algorithmes.h"
/*Variables Globales d'interface */
//int kwidth=5; //largeur ou nombre de colonne du filtre que l'on applique a info.image
//int kheight=5; //hauteur ou nombre de ligne que l'on applique a info.image
int normalized=1; //booleen signalant si le resultat d'une operation sur une image doit etre normalisee ou pas
//kernel_* represente un filtre que l'on appliquera a info.image
int kernel [5][5] = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}};
int kernel_moyenne_passe_bas[3][3] = {{1,1,1},{1,1,1},{1,1,1}}; // filtre moyenne-passe-bas.
int kernel_sobel_1 [3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}};//sobel filter.
int kernel_sobel_2 [3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}}; // sobel filter 2.
int kernel_prewitt_1 [3][3] = {{-1,-1,-1},{0,0,0},{1,1,1}}; // filtre de Prewitt 1.
int kernel_prewitt_2 [3][3] = {{-1,0,1},{-1,0,1},{-1,0,1}}; // filtre de Prewitt 2
//int kernel[3][3] = {{1,2,1},{2,4,2},{1,2,1}};
//int kernel[5][5] = {{1,4,6,6,1},{4,16,24,16,4},{6,24,36,24,6},{4,16,24,16,4},{1,4,6,6,1}};
//int kernel[5][5] = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}};
char file_current [MAX_STRING] ="\0"; //variable représentant le fichier courant
int isFirst = 1 ;
//Menu principale lorsque l'on entre dans le programme pour la première fois.
char* main_menu [] = {
"1. Choisir une image.",
"2. Quitter.",
0
};
//Représente le menu principal lorsqu'une image a déjà était choisie.
char* extend_menu [] = {
"1. Choisir une image.",
"2. Visualiser image.",
"3. Proprietes image.",
"4. Histogramme image.",
"5. Traitements sur image.",
"6. Quitter",
0
};
//Donne la liste des opérations applicables sur une image.
char* traitement_submenu [] = {
"1. Convolution.",
"2. Segmentation.",
"3. Precedent",
0
};
//Représente les différents filtres applicables pour une convolution.
char* convolution_submenu [] = {
"1. Filre moyenne-passe-bas.",
"2. Filtre de Sobel 1.",
"3. Filtre de Sobel 2.",
"4. Filtre de Prewitt 1.",
"5. Filtre de Prewitt 2.",
"6. Filtre Quelconque.",
"7. Visualiser image.",
"8. Precedent.",
0
};
// Représente les différents options pour une segmentation.
char* segmentation_submenu [] = {
"1. K-means.",
"2. Otsu.",
"3. Visualiser image.",
"4. Precedent.",
0
};
/* Permet de mettre en surbrillance le choix d'un utilisateur en attendant sa validation.
Les paramétres, une liste d'option, l'option en mettre en surbrillance dans la liste des
colonnes, la ligne et colonne de début où commencer à afficher les options à l'écran.
*/
/* Demande une saisie qu'elle lit à la position courante du curseur. Elle supprime tout saut
de ligne présent à la fin de la ligne*/
void getString(char* chaine) {
int length ;
wgetnstr(stdscr,chaine,MAX_STRING);
length = strlen(chaine);
if(length >0 && chaine[length-1]== '\n') chaine[length-1]='\0';
}
/* Demande confirmation à l'utilisateur pour une action */
int showMessageConfirm() {
int confirm = 0 ;
char answer ;
mvprintw(QUESTION_ROW,5,"Etes-vous sur ? ");
clrtoeol();
refresh();
cbreak();
answer = getch();
if(answer=='o' || answer== 'y' || answer=='O' || answer=='Y') confirm = 1 ;
nocbreak();
if(!confirm){
mvprintw(QUESTION_ROW,1," Annulation");
clrtoeol();
refresh();
sleep(1);
}
return confirm ;
}
/* Nettoie l'écran et affiche l'objectif de notre application sous forme de titre. */
void clear_screen() {
clear();
//attron(A_UNDERLINE);
mvprintw(2,20,"Application de Traitements d'Image");
//attroff(A_UNDERLINE);
if(file_current[0])
mvprintw(PROMPT_ROW-2,0,"Le fichier actif est : %s\n",file_current);
refresh();
}
/* Permet d'afficher le menu avec un element en subrillance */
void display_menu(char* options[],int surbrill_item,int row_begin,int columm_begin){
int row_current = 0 ;
char** option;
char* txt;
option = options ;
while(*option){
if(row_current==surbrill_item) mvaddch(row_begin+row_current,columm_begin-3,ACS_RARROW);
else mvaddch(row_begin+row_current,columm_begin-3,' ');
txt = options[row_current];
mvprintw(row_begin+row_current,columm_begin,"%s",txt);
row_current++;
option++;
}
mvprintw(row_begin+row_current+5,columm_begin,"Déplacez la surbrillance puis appuyer sur entrée ");
refresh();
}
/* Permet d'obtenir le choix effectue par l'utilisateur à partir d'un ensemble d'options.*/
int select_item(char* prompt,char* options[]){
static int row_selected = 0 ;
int row_max = 0;
int row_begin = MESSAGE_ROW, col_begin = 10 ;
char** option;
int selected;
int touche = 0 ;
option = options ;
while(*option) {
row_max++;
option++;
}
if (row_selected >= row_max) row_selected = 0;
clear_screen();
mvprintw(row_begin-2,col_begin,prompt);
keypad(stdscr,TRUE);
cbreak();
noecho();
touche = 0 ;
while( touche!='q' && touche!=KEY_ENTER && touche!='\n') {
if(touche==KEY_UP){
if(row_selected==0) row_selected = row_max -1 ;
else row_selected--;
}
if(touche==KEY_DOWN){
if(row_selected==(row_max-1)) row_selected = 0 ;
else row_selected++;
}
selected = *options[row_selected];
display_menu(options,row_selected,row_begin,col_begin);
touche = getch();
}
keypad(stdscr,FALSE);
nocbreak();
echo();
if(touche =='q') selected = 'q';
return (selected);
}
void chooseFile(){
int row_begin = MESSAGE_ROW,col_begin = 10 ;
clear_screen();
mvprintw(row_begin-2,1,"{ Path : Home - Select a file }");
mvprintw(row_begin,col_begin,"Donnez le chemin d'un fichier image : ");
getString(file_current);
free_memory();
if(file_current[0]){ isFirst = 0; init_variables(file_current); }
else isFirst = 1 ;
}
/* Menu principal dans le cas du traitement d'une segmentation */
//1-4
void main_segmentation() {
int select ;
do{
select = select_item ("{ Path : Home - Traitements- Segmentation }",segmentation_submenu);
switch(select) {
case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
case '4' : select ='q'; break;//mvprintw(ERROR_ROW-4,5,segmentation_submenu[3]);break;
case '1' : clear_screen();
mvprintw(MESSAGE_ROW,5,"Donnez le nombre de cluster : ");
int k = getch();
kmeans(k);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee avec %d clusters",segmentation_submenu[0]+2,k);
getch();
break;
//mvprintw(ERROR_ROW-4,25,segmentation_submenu[0]);break;
case '2': clear_screen();
Otsu();
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee avec un seuil de %d",segmentation_submenu[1]+2,getOtsuSeuil());
getch();
break;
//mvprintw(ERROR_ROW-4,25,segmentation_submenu[1]);break;
case '3' : clear_screen();
visualize(getNameFile());
getch();
break;
//mvprintw(ERROR_ROW-4,25,segmentation_submenu[2]);break;
}
refresh();
}while(select!='q');
}
/* Menu principal dans le cas du traitement d'une convolution */
void main_convolution() {
int select ;
do{
select = select_item ("{ Path : Home - Traitements }",convolution_submenu);
switch(select) {
case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
case '8' : select ='q'; break;//mvprintw(ERROR_ROW-4,5,convolution_submenu[7]);break;
case '1' : clear_screen();
initNameFile("_Filre_Moyenne_Passe_Bas");
convolve((int*)kernel_moyenne_passe_bas,3,3,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[0]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[0]);break;
case '2' : clear_screen();
initNameFile("_Filre_Sobel_1");
convolve((int*)kernel_sobel_1,3,3,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[1]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[1]);break;
case '3' : clear_screen();
initNameFile("_Filre_Sobel_2");
convolve((int*)kernel_sobel_2,3,3,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[2]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[2]);break;
case '4' : clear_screen();
initNameFile("_Filre_Prewitt_1");
convolve((int*)kernel_prewitt_1,3,3,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[3]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[3]);break;
case '5' : clear_screen();
initNameFile("_Filre_Prewitt_2");
convolve((int*)kernel_prewitt_2,3,3,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[4]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[4]);break;
case '6' : clear_screen();
initNameFile("_Filre_Quelconque");
convolve((int*)kernel,5,5,normalized);
rewriteImage(getOperationResult());
mvprintw(MESSAGE_ROW,5,"%s effectuee",convolution_submenu[5]+2);
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[5]);break;
case '7' : clear_screen();
visualize(getNameFile());
getch();
break;
//mvprintw(ERROR_ROW-4,25,convolution_submenu[6]);break;
}
refresh();
}while(select!='q');
}
/* Menu principal dans le cas du sous-menu traitement */
void main_traitement() {
int select ;
do{
select = select_item ("{ Path : Home - Traitements }",traitement_submenu);
switch(select) {
case 'q' : break;//mvprintw(ERROR_ROW-4,25,"Quitter");break;
case '3' : select ='q'; break; //mvprintw(ERROR_ROW-4,5,traitement_submenu[2]);break;
case '1' : main_convolution(); break;//mvprintw(ERROR_ROW-4,25,traitement_submenu[0]);
case '2' : main_segmentation(); break;//mvprintw(ERROR_ROW-4,25,traitement_submenu[1]);
}
refresh();
}while(select!='q');
initNameFile(NULL);
}
int main() {
int select;
initscr();
start_color();
do{
select = select_item ("{ Path : Home }",file_current[0]?extend_menu:main_menu);
switch(select) {
case 'q' : //mvprintw(ERROR_ROW-3,5,"Quitter");
break;
case '6' : //mvprintw(ERROR_ROW-3,5,extend_menu[5]);
select = 'q';
break;
case '2' :
if(isFirst) select = 'q';
else{
clear_screen();
visualize(getImageName());
getch();
}
break ;
case '1' : chooseFile();
//mvprintw(ERROR_ROW-3,5,main_menu[0]);
break ;
case '3' : clear_screen();
displayImageProperties();
getch();
//mvprintw(ERROR_ROW-3,5,extend_menu[2]);
break ;
case '4' : //mvprintw(ERROR_ROW-3,5,extend_menu[3]);
clear_screen();
displayImageHistogramme();
getch();
break ;
case '5' : main_traitement();
break ;//ivprintw(ERROR_ROW-3,5,extend_menu[4]);
}
refresh();
}while(select!='q');
endwin();
free_memory();
exit(EXIT_SUCCESS);
}
--- le fichier MakeFile ---
SOURCE=./
CC=gcc
CFLAGS= -lcurses
CMD=application
all: exe
exe: $(CMD).c
$(CC) -I $(SOURCE) -o $(CMD).exe $(CMD).c $(CFLAGS)
test: $(CMD).exe
./$(CMD).exe
clean:
rm -rf $(CMD).exe
Conclusion
--- Services Exigés
1 - Systéme d'exploitation : une distribution linux. 2 - Librairie curses.h 3 - Le compilateur gcc et le programme make. 4 - Le visualiseur d'image kview (vous pourrez le modifier directement dans le code de la fonction visualize(char*filename) ) 5 - Des fichiers images au format pgm (car le programme tourne sur la structure de ces derniers)
--- Instructions pour tester le programme ---
1- Pour recompiler vous devez taper d'abord make clean et ensuite make all
2- Pour tester l'application tapez make test. Afin d'éviter une erreur du genre " vous n'avez pas la permission pour execlp " nous vous conseillons de copier d'abord les fichiers sur votre distribution linux.
3- Pour effacer les fichiers générés lors de la compilation vous devez taper make clean.
--- Présentation sommaire de l'application ---
L'interface de l'application a été fait à partir de la librairie curses, et nous avons considéré que la configuration de curses impose directement ncurses. Si ce n'est pas le cas de votre systéme, une erreur pourrait survenir et pour la corriger vous devrez modifier les option SOURCE et CFLAGS du fichier Makefile ainsi qu'il suit : SOURCE=.:/usr/include/ncurses CFLAGS= -lncurses Principalement vous aurez quatres menus. A tout moment vous pouvez taper q pour sortir d'un menu et l'option de visualisation vous permet d'afficher la derniére image à laquelle vous avez eût accés.
- Le premier menu : Menu principale
1. Choisir une image. 2. Quitter.
Ce menu est le menu lorsqu'aucune image n'a été choisie.
- Le menu principale étendu : donne la liste des opérations possibles sur l'image courante. L'option visualiser à ce niveau vous permet d'afficher l'image originelle.
1. Choisir une image. 2. Visualiser image. 3. Proprietes image. 4. Histogramme image. 5. Traitements sur image. 6. Quitter
- Le menu des traitements
1. Convolution. 2. Segmentation. 3. Precedent
- Le menu des opérations proposés sur la convolution : vous ne pouvez visualiser l'image qu'une fois un traitement appliqué. Auquel quel cas aucune image ne s'affiche.
1. Filre moyenne-passe-bas. 2. Filtre de Sobel 1. 3. Filtre de Sobel 2. 4. Filtre de Prewitt 1. 5. Filtre de Prewitt 2. 6. Filtre Quelconque. 7. Visualiser image. 8. Precedent.
- Le menu des opérations proposés sur la segmentation.
1. K-means. 2. Otsu. 3. Visualiser image. 4. Precedent.
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
Librairie Curses [ par Zevka ]
Salut,Je suis en première année de DUT, on on va entamer un projet en C utilisant la librairie Curses.J'ai farfouillé un peu mais je n'ai trouvé que t
CURSES.H [ par kevgom ]
Bonjour,Je cherche depuis 2 semaine la librairie curses.h pour mon projet d'info en C et je n'ai trouvé qu'une vague source plutot fausse a priori car
Structure ligne + bibliothèque curses !! [ par flopflopp ]
Bonjour, je travaille sur le développement d'un éditeur de texte très simple type vi mais encore plus simple.Pour celà je créer 3 modules, 1 module li
Produit de convolution 2D [ par dartal ]
Salut ! Je dois realiser un produit de convolution pour pouvoir filtrer une image avec un masque ( un tableau de taille 3*3 )... J'ai reussi à
convolution 2D [ par gasougasou ]
quelqu'un sait commun s'effectue la convolution d'une image par un masque? (code source bien venu)?Merci d'avance
convolution filter [ par dmothes ]
Bonjour, je n'arrive pas à utiliser la fonction : glConvolutionFilter2D.j'ai droit à cette erreur là :main.cpp(110): e
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|