/*************************************************************************************************************************************/ /* */ /* E X T R A C T I O N D ' U N C O N T O U R : */ /* */ /* */ /* Definition : */ /* */ /* Cette commande permet d'extraire */ /* un contour contenu dans une image */ /* Argument. */ /* */ /* */ /* Author of '$xci/contours.11$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 19990602155545). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* I N T E R F A C E ' listG ' : */ /* */ /* */ /* :Debut_listG: */ /* :Fin_listG: */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_BASE #include image_image_CONTOURS_EXT /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R A M E T R E S : */ /* */ /*************************************************************************************************************************************/ #define SEUIL_DE_LIMITE_ENTRE_L_INTERIEUR_ET_L_EXTERIEUR \ GRIS \ /* Seuil de limite entre l'interieur et l'exterieur des contours : */ \ /* */ \ /* niveaux <= seuil : EXTERIEUR */ \ /* niveaux > seuil : INTERIEUR */ \ /* */ #define X_POINT_DE_DEPART_DU_CONTOUR \ _____cNORMALISE_OX(Xmin) #define Y_POINT_DE_DEPART_DU_CONTOUR \ _____cNORMALISE_OY(Ymin) /* Point de depart de l'extraction du contours. */ #define INDICATEUR_D_ECHANTILLONNAGE_DU_CONTOUR \ ZERO \ /* Lorsque 'indicateur_d_echantillonnage_du_contour' vaut */ \ /* 'indicateur_d_echantillonnage_du_contour', le point courant du contour est edite... */ #define PAS_D_ECHANTILLONNAGE_DU_CONTOUR \ UN \ /* Pour un point extrait du contour, on en saute 'pas_d_echantillonnage_du_contour'-1. */ #define NIVEAU_DE_MARQUAGE_DU_CONTOUR \ BLANC \ /* Niveau de marquage du contour extrait. */ #define EDITER_LES_POINTS_DU_CONTOUR \ VRAI \ /* Afin d'editer les points du contour... */ #define EDITER_LE_CENTRE_DE_GRAVITE_DU_CONTOUR \ FAUX \ /* Afin d'editer le centre de gravite du contour (introduit le 20051207140139). */ #define EDITER_UN_POINT_INTERIEUR_AU_CONTOUR \ FAUX \ /* Afin d'editer un point interieur au contour utile a 'v $xci/contours.12$K'. */ #define ECHELLE_X \ FU #define TRANSLATION_X \ FZERO /* {echelle,translation} relative aux coordonnees 'X'. */ #define ECHELLE_Y \ FU #define TRANSLATION_Y \ FZERO /* {echelle,translation} relative aux coordonnees 'Y'. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ #define DEFINE_CONTOUR(logique1,logique2) \ Bblock \ BoIn(niveau,NOIR,seuil_de_limite_entre_l_interieur_et_l_exterieur,PAS_COULEURS) \ Bblock \ EGAL(ITb1(exterieur,INDX(niveau,NOIR)),logique1); \ EGAL(ITb1(interieur,INDX(niveau,NOIR)),logique2); \ Eblock \ EBoI \ \ BoIn(niveau,SUCN(seuil_de_limite_entre_l_interieur_et_l_exterieur),BLANC,PAS_COULEURS) \ Bblock \ EGAL(ITb1(exterieur,INDX(niveau,NOIR)),logique2); \ EGAL(ITb1(interieur,INDX(niveau,NOIR)),logique1); \ Eblock \ EBoI \ Eblock \ /* Definition de l'interieur et de l'exterieur d'un contour. */ #define MODIFICATION_X(x) \ AXPB(echelle_X,x,translation_X) \ /* Modification des coordonnees 'X'. */ #define MODIFICATION_Y(y) \ AXPB(echelle_Y,y,translation_Y) \ /* Modification des coordonnees 'Y'. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* E X T R A C T I O N D ' U N C O N T O U R : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(CHAR,INIC(POINTERc(nom_imageR),NOM_PIPE)); DEFV(CHAR,INIC(POINTERc(nom_imageA),NOM_PIPE)); DEFV(genere_p,INIT(seuil_de_limite_entre_l_interieur_et_l_exterieur,SEUIL_DE_LIMITE_ENTRE_L_INTERIEUR_ET_L_EXTERIEUR)); /* Seuil de limite entre l'interieur et l'exterieur des contours : */ /* */ /* niveaux <= seuil : EXTERIEUR */ /* niveaux > seuil : INTERIEUR */ /* */ DEFV(Int,INIT(indicateur_d_echantillonnage_du_contour,INDICATEUR_D_ECHANTILLONNAGE_DU_CONTOUR)); /* Lorsque 'indicateur_d_echantillonnage_du_contour' vaut */ /* 'indicateur_d_echantillonnage_du_contour', le point courant du contour est edite... */ DEFV(Int,INIT(pas_d_echantillonnage_du_contour,PAS_D_ECHANTILLONNAGE_DU_CONTOUR)); /* Pour un point extrait du contour, on en saute 'pas_d_echantillonnage_du_contour'-1. */ DEFV(processus,Pextraction); /* Processus d'extraction du contour. */ DEFV(Logical,DTb1(exterieur,COULEURS)); /* Definition de l'exterieur, */ DEFV(Logical,DTb1(interieur,COULEURS)); /* Et de l'interieur. */ DEFV(pointF_2D,point_de_depart); /* Point de depart de l'extraction de contour. */ DEFV(Logical,INIT(fin_de_contour,FAUX)); /* Afin de connaitre le dernier point du contour, mais on n'y est pas encore... */ DEFV(pointF_2D,point_courant_extrait); /* Point courant extrait du contour dans [0,1]. */ DEFV(genere_p,INIT(niveau_de_marquage_du_contour,NIVEAU_DE_MARQUAGE_DU_CONTOUR)); /* Niveau de marquage du contour extrait. */ DEFV(Logical,INIT(emission_des_points,VRAI)); /* Afin de transmettre les points du contour. On notera que cet indicateur est toujours */ /* 'VRAI' afin de ne pas bloquer le processus qui fait un 'Tant(EST_FAUX(fin_de_contour))'. */ DEFV(Logical,INIT(editer_les_points_du_contour,EDITER_LES_POINTS_DU_CONTOUR)); /* Afin d'editer les points du contour... */ DEFV(Logical,INIT(editer_le_centre_de_gravite_du_contour,EDITER_LE_CENTRE_DE_GRAVITE_DU_CONTOUR)); /* Afin d'editer le centre de gravite du contour (introduit le 20051207140139). */ DEFV(Logical,INIT(editer_un_point_interieur_au_contour,EDITER_UN_POINT_INTERIEUR_AU_CONTOUR)); /* Afin d'editer un point interieur au contour utile a 'v $xci/contours.12$K'. */ DEFV(Float,INIT(echelle_X,ECHELLE_X)); DEFV(Float,INIT(translation_X,TRANSLATION_X)); /* {echelle,translation} relative aux coordonnees 'X'. */ DEFV(Float,INIT(echelle_Y,ECHELLE_Y)); DEFV(Float,INIT(translation_Y,TRANSLATION_Y)); /* {echelle,translation} relative aux coordonnees 'Y'. */ /*..............................................................................................................................*/ INITIALISATION_POINT_2D(point_de_depart,X_POINT_DE_DEPART_DU_CONTOUR,Y_POINT_DE_DEPART_DU_CONTOUR); /* Introduit le 20050310155758 pour eviter de voir "n'importe quoi" lorsque l'option */ /* "Parametres=VRAI" est active... */ GET_ARGUMENTSv(nombre_d_arguments ,BLOC(GET_ARGUMENT_L("Iextraction_contour_____compatibilite_20070213=""compatibilite_20070213=" ,Iextraction_contour_____compatibilite_20070213 ); GET_ARGUMENT_L("Iextraction_contour_____compatibilite_20070407=""compatibilite_20070407=" ,Iextraction_contour_____compatibilite_20070407 ); GET_ARGUMENT_C("imageA=""A=",nom_imageA); GET_ARGUMENT_C("imageR=""R=",nom_imageR); GET_ARGUMENT_P("seuil=""s=",seuil_de_limite_entre_l_interieur_et_l_exterieur); GET_ARGUMENT_I("pas=",pas_d_echantillonnage_du_contour); GET_ARGUMENT_P("niveau=",niveau_de_marquage_du_contour); GIT_ARGUMENT_F("x=""X=",ASD1(point_de_depart,x),X_POINT_DE_DEPART_DU_CONTOUR); GIT_ARGUMENT_F("y=""Y=",ASD1(point_de_depart,y),Y_POINT_DE_DEPART_DU_CONTOUR); GET_ARGUMENT_I("nombre_minimal_de_points=""minimum=" ,Iextraction_contour_____nombre_minimal_de_points_du_contour ); /* Afin de resoudre le probleme 'v $xiii/contours$FON 20070214153034' dit des impasses, */ /* ce parametre fut introduit le 20070215130840... */ GET_ARGUMENT_L("points_contour=""edition=""editer=",editer_les_points_du_contour); GET_ARGUMENT_L("g=""centre_gravite=""G=",editer_le_centre_de_gravite_du_contour); GET_ARGUMENT_L("point_interieur=""interieur=",editer_un_point_interieur_au_contour); GET_ARGUMENT_F("Ex=""EX=",echelle_X); GET_ARGUMENT_F("Tx=""TX=",translation_X); GET_ARGUMENT_F("Ey=""EY=",echelle_Y); GET_ARGUMENT_F("Ty=""TY=",translation_Y); ) ); CALi(Inoir(ImageR)); /* Initialisation de l'image Resultat. */ Test(IFGE(seuil_de_limite_entre_l_interieur_et_l_exterieur,BLANC)) Bblock PRINT_ERREUR("le seuil de limite entre l'interieur et l'exterieur doit etre inferieur au niveau maximal"); EGAL(seuil_de_limite_entre_l_interieur_et_l_exterieur,PREN(BLANC)); Eblock ATes Bblock Eblock ETes Test(PAS_D_ERREUR(CODE_ERROR(Iload_image(ImageA,nom_imageA)))) Bblock DEFV(Int,INIT(nombre_de_points_du_contour,ZERO)); /* Nombre de points du contour extrait... */ DEFV(pointF_2D,centre_de_gravite_du_contour); INITIALISATION_POINT_2D(centre_de_gravite_du_contour,FZERO,FZERO); /* Centre de gravite du contour extrait... */ DEFINE_CONTOUR(VRAI,FAUX); /* Definition de l'interieur et de l'exterieur du contour... */ CALS(Idelete_image(nom_imageR)); /* Contrairement aux apparences, ce 'Idelete_image(...)' n'est pas inutile. En effet, il */ /* dans le processus 'Pextraction' l'emission d'un signal "fin_de_contour". Mais */ /* malheureusment, apres 'Iextraction_contour(...)' et donc l'envoi de ce signal de fin, */ /* il y a le 'Iupdate_image(...)'. Moralite : la commande '$xci/contours.11$X' peut rendre */ /* la main avant que le 'Iupdate_image(...)' ne soit fait. Cela s'est vu le 19990603170615 */ /* avec la mise au point de 'v $xci/contours.11$Z' ou l'appel a '$xci/contours.12$X' (qui */ /* suivait un appel a '$xci/contours.11$X') ne voyait pas encore son image Argument "A="... */ /* Donc avant de sortir de '$xci/contours.11$X' il faut tester l'existence de l'image */ /* Resultat... */ iPARALLELE(BLOC(CALS(Iextraction_contour(ImageR ,ImageA ,ADRESSE(point_de_depart) ,exterieur,interieur ,niveau_de_marquage_du_contour ,emission_des_points ,ADRESSE(Pextraction) ) ); CALi(Istore_image(nom_imageR,ImageR)); /* Et on stocke le contour en notant de nouveau que l'on n'utilise pas 'Iupdate_image(...)' */ /* car un 'Idelete_image(...)' a ete fait explicitement avant d'entrer dans le mode de */ /* fonctionnement 'iPARALLELE(...)'. */ ) ,Pextraction ); /* Envoi en parallele de l'extraction du contour, c'est-a-dire de */ /* l'equipotentielle numero 'seuil_de_limite_entre_l_interieur_et_l_exterieur'. */ Tant(EST_FAUX(fin_de_contour)) Bblock RECEIVE_F(Pextraction,ASD1(point_courant_extrait,x)); RECEIVE_F(Pextraction,ASD1(point_courant_extrait,y)); /* Recuperation du point courant du contour, */ RECEIVE_L(Pextraction,fin_de_contour); /* Et de l'indicateur de fin... */ Test(IFET(IFEQ(ASD1(point_courant_extrait,x),FLOT(COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE)) ,IFEQ(ASD1(point_courant_extrait,y),FLOT(COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE)) ) ) Bblock /* Cas ou le contour est vide ('v $xiii/contours$FON 20051207143533')... */ Eblock ATes Bblock /* Cas ou le contour n'est pas vide : */ INCR(ASD1(centre_de_gravite_du_contour,x),ASD1(point_courant_extrait,x)); INCR(ASD1(centre_de_gravite_du_contour,y),ASD1(point_courant_extrait,y)); INCR(nombre_de_points_du_contour,I); /* Cumul en vue du calcul du centre de gravite (introduit le 20051207140139)... */ Eblock ETes Test(IL_FAUT(editer_les_points_du_contour)) Bblock Test(IFOU(IFEQ(indicateur_d_echantillonnage_du_contour,INDICATEUR_D_ECHANTILLONNAGE_DU_CONTOUR) ,EST_VRAI(fin_de_contour) ) ) Bblock CAL3(Prme2("X=%+.^^^ Y=%+.^^^\n" ,MODIFICATION_X(ASD1(point_courant_extrait,x)) ,MODIFICATION_Y(ASD1(point_courant_extrait,y)) ) ); /* On n'edite les points que lorsque 'indicateur_d_echantillonnage_du_contour' est nul, ou */ /* bien pour le dernier point (afin de "refermer" le contour). */ /* */ /* Le 20060105154618, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123210, le format "^^g" est passe a "^^^" pour plus de souplesse... */ Eblock ATes Bblock Eblock ETes EGAL(indicateur_d_echantillonnage_du_contour ,MODU(SUCC(indicateur_d_echantillonnage_du_contour) ,INDICATEUR_D_ECHANTILLONNAGE_DU_CONTOUR ,PRED(INTE(DIVI(FLOT(pas_d_echantillonnage_du_contour) ,MAX2(DIVI(FLOT(dimX_BASE),FLOT(dimX)),DIVI(FLOT(dimY_BASE),FLOT(dimY))) ) ) ) ) ); /* Afin de determiner le point suivant de facon "homothetique", c'est-a-dire de facon a ce */ /* que le nombre de points extraits soit a peu pres independant de la taille de l'image... */ Eblock ATes Bblock Test(IL_FAUT(editer_un_point_interieur_au_contour)) Bblock Test(EST_VRAI(fin_de_contour)) Bblock DEFV(pointI_2D,point_d_arrivee); /* Point courant lors de la recherche d'un point interieur au contour. */ SPIRALE_DEFINITION /* Donnees de generation d'une spirale de parcours d'une image. */ SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ INITIALISATION_POINT_2D(point_d_arrivee ,_cDENORMALISE_OX(ASD1(point_courant_extrait,x)) ,_cDENORMALISE_OY(ASD1(point_courant_extrait,y)) ); /* Recuperation des coordonnees du point d'arrivee (qui etait aussi le point de depart). */ Tant(IFOU(TEST_HORS_IMAGE(ASD1(point_d_arrivee,x),ASD1(point_d_arrivee,y)) ,EST_VRAI(ITb1(exterieur ,INDX(load_point_valide(ImageA ,ASD1(point_d_arrivee,x) ,ASD1(point_d_arrivee,y) ) ,NOIR ) ) ) ) ) Bblock /* Ainsi, on cherche "en spirale" le premier point interieur au contour et qui existe */ /* (DANS_L_IMAGE). */ SPIRALE_INITIALISATION; /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ SPIRALE_DEPLACEMENT(ASD1(point_d_arrivee,x),ASD1(point_d_arrivee,y)); /* Deplacement du point courant de la spirale... */ /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir la */ /* terminaison du processus 'Tant(...)'. */ SPIRALE_PARCOURS; /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ Eblock ETan CAL3(Prme2("XI=%+.^^^ YI=%+.^^^\n" ,MODIFICATION_X(_____cNORMALISE_OX(ASD1(point_d_arrivee,x))) ,MODIFICATION_Y(_____cNORMALISE_OY(ASD1(point_d_arrivee,y))) ) ); /* Edition d'un point interieur voisin du point d'arrivee (qui est aussi le point de */ /* depart...). */ /* */ /* Le 20051207140139, {X=,Y=} a ete remplace par {XI=,YI=} afin que les trois types de */ /* sorties de coordonnees soient differentes : {{X=,Y=},{XG=,YG=},{XI=,YI=}}. Cela a */ /* implique la modification 'v $xci/contours.12$K XI='... */ /* */ /* Le 20060105154618, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123210, le format "^^g" est passe a "^^^" pour plus de souplesse... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETes Eblock ETan Test(IL_FAUT(editer_le_centre_de_gravite_du_contour)) Bblock Test(IZGT(nombre_de_points_du_contour)) Bblock INITIALISATION_POINT_2D(centre_de_gravite_du_contour ,DIVI(ASD1(centre_de_gravite_du_contour,x),nombre_de_points_du_contour) ,DIVI(ASD1(centre_de_gravite_du_contour,y),nombre_de_points_du_contour) ); /* Calcul final du centre de gravite du contour extrait... */ CAL3(Prme2("XG=%+.^^^ YG=%+.^^^\n" ,MODIFICATION_X(ASD1(centre_de_gravite_du_contour,x)) ,MODIFICATION_Y(ASD1(centre_de_gravite_du_contour,y)) ) ); /* Edition du centre de gravite (introduit le 20051207140139)... */ /* */ /* Le 20060105154618, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123210, le format "^^g" est passe a "^^^" pour plus de souplesse... */ Eblock ATes Bblock PRINT_ATTENTION("le nombre de points du contour est nul, le centre de gravite ne peut donc etre calcule"); Eblock ETes Eblock ATes Bblock Eblock ETes Test(I3OU(IL_FAUT(editer_les_points_du_contour) ,IL_FAUT(editer_le_centre_de_gravite_du_contour) ,IL_FAUT(editer_un_point_interieur_au_contour) ) ) Bblock CALS(Fsauts_de_lignes(UN)); /* "Fermeture" du fichier des coordonnees... */ Eblock ATes Bblock Eblock ETes Tant(IL_Y_A_ERREUR(Itest_image(nom_imageR))) /* Tant que 'nom_imageR' n'existe pas, cela signifie que le processus 'Pextraction' n'a pas */ /* fini son travail ; on ne peut donc pas sortir de cette commande (vu le 19990603170615). */ Bblock Eblock ETan Eblock ATes Bblock Test__CODE_ERREUR__ERREUR07; Eblock ETes RETU_Commande; Eblock ECommande