/*************************************************************************************************************************************/
/* */
/* 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