/* ==================================== */ void empilevoisins(int32_t x, int32_t rs, int32_t N, Fifo *FIFOna, Fifo *FIFOea, Fifo *FIFOsa, Fifo *FIFOoa) /* ==================================== */ { int32_t y, z, k; /* x est un point qui vient de passer a 0 */ for (k = 0; k < 8; k++) { y = voisin(x, k, rs, N); if ((y!=-1) && !IsSet(y,MINI) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { z = voisin(y, NORD, rs, N); if ((z != 0) && IsSet(z, MINI)) { FifoPush(FIFOna, y); Set(y, EN_FIFO); goto nextk; } z = voisin(y, SUD, rs, N); if ((z != 0) && IsSet(z, MINI)) { FifoPush(FIFOsa, y); Set(y, EN_FIFO); goto nextk; } z = voisin(y, EST, rs, N); if ((z != 0) && IsSet(z, MINI)) { FifoPush(FIFOea, y); Set(y, EN_FIFO); goto nextk; } z = voisin(y, OUEST, rs, N); if ((z != 0) && IsSet(z, MINI)) { FifoPush(FIFOoa, y); Set(y, EN_FIFO); goto nextk; } } nextk: ; } } /* empilevoisins() */
int* voisinageTriangle(std::vector<Triangle> listeTriangle){ int* voisinage = new int[3*listeTriangle.size()]; for(int i = 0; i<3*listeTriangle.size(); i++){ voisinage[i] = -1; } int indice = 0; for(int i =0; i< listeTriangle.size(); i++){ indice = 0; for(int j =0; j< listeTriangle.size(); j++){ if( !listeTriangle.at(i).compareTriangle(listeTriangle.at(j)) && voisin(listeTriangle.at(i), listeTriangle.at(j)) ){ voisinage[3*i + indice] = j; indice++; } } } return voisinage; }
/* ==================================== */ int32_t testabaisse(uint8_t *SOURCE, int32_t x, int32_t rs, int32_t N, int32_t seuil, int32_t niter, int32_t niseuil) /* ==================================== */ { int32_t t4mm, t4m, t8p, t8pp; int32_t modifie = 0; #ifdef DEBUG printf("testabaisse : point %d (%d %d), val = %d\n", x, x%rs, x/rs, SOURCE[x]); #endif nbtopo(SOURCE, x, rs, N, &t4mm, &t4m, &t8p, &t8pp); if (t4mm == 2) Set(x, COURBE); #ifdef REGULARISE if (IsSet(x, COURBE)) { int32_t valmaxmin = -1; int32_t k, y; /* si c'est un point de courbe "inconsistant", on l'abaisse def. x inconsistant : l'ecart entre F(x) et la valeur du minimum voisin le plus proche est < seuil */ for (k = 0; k < 8; k += 2) /* parcourt les voisins en 4-connexite */ { y = voisin(x, k, rs, N); if ((y != -1) && (IsSet(y, MINI)) && ((int32_t)(SOURCE[y]) > valmaxmin)) valmaxmin = (int32_t)(SOURCE[y]); } /* for k */ if ((valmaxmin > -1) && ((SOURCE[x] - (uint8_t)valmaxmin) < seuil)) { modifie = 1; SOURCE[x] = (uint8_t)valmaxmin; UnSet(x, COURBE); } } #endif /* if (!IsSet(x, COURBE) && */ if ((niter <= niseuil) || !extremite8(SOURCE, x, rs, N)) { while ((t4mm == 1) && (t8p == 1)) { modifie = 1; SOURCE[x] = alpha8m(SOURCE, x, rs, N); nbtopo(SOURCE, x, rs, N, &t4mm, &t4m, &t8p, &t8pp); } } /* if (!extremite8(SOURCE, x, rs, N)) */ #ifdef DEBUG if (modifie) printf("========> ABAISSE : %d\n", SOURCE[x]); #endif return modifie; } /* testabaisse() */
/* ==================================== */ void testmini(uint8_t *SOURCE, int32_t x, int32_t rs, int32_t N, Fifo *FIFO) /* ==================================== */ { int32_t k, y, kk, yy, w; uint8_t valmin; #ifdef REGULARISE for (k = 0; k < 8; k += 2) /* parcourt les voisins en 4-connexite */ { /* pour voir s'il existe un minimum voisin */ y = voisin(x, k, rs, N); /* a un niveau > a celui atteint par x */ if ((y != -1) && (IsSet(y, MINI)) && (SOURCE[y] > SOURCE[x])) { /* ce n'est plus un minimum */ FifoPush(FIFO, y); UnSet(y, MINI); valmin = SOURCE[y]; while (! FifoVide(FIFO)) /* parcours pour demarquer l'ex minimum */ { w = FifoPop(FIFO); for (kk = 0; kk < 8; kk += 2) { yy = voisin(w, kk, rs, N); if ((yy != -1) && (SOURCE[yy] == valmin) && (IsSet(yy, MINI))) { FifoPush(FIFO, yy); UnSet(yy, MINI); } } /* for kk ... */ } /* while (! FifoVide(FIFO)) */ } /* if ((y != -1) && (IsSet(y, MINI)) && (SOURCE[y] > SOURCE[x])) */ } /* for k */ #endif for (k = 0; k < 8; k += 2) /* parcourt les voisins en 4-connexite */ { /* pour voir s'il existe un minimum */ y = voisin(x, k, rs, N); /* au niveau atteint par x */ if ((y != -1) && (IsSet(y, MINI)) && (SOURCE[y] == SOURCE[x])) { Set(x, MINI); break; } } /* for k */ } /* testmini() */
/* ==================================== */ int32_t lerosfast(struct xvimage *f, uint8_t *mask) /* mask : masque du 8-voisinage representant l'element structurant */ /* ==================================== */ { int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t k; /* index muet */ int32_t rs = rowsize(f); /* taille ligne */ int32_t cs = colsize(f); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *F = UCHARDATA(f); uint8_t *H; /* image de travail */ uint8_t inf; if (depth(f) != 1) { fprintf(stderr, "ldilatfast: cette version ne traite pas les images volumiques\n"); return 0; } H = (uint8_t *)calloc(1,N*sizeof(char)); if (H == NULL) { fprintf(stderr,"lerosfast() : malloc failed for H\n"); return(0); } for (x = 0; x < N; x++) H[x] = F[x]; for (x = 0; x < N; x++) { inf = H[x]; /* l'ES est reflexif */ for (k = 0; k < 8; k += 1) { if (mask[k]) /* element structurant */ { y = voisin(x, k, rs, N); if ((y != -1) && (H[y] < inf)) inf = H[y]; #ifdef BORDZERO if (y == -1) inf = NDG_MIN; #endif } } /* for k */ F[x] = inf; } free(H); return 1; }
/* ==================================== */ int32_t abaisse8(int32_t x, int32_t *DT, int32_t rs, int32_t N) /* ==================================== */ { int32_t y, k, abaisse; int32_t t4mm, t4m, t8p, t8pp; uint32_t d, old; old = DT[x]; do { abaisse = 0; nbtopoh_l(DT, x, DT[x], rs, N, &t4mm, &t4m, &t8p, &t8pp); if ((t8p == 1) && (t4mm == 1)) { nbtopoh_l(DT, x, DT[x]-1, rs, N, &t4mm, &t4m, &t8p, &t8pp); if ((t8p == 1) && (t4mm == 1)) { d = alpha8m_l(DT, x, rs, N); d = mcmin((DT[x]-1),(d+1)); DT[x] = d; abaisse = 1; #ifdef DEBUG printf("pre-abaisse a d = %ld\n", d); #endif #ifndef OLD_VERSION for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { y = voisin(x, k, rs, N); if ((y != -1) && (DT[y] <= DT[x]) && (DT[y]==alpha8p_l(DT, y, rs, N))) { DT[x] += 1; abaisse = 0; break; } /* if y */ } /* for k */ #endif } } // if ((t8p == 1) && (t4mm == 1)) } while (abaisse); if (DT[x] < old) return 1; else return 0; } // abaisse8()
/* ==================================== */ int32_t ldir(struct xvimage * image1, int32_t dir) /* ==================================== */ { int32_t i, v; uint8_t *pt1; int32_t rs, cs, N; if (depth(image1) != 1) { fprintf(stderr, "ldir: cette version ne traite pas les images volumiques\n"); return 0; } rs = rowsize(image1); cs = colsize(image1); N = rs * cs; IndicsInit(N); /* ---------------------------------------------------------- */ /* calcul du resultat */ /* ---------------------------------------------------------- */ pt1 = UCHARDATA(image1); for (i = 0; i < N; i++) if (pt1[i]) { v = voisin(i, dir, rs, N); if ((v != -1) && (pt1[v] < pt1[i])) Set(i,0); } for (i = 0; i < N; i++) if (IsSet(i,0)) pt1[i] = NDG_MAX; else pt1[i] = NDG_MIN; IndicsTermine(); return 1; }
/* ==================================== */ int32_t lsquelval(struct xvimage *image, // entree/sortie: image originale / squelette struct xvimage *dx, // entree/sortie: distance / distance topologique int32_t connex, int32_t val_inhibit) /* ==================================== */ #undef F_NAME #define F_NAME "lsquelval" { int32_t k; int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t rs = rowsize(image); /* taille ligne */ int32_t cs = colsize(image); /* taille colonne */ int32_t N = rs * cs; /* taille image */ struct xvimage *dt; /* pour le calcul de la "distance topologique" */ uint8_t *IM = UCHARDATA(image); /* l'image de depart */ uint32_t *DX; /* fonction distance au complementaire de IM */ uint32_t *DT; /* fonction "distance topologique" */ uint32_t d; Rbt * RBT; int32_t taillemaxrbt; IndicsInit(N); if ((rowsize(dx) != rs) || (colsize(dx) != cs) || (depth(dx) != 1)) { fprintf(stderr, "%s() : bad size for dx\n", F_NAME); return(0); } if (datatype(dx) != VFF_TYP_4_BYTE) { fprintf(stderr, "%s() : datatype(dx) must be uint32_t\n", F_NAME); return(0); } DX = ULONGDATA(dx); dt = copyimage(dx); DT = ULONGDATA(dt); taillemaxrbt = 2 * rs + 2 * cs ; /* cette taille est indicative, le RBT est realloue en cas de depassement */ RBT = mcrbt_CreeRbtVide(taillemaxrbt); if (RBT == NULL) { fprintf(stderr, "%s() : mcrbt_CreeRbtVide failed\n", F_NAME); return(0); } /* ================================================ */ /* PREMIERE PHASE */ /* ================================================ */ #ifdef VERBOSE printf("1ere etape\n"); #endif // INITIALISATION DT for (x = 0; x < N; x++) if (IM[x]) DT[x] = INFINI; else DT[x] = 0; // INITIALISATION DU RBT for (x = 0; x < N; x++) if (IM[x] && (DX[x] != val_inhibit) && bordext8(IM, x, rs, N)) { mcrbt_RbtInsert(&RBT, DX[x], x); Set(x, EN_RBT); } // if, for d = 1; if (connex == 4) { while (!mcrbt_RbtVide(RBT)) { x = RbtPopMin(RBT); UnSet(x, EN_RBT); #ifdef DEBUG printf("pop x = %d,%d, im = %d, dx = %ld\n", x%rs, x/rs, IM[x], DX[x]); #endif if (simple4(IM, x, rs, N)) { DT[x] = d; IM[x] = 0; d++; for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (IM[y]) && (DX[y] != val_inhibit) && (! IsSet(y, EN_RBT))) { mcrbt_RbtInsert(&RBT, DX[y], y); Set(y, EN_RBT); } /* if y */ } /* for k */ } // if (simple4(IM, x, rs, N)) } /* while (!mcrbt_RbtVide(RBT)) */ } /* if (connex == 4) */ else if (connex == 8) { while (!mcrbt_RbtVide(RBT)) { x = RbtPopMin(RBT); UnSet(x, EN_RBT); #ifdef DEBUG printf("pop x = %d,%d, im = %d, dx = %ld\n", x%rs, x/rs, IM[x], DX[x]); #endif if (simple8(IM, x, rs, N)) { DT[x] = d; IM[x] = 0; d++; for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (IM[y]) && (DX[y] != val_inhibit) && (! IsSet(y, EN_RBT))) { mcrbt_RbtInsert(&RBT, DX[y], y); Set(y, EN_RBT); } /* if y */ } /* for k */ } // if (simple8(IM, x, rs, N)) } /* while (!mcrbt_RbtVide(RBT)) */ } /* if (connex == 8) */ #ifdef DEBUG writeimage(dt, "_dt"); #endif /* ================================================ */ /* SECONDE PHASE */ /* ================================================ */ #ifdef SECONDE_PHASE stabilite = 0; while (!stabilite) { #ifdef VERBOSE printf("2eme etape\n"); #endif stabilite = 1; // INITIALISATION DU RBT for (j = 1; j < cs-1; j++) for (i = 1; i < rs-1; i++) { x = j * rs + i; if (DT[x] && (DT[x] != INFINI)) mcrbt_RbtInsert(&RBT, DT[x], x); } if (connex == 4) { while (!mcrbt_RbtVide(RBT)) { x = RbtPopMin(RBT); #ifdef DEBUG printf("pop x = %d,%d, dt = %ld\n", x%rs, x/rs, DT[x]); #endif if (abaisse4(x, DT, rs, N)) { stabilite = 0; #ifdef DEBUG printf("abaisse a %ld\n", DT[x]); #endif } // if (abaisse4(x, DT, rs, N)) } // while (!mcrbt_RbtVide(RBT)) } // if (connex == 4) else if (connex == 8) { int32_t abaisse; while (!mcrbt_RbtVide(RBT)) { x = RbtPopMin(RBT); #ifdef DEBUG printf("pop x = %d,%d, dt = %d\n", x%rs, x/rs, DT[x]); #endif if (abaisse8(x, DT, rs, N)) { stabilite = 0; #ifdef DEBUG printf("abaisse a %ld\n", DT[x]); #endif } // if (abaisse8(x, DT, rs, N)) } // while (!mcrbt_RbtVide(RBT)) } // if (connex == 8) } // while (!stabilite) #endif // RECUPERATION DU RESULTAT d = 0; // valeur pour l'infini: plus grande valeur finie + 1 for (x = 0; x < N; x++) if ((DT[x] > d) && (DT[x] < INFINI)) d = DT[x]; d += 1; for (x = 0; x < N; x++) if (DT[x] == INFINI) DX[x] = d; else DX[x] = DT[x]; /* ================================================ */ /* UN PEU DE MENAGE */ /* ================================================ */ IndicsTermine(); mcrbt_RbtTermine(RBT); freeimage(dt); return(1); } /* lsquelval() */
/* ==================================== */ int32_t lattribute( struct xvimage *img, /* image de depart */ int32_t connex, /* 4, 8 */ int32_t typregion, /* = <LABMIN | LABMAX | LABPLATEAU> */ int32_t attrib, /* 0: surface, 1: perimetre, 2: circularite, 3: nb. trous, 4: excentricite, 5: orientation, 6: diamètre vertical, 7: diamètre horizontal */ int32_t seuil, /* en dessous (<=) de seuil, l'attribut est mis a 0 */ struct xvimage *lab, /* resultat: image d'attributs */ int32_t *nlabels) /* resultat: nombre de regions traitees */ /* ==================================== */ #undef F_NAME #define F_NAME "lattribute" { int32_t k, l; index_t w, x, y, z; uint8_t *SOURCE = UCHARDATA(img); int32_t *LABEL = SLONGDATA(lab); index_t rs = rowsize(img); index_t cs = colsize(img); index_t d = depth(img); index_t N = rs * cs; /* taille image */ Lifo * LIFO; int32_t label; int32_t area; int32_t perim; int32_t min, max; int32_t val_attrib; double mx1, my1; // cumuls des variables x et y double mx2, my2, mxy2; // cumuls des x^2, y^2 et xy int32_t incr_vois; if (datatype(lab) != VFF_TYP_4_BYTE) { fprintf(stderr, "%s: le resultat doit etre de type VFF_TYP_4_BYTE\n", F_NAME); return 0; } if ((rowsize(lab) != rs) || (colsize(lab) != cs) || (depth(lab) != d)) { fprintf(stderr, "%s: tailles images incompatibles\n", F_NAME); return 0; } if (depth(img) != 1) { fprintf(stderr, "%s: cette version ne traite pas les images volumiques\n", F_NAME); exit(0); } switch (connex) { case 4: incr_vois = 2; break; case 8: incr_vois = 1; break; default: fprintf(stderr, "%s: mauvaise connexite: %d\n", F_NAME, connex); return 0; } /* switch (connex) */ /* le LABEL initialement est mis a NONMARQUE */ for (x = 0; x < N; x++) LABEL[x] = NONMARQUE; LIFO = CreeLifoVide(N); if (LIFO == NULL) { fprintf(stderr, "%s: CreeLifoVide failed\n", F_NAME); return(0); } *nlabels = 0; if ((typregion == LABMIN) || (typregion == LABMAX)) { for (x = 0; x < N; x++) { if (LABEL[x] == NONMARQUE) /* on trouve un point x non etiquete */ { *nlabels += 1; LABEL[x] = MARQUE; #ifdef DEBUGTROU printf("AMORCE p=%d,%d h=%d set LABEL = %d\n", x%rs, x/rs, SOURCE[x], LABEL[x]); #endif switch (attrib) /* on initialise les attributs de cette composante */ { case AREA: val_attrib = 0; break; case PERIM: val_attrib = 0; break; case TROUS: val_attrib = 0; break; case CIRC: area = perim = 0; break; case EXCEN: case ORIEN: area = 0; mx1 = my1 = mx2 = my2 = mxy2 = 0.0; break; case VDIAM: min = cs-1; max = 0; break; case HDIAM: min = rs-1; max = 0; break; default: fprintf(stderr, "%s: mauvais attribut: %d\n", F_NAME, attrib); return 0; } /* switch (attrib) */ LifoPush(LIFO, x); /* on va parcourir le plateau auquel appartient x */ while (! LifoVide(LIFO)) { w = LifoPop(LIFO); label = LABEL[w]; if (label == MARQUE) /* c'est une propagation de "marquage" : pour l'instant, */ { /* on croit qu'on est dans un extremum */ switch (attrib) { case AREA: val_attrib++; break; case VDIAM: if (w/rs < min) min = w/rs; else if (w/rs > max) max = w/rs; break; case HDIAM: if (w%rs < min) min = w%rs; else if (w%rs > max) max = w%rs; break; case EXCEN: case ORIEN: area++; mx1 += w%rs; my1 += w/rs; mxy2 += (w%rs) * (w/rs); mx2 += (w%rs) * (w%rs); my2 += (w/rs) * (w/rs); break; case PERIM: if (w%rs==rs-1) val_attrib++; /* point de bord */ if (w<rs) val_attrib++; /* point de bord */ if (w%rs==0) val_attrib++; /* point de bord */ if (w>=N-rs) val_attrib++; /* point de bord */ for (k = 0; k < 8; k += 2) /* 4-connexite obligatoire */ { y = voisin(w, k, rs, N); if ((y != -1) && (SOURCE[y] != SOURCE[w])) val_attrib++; } /* for k */ break; case CIRC: area++; if (w%rs==rs-1) perim++; /* point de bord */ if (w<rs) perim++; /* point de bord */ if (w%rs==0) perim++; /* point de bord */ if (w>=N-rs) perim++; /* point de bord */ for (k = 0; k < 8; k += 2) /* 4-connexite obligatoire */ { y = voisin(w, k, rs, N); if ((y != -1) && (SOURCE[y] != SOURCE[w])) perim++; } /* for k */ break; } /* switch (attrib) */ for (k = 0; k < 8; k += incr_vois) { y = voisin(w, k, rs, N); if (y != -1) { if (((typregion == LABMIN) && (SOURCE[y] < SOURCE[w])) || ((typregion == LABMAX) && (SOURCE[y] > SOURCE[w]))) { /* w non dans un minimum (resp. maximum) */ if (label == MARQUE) { label = NONEXTREM; *nlabels -= 1; LABEL[w] = label; LifoPush(LIFO, w); } } else if ((SOURCE[y] == SOURCE[w]) && (LABEL[y] == NONMARQUE)) { LABEL[y] = label; #ifdef DEBUGTROU printf(" p=%d,%d h=%d set LABEL = %d\n", y%rs, y/rs, SOURCE[y], LABEL[y]); #endif LifoPush(LIFO, y); if (attrib == TROUS) { int32_t masque = 0, imasque = 1; /* fabrique le masque des voisins de y MARQUES */ for (l = 0; l < 8; l += 1) { z = voisin(y, l, rs, N); if ((z != -1) && (LABEL[z] == MARQUE)) masque |= imasque; imasque = imasque << 1; } /* for k ... */ #ifdef DEBUGTROU printf(" p=%d,%d h=%d masque=%x t4m=%d t8b=%d\n", y%rs, y/rs, SOURCE[y], masque, t4(masque), t8b(masque)); #endif if (connex == 4) { val_attrib += (t4(masque) - 1); if (t8b(masque) == 0) val_attrib--; } else { val_attrib += (t8(masque) - 1); if (t4b(masque) == 0) val_attrib--; } } /* if (attrib == TROUS) */ } /* if ((SOURCE[y] == SOURCE[w]) && (LABEL[y] == NONMARQUE)) */ } /* if (y != -1) */ } /* for k ... */ } /* if (label == MARQUE) */ else /* propagation de "demarquage" */ { for (k = 0; k < 8; k += incr_vois) { y = voisin(w, k, rs, N); if (y != -1) { if ((SOURCE[y] == SOURCE[w]) && (LABEL[y] != NONEXTREM)) { LABEL[y] = NONEXTREM; LifoPush(LIFO, y); } /* if .. */ } /* if (y != -1) */ } /* for k ... */ } /* else if (label == MARQUE) */ } /* while (! LifoVide(LIFO)) */ if (label == MARQUE) { if (attrib == CIRC) { val_attrib = (int32_t)(256 * 4 * M_PI * (double)area / (double)(perim * perim)); if (val_attrib > 255) { fprintf(stderr, "WARNING: indice de circularite > 255 : %d, a=%d, p=%d\n", val_attrib, area, perim); val_attrib = 255; } } if (attrib == EXCEN) val_attrib = excentricity(mx1, my1, mx2, my2, mxy2, area); if (attrib == ORIEN) val_attrib = orientation(mx1, my1, mx2, my2, mxy2, area); if (attrib == VDIAM) val_attrib = max - min + 1; if (attrib == HDIAM) val_attrib = max - min + 1; if (val_attrib <= seuil) val_attrib = 0; #ifdef VERBOSE printf("valeur attribut = %d\n", val_attrib); #endif LifoPush(LIFO, x); /* on re-parcourt le plateau pour propager l'attribut */ LABEL[x] = val_attrib; while (! LifoVide(LIFO)) { w = LifoPop(LIFO); for (k = 0; k < 8; k += incr_vois) { y = voisin(w, k, rs, N); if ((y != -1) && (LABEL[y] == MARQUE)) { LABEL[y] = val_attrib; LifoPush(LIFO, y); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (label == MARQUE) */ } /* if (LABEL[x] != -1) */ } /* for (x = 0; x < N; x++) */ } /* if ((typregion == LABMIN) || (typregion == LABMAX)) */ else { if (attrib == TROUS) { fprintf(stderr, "%s: attribut TROUS non compatible avec typreg = PLA\n", F_NAME); return 0; } for (x = 0; x < N; x++) { if (LABEL[x] == NONMARQUE) { *nlabels += 1; LABEL[x] = *nlabels; switch (attrib) /* on initialise les attributs de cette composante */ { case AREA: val_attrib = 0; break; case VDIAM: min = cs-1; max = 0; break; case HDIAM: min = rs-1; max = 0; break; case PERIM: val_attrib = 0; break; case CIRC: area = perim = 0; break; case EXCEN: case ORIEN: area = 0; mx1 = my1 = mx2 = my2 = mxy2 = 0.0; break; default: fprintf(stderr, "%s: mauvais attribut: %d\n", F_NAME, attrib); return 0; } /* switch (attrib) */ LifoPush(LIFO, x); while (! LifoVide(LIFO)) { w = LifoPop(LIFO); switch (attrib) { case AREA: val_attrib++; break; case VDIAM: if (w/rs < min) min = w/rs; else if (w/rs > max) max = w/rs; break; case HDIAM: if (w%rs < min) min = w%rs; else if (w%rs > max) max = w%rs; break; case EXCEN: case ORIEN: area++; mx1 += w%rs; my1 += w/rs; mxy2 += (w%rs) * (w/rs); mx2 += (w%rs) * (w%rs); my2 += (w/rs) * (w/rs); break; case PERIM: if (w%rs==rs-1) val_attrib++; /* point de bord */ if (w<rs) val_attrib++; /* point de bord */ if (w%rs==0) val_attrib++; /* point de bord */ if (w>=N-rs) val_attrib++; /* point de bord */ for (k = 0; k < 8; k += 2) /* 4-connexite obligatoire */ { y = voisin(w, k, rs, N); if ((y != -1) && (SOURCE[y] != SOURCE[w])) val_attrib++; } /* for k */ break; case CIRC: area++; if (w%rs==rs-1) perim++; /* point de bord */ if (w<rs) perim++; /* point de bord */ if (w%rs==0) perim++; /* point de bord */ if (w>=N-rs) perim++; /* point de bord */ for (k = 0; k < 8; k += 2) /* 4-connexite obligatoire */ { y = voisin(w, k, rs, N); if ((y != -1) && (SOURCE[y] != SOURCE[w])) perim++; } /* for k */ break; } /* switch (attrib) */ for (k = 0; k < 8; k += incr_vois) { y = voisin(w, k, rs, N); if ((y != -1) && (LABEL[y] == NONMARQUE) && (SOURCE[y] == SOURCE[w])) { LABEL[y] = MARQUE; LifoPush(LIFO, y); } /* if y ... */ } /* for k ... */ } /* while (! LifoVide(LIFO)) */ if (attrib == CIRC) { val_attrib = (int32_t)(256 * 4 * M_PI * (double)area / (double)(perim * perim)); if (val_attrib > 255) { fprintf(stderr, "WARNING: indice de circularite > 255 : %d, a=%d, p=%d\n", val_attrib, area, perim); val_attrib = 255; } } if (attrib == EXCEN) val_attrib = excentricity(mx1, my1, mx2, my2, mxy2, area); if (attrib == ORIEN) val_attrib = orientation(mx1, my1, mx2, my2, mxy2, area); if (attrib == VDIAM) val_attrib = max - min + 1; if (attrib == HDIAM) val_attrib = max - min + 1; if (val_attrib <= seuil) val_attrib = 0; LifoPush(LIFO, x); /* on re-parcourt le plateau pour propager l'attribut */ LABEL[x] = val_attrib; while (! LifoVide(LIFO)) { w = LifoPop(LIFO); for (k = 0; k < 8; k += incr_vois) { y = voisin(w, k, rs, N); if ((y != -1) && (LABEL[y] == MARQUE)) { LABEL[y] = val_attrib; LifoPush(LIFO, y); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (LABEL[x] == NONMARQUE) */ } /* for (x = 0; x < N; x++) */ } /* else if ((typregion == LABMIN) || (typregion == LABMAX)) */ LifoTermine(LIFO); *nlabels += 1; /* pour le niveau 0 */ return(1); } // lattribute()
/* ==================================== */ int32_t lnbvois( struct xvimage * image, int32_t connex) /* ==================================== */ { int32_t nvois, k; int32_t p, q; int32_t rs = rowsize(image); int32_t cs = colsize(image); int32_t ds = depth(image); int32_t ps = rs * cs; /* taille plan */ int32_t N = ps * ds; /* taille image */ uint8_t *F = UCHARDATA(image); /* l'image de depart */ switch (connex) { case 4: for (p = 0; p < N; p++) if (F[p]) { nvois = 0; /* compte le nombre de voisins non nuls */ for (k = 0; k < 8; k += 2) { q = voisin(p, k, rs, N); if ((q != -1) && (F[q])) nvois++; } F[p] = nvois; } break; case 8: for (p = 0; p < N; p++) if (F[p]) { nvois = 0; /* compte le nombre de voisins non nuls */ for (k = 0; k < 8; k += 1) { q = voisin(p, k, rs, N); if ((q != -1) && (F[q])) nvois++; } F[p] = nvois; } break; case 6: for (p = 0; p < N; p++) if (F[p]) { nvois = 0; /* compte le nombre de voisins non nuls */ for (k = 0; k <= 10; k += 2) { q = voisin6(p, k, rs, ps, N); if ((q != -1) && (F[q])) nvois++; } F[p] = nvois; } break; case 18: for (p = 0; p < N; p++) if (F[p]) { nvois = 0; /* compte le nombre de voisins non nuls */ for (k = 0; k < 18; k += 1) { q = voisin18(p, k, rs, ps, N); if ((q != -1) && (F[q])) nvois++; } F[p] = nvois; } break; case 26: for (p = 0; p < N; p++) if (F[p]) { nvois = 0; /* compte le nombre de voisins non nuls */ for (k = 0; k < 26; k += 1) { q = voisin26(p, k, rs, ps, N); if ((q != -1) && (F[q])) nvois++; } F[p] = nvois; } break; default: fprintf(stderr, "lnbvois: mauvaise connexite: %d\n", connex); return 0; } /* switch (connex) */ return 1; }
/* ==================================== */ int32_t ldilatbin_ldilatbin(struct xvimage *f, struct xvimage *m, int32_t xc, int32_t yc) /* m : masque representant l'element structurant */ /* xc, yc : coordonnees de l'origine de l'element structurant */ /* ==================================== */ { int32_t x, y, z, w; /* index muet de pixel */ register int32_t i, j; /* index muet */ register int32_t k, l; /* index muet */ int32_t rs = rowsize(f); /* taille ligne */ int32_t cs = colsize(f); /* taille colonne */ int32_t N = rs * cs; /* taille image */ int32_t rsm = rowsize(m); /* taille ligne masque */ int32_t csm = colsize(m); /* taille colonne masque */ int32_t Nm = rsm * csm; uint8_t *M = UCHARDATA(m); uint8_t *F = UCHARDATA(f); uint8_t *H; /* image de travail */ uint8_t sup; int32_t nptb; /* nombre de points de l'e.s. */ int32_t *tab_es_x; /* liste des coord. x des points de l'e.s. */ int32_t *tab_es_y; /* liste des coord. y des points de l'e.s. */ int32_t c; int32_t frontiere; if (depth(f) != 1) { fprintf(stderr, "ldilatbin_ldilatbin: cette version ne traite pas les images volumiques\n"); return 0; } if (!M[yc * rsm + xc]) /* l'element structurant N'est PAS reflexif */ { fprintf(stderr, "ldilatbin_ldilatbin: l'element structurant doit etre reflexif\n"); return 0; } H = (uint8_t *)calloc(1,N*sizeof(char)); if (H == NULL) { fprintf(stderr,"ldilatbin_ldilatbin() : malloc failed for H\n"); return(0); } memcpy(H, F, N); nptb = 0; for (i = 0; i < Nm; i += 1) if (M[i]) nptb += 1; tab_es_x = (int32_t *)calloc(1,nptb * sizeof(int32_t)); tab_es_y = (int32_t *)calloc(1,nptb * sizeof(int32_t)); if ((tab_es_x == NULL) || (tab_es_y == NULL)) { fprintf(stderr,"ldilatbin_ldilatbin() : malloc failed for tab_es\n"); return(0); } k = 0; for (j = 0; j < csm; j += 1) for (i = 0; i < rsm; i += 1) if (M[j * rsm + i]) { tab_es_x[k] = i; tab_es_y[k] = j; k += 1; } for (y = 0; y < cs; y++) for (x = 0; x < rs; x++) { /* verifie si (x,y) est un point de la frontiere de l'objet */ w = y * rs + x; if (H[w]) { frontiere = 0; for (k = 0; k < 8; k += 2) /* on cherche une frontiere 8-connexe */ { z = voisin(w, k, rs, N); if ((z != -1) && (!H[z])) { frontiere = 1; break; } } /* for k... */ if (!frontiere) F[w] = NDG_MAX; else { for (c = 0; c < nptb ; c += 1) { l = y + tab_es_y[c] - yc; k = x + tab_es_x[c] - xc; if ((l >= 0) && (l < cs) && (k >= 0) && (k < rs)) F[l * rs + k] = NDG_MAX; } } } } free(H); free(tab_es_x); free(tab_es_y); return 1; }
/* ==================================== */ int32_t lpropgeo( struct xvimage *img1, struct xvimage *mask, int32_t connex, int32_t function ) /* ==================================== */ #undef F_NAME #define F_NAME "lpropgeo" { int32_t k; int32_t w; int32_t x; int32_t y; uint8_t min; uint8_t max; uint8_t moy; uint8_t minb; uint8_t maxb; uint8_t moyb; uint8_t valcomp; int32_t valcomplong; int32_t mintrouve; int32_t maxtrouve; int32_t moytrouve; int32_t incr_vois; int32_t incr_voisb; int32_t sumndg; /* pour calculer la moyenne sur la composante */ int32_t surf; /* pour calculer la surface de la composante */ int32_t sumndgb; /* pour calculer la moyenne sur le bord */ int32_t sumndgc; /* pour calculer la variance sur le bord */ int32_t surfb; /* pour calculer la surface du bord */ double moybd; /* moyenne sur le bord */ double devb; /* deviation (ecart-type) sur le bord */ int32_t tmp; uint8_t *SOURCE = UCHARDATA(img1); uint8_t *MASK = UCHARDATA(mask); int32_t *MASKLONG = SLONGDATA(mask); int32_t rs = rowsize(img1); int32_t cs = colsize(img1); int32_t N = rs * cs; Lifo * LIFO; #ifdef PERF chrono chrono1; #endif if (depth(img1) != 1) { fprintf(stderr, "%s: cette version ne traite pas les images volumiques\n", F_NAME); return 0; } if (img1->data_storage_type != VFF_TYP_1_BYTE) return lpropgeolong(img1, mask, connex, function); if ((rowsize(mask) != rs) || (colsize(mask) != cs)) { fprintf(stderr, "%s: incompatible image sizes\n", F_NAME); return 0; } switch (connex) { case 4: incr_vois = 2; incr_voisb = 1; break; case 8: incr_vois = 1; incr_voisb = 2; break; default: fprintf(stderr, "%s: mauvaise connexite: %d\n", F_NAME, connex); return 0; } /* switch (connex) */ #ifdef PERF /* pour l'analyse de performances */ start_chrono(&chrono1); #endif IndicsInit(N); LIFO = CreeLifoVide(N); if (LIFO == NULL) { fprintf(stderr, "%s: CreeLifoVide failed\n", F_NAME); return(0); } if (mask->data_storage_type == VFF_TYP_1_BYTE) { for (x = 0; x < N; x++) /* recherche dans toute l'image */ { if (!MASK[x]) SOURCE[x] = NDG_MIN; if (MASK[x] && (!IsSet(x, TRAITE1))) /* on est dans une CC non traitee */ { valcomp = MASK[x]; LifoPush(LIFO, x); Set(x, TRAITE1); min = SOURCE[x]; max = SOURCE[x]; minb = NDG_MAX; maxb = NDG_MIN; sumndg = 0; surf = 0; sumndgb = 0; sumndgc = 0; surfb = 0; while (! LifoVide(LIFO)) /* parcourt la CC */ { w = LifoPop(LIFO); if ((SOURCE[w] < min)) min = SOURCE[w]; if ((SOURCE[w] > max)) max = SOURCE[w]; surf += 1; sumndg += SOURCE[w]; for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE1))) { LifoPush(LIFO, y); Set(y, TRAITE1); } } /* for k ... */ for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { y = voisin(w, k, rs, N); #ifdef VALEURTABOUE if ((y != -1) && (MASK[y] == 0) && (!IsSet(y, TRAITE1)) && (SOURCE[y] != VALEURTABOUE)) #else if ((y != -1) && (MASK[y] == 0) && (!IsSet(y, TRAITE1))) #endif { if ((SOURCE[y] < minb)) minb = SOURCE[y]; if ((SOURCE[y] > maxb)) maxb = SOURCE[y]; surfb += 1; sumndgb += SOURCE[y]; sumndgc += SOURCE[y] * SOURCE[y]; Set(y, TRAITE1); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ moy = (uint8_t)(sumndg/surf); if (surfb > 0) { moyb = (uint8_t)(sumndgb/surfb); moybd = ((double)sumndgb)/surfb; } else { moyb = 0; moybd = 0.0; } devb = sqrt(((double)sumndgc)/surfb - ((double)sumndgb * sumndgb)/(surfb * surfb)); #ifdef DEBUG printf("composante %d - surf=%d ; sumndg=%d ; surfb=%d ; sumndgb=%d ; max=%d\n", valcomplong, surf, sumndg, surfb, sumndgb, max); #endif LifoPush(LIFO, x); Set(x, TRAITE2); mintrouve = 0; maxtrouve = 0; moytrouve = 0; while (! LifoVide(LIFO)) /* RE-parcourt la CC */ { w = LifoPop(LIFO); switch (function) { case MIN1: if ((SOURCE[w] == min) && !mintrouve) { Set(w, MINIMUM); mintrouve = 1; } break; case MAX1: if ((SOURCE[w] == max) && !maxtrouve) { Set(w, MAXIMUM); maxtrouve = 1; } break; case MOY1: if ((SOURCE[w] == moy) && !moytrouve) { Set(w, MOYEN); moytrouve = 1; } break; case MIN: SOURCE[w] = min; break; case MAX: SOURCE[w] = max; break; case MOY: SOURCE[w] = moy; break; case MINB: SOURCE[w] = minb; break; case MAXB: SOURCE[w] = maxb; break; case MOYB: SOURCE[w] = moyb; break; case RANDB: tmp = (int32_t)Normal(moybd, devb); if (tmp > (int32_t)NDG_MAX) tmp = (int32_t)NDG_MAX; if (tmp < (int32_t)NDG_MIN) tmp = (int32_t)NDG_MIN; SOURCE[w] = (uint8_t)tmp; break; default: fprintf(stderr, "%s: bad argument\n", F_NAME); return(0); } for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { /* pour les demarquer (TRAITE1) */ y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == 0) && (IsSet(y, TRAITE1))) UnSet(y, TRAITE1); } /* for k ... */ for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE2))) { LifoPush(LIFO, y); Set(y, TRAITE2); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (MASK[x] && (!IsSet(x, TRAITE1))) */ } /* for (x = 0; x < N; x++) */ } /* if (mask->data_storage_type == VFF_TYP_1_BYTE) */ else if (mask->data_storage_type == VFF_TYP_4_BYTE) { for (x = 0; x < N; x++) /* recherche dans toute l'image */ { if (!MASKLONG[x]) SOURCE[x] = NDG_MIN; if (MASKLONG[x] && (!IsSet(x, TRAITE1))) /* on est dans une CC non traitee */ { valcomplong = MASKLONG[x]; LifoPush(LIFO, x); Set(x, TRAITE1); #ifdef DEBUG printf("Set TRAITE1 %d (%d,%d)\n",x, x%rs, x/rs); #endif min = SOURCE[x]; max = SOURCE[x]; sumndg = 0; surf = 0; sumndgb = 0; sumndgc = 0; surfb = 0; while (! LifoVide(LIFO)) /* parcourt la CC */ { w = LifoPop(LIFO); if ((SOURCE[w] < min)) min = SOURCE[w]; if ((SOURCE[w] > max)) max = SOURCE[w]; surf += 1; sumndg += SOURCE[w]; for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE1))) { LifoPush(LIFO, y); Set(y, TRAITE1); #ifdef DEBUG printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs); #endif } } /* for k ... */ for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { y = voisin(w, k, rs, N); #ifdef VALEURTABOUE if ((y != -1) && (MASKLONG[y] == 0) && (!IsSet(y, TRAITE1)) && (SOURCE[y] != VALEURTABOUE)) #else if ((y != -1) && (MASKLONG[y] == 0) && (!IsSet(y, TRAITE1))) #endif { if ((SOURCE[y] < minb)) minb = SOURCE[y]; if ((SOURCE[y] > maxb)) maxb = SOURCE[y]; surfb += 1; sumndgb += SOURCE[y]; sumndgc += SOURCE[y] * SOURCE[y]; Set(y, TRAITE1); #ifdef DEBUG printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs); #endif } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ moy = (uint8_t)(sumndg/surf); if (surfb > 0) { moyb = (uint8_t)(sumndgb/surfb); moybd = ((double)sumndgb)/surfb; } else { moyb = 0; moybd = 0.0; } devb = sqrt(((double)sumndgc)/surfb - ((double)sumndgb * sumndgb)/(surfb * surfb)); #ifdef DEBUG printf("composante %d - surf=%d ; sumndg=%d ; surfb=%d ; sumndgb=%d ; max=%d\n", valcomplong, surf, sumndg, surfb, sumndgb, max); #endif LifoPush(LIFO, x); Set(x, TRAITE2); mintrouve = 0; maxtrouve = 0; moytrouve = 0; while (! LifoVide(LIFO)) /* RE-parcourt la CC */ { w = LifoPop(LIFO); switch (function) { case MIN1: if ((SOURCE[w] == min) && !mintrouve) { Set(w, MINIMUM); mintrouve = 1; } break; case MAX1: if ((SOURCE[w] == max) && !maxtrouve) { Set(w, MAXIMUM); maxtrouve = 1; } break; case MOY1: if ((SOURCE[w] == moy) && !moytrouve) { Set(w, MOYEN); moytrouve = 1; } break; case MIN: SOURCE[w] = min; break; case MAX: SOURCE[w] = max; break; case MOY: SOURCE[w] = moy; break; case MINB: SOURCE[w] = minb; break; case MAXB: SOURCE[w] = maxb; break; case MOYB: SOURCE[w] = moyb; break; case RANDB: tmp = (int32_t)Normal(moybd, devb); if (tmp > (int32_t)NDG_MAX) tmp = (int32_t)NDG_MAX; if (tmp < (int32_t)NDG_MIN) tmp = (int32_t)NDG_MIN; SOURCE[w] = (uint8_t)tmp; break; default: fprintf(stderr, "%s: bad argument\n", F_NAME); return(0); } for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { /* pour les demarquer (TRAITE1) */ y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == 0) && (IsSet(y, TRAITE1))) { UnSet(y, TRAITE1); #ifdef DEBUG printf("UnSet TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs); #endif } } /* for k ... */ for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE2))) { LifoPush(LIFO, y); Set(y, TRAITE2); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (MASKLONG[x] && (!IsSet(x, TRAITE1))) */ } /* for (x = 0; x < N; x++) */ } /* if (mask->data_storage_type == VFF_TYP_4_BYTE) */ else { fprintf(stderr, "%s: bad storage type\n", F_NAME); return(0); } if (function == MIN1) for (x = 0; x < N; x++) if (IsSet(x, MINIMUM)) SOURCE[x] = NDG_MAX; else SOURCE[x] = NDG_MIN; if (function == MAX1) for (x = 0; x < N; x++) if (IsSet(x, MAXIMUM)) SOURCE[x] = NDG_MAX; else SOURCE[x] = NDG_MIN; if (function == MOY1) for (x = 0; x < N; x++) if (IsSet(x, MOYEN)) SOURCE[x] = NDG_MAX; else SOURCE[x] = NDG_MIN; LifoTermine(LIFO); IndicsTermine(); return(1); } /* lpropgeo() */
/* ==================================== */ int32_t lpropgeolong( struct xvimage *img1, struct xvimage *mask, int32_t connex, int32_t function ) /* ==================================== */ #undef F_NAME #define F_NAME "lpropgeolong" { int32_t k; int32_t w; int32_t x; int32_t y; int32_t min; int32_t max; int32_t moy; uint8_t valcomp; int32_t valcomplong; int32_t mintrouve; int32_t maxtrouve; int32_t moytrouve; int32_t incr_vois; int32_t incr_voisb; int32_t sumndg; /* pour calculer la moyenne sur la composante */ int32_t surf; /* pour calculer la surface de la composante */ int32_t *SOURCE = SLONGDATA(img1); uint8_t *MASK = UCHARDATA(mask); int32_t *MASKLONG = SLONGDATA(mask); int32_t rs = rowsize(img1); int32_t cs = colsize(img1); int32_t N = rs * cs; Lifo * LIFO; #ifdef PERF chrono chrono1; #endif if (depth(img1) != 1) { fprintf(stderr, "%s: cette version ne traite pas les images volumiques\n", F_NAME); return 0; } if (img1->data_storage_type != VFF_TYP_4_BYTE) { fprintf(stderr, "%s: datatype for arg1 must be int32_t\n", F_NAME); return 0; } if ((rowsize(mask) != rs) || (colsize(mask) != cs)) { fprintf(stderr, "%s: incompatible image sizes\n", F_NAME); return 0; } switch (connex) { case 4: incr_vois = 2; incr_voisb = 1; break; case 8: incr_vois = 1; incr_voisb = 2; break; default: fprintf(stderr, "%s: mauvaise connexite: %d\n", F_NAME, connex); return 0; } /* switch (connex) */ #ifdef PERF /* pour l'analyse de performances */ start_chrono(&chrono1); #endif IndicsInit(N); LIFO = CreeLifoVide(N); if (LIFO == NULL) { fprintf(stderr, "%s: CreeLifoVide failed\n", F_NAME); return(0); } if (mask->data_storage_type == VFF_TYP_1_BYTE) { for (x = 0; x < N; x++) /* recherche dans toute l'image */ { if (!MASK[x]) SOURCE[x] = 0; if (MASK[x] && (!IsSet(x, TRAITE1))) /* on est dans une CC non traitee */ { valcomp = MASK[x]; LifoPush(LIFO, x); Set(x, TRAITE1); min = SOURCE[x]; max = SOURCE[x]; surf = 0; while (! LifoVide(LIFO)) /* parcourt la CC */ { w = LifoPop(LIFO); if ((SOURCE[w] < min)) min = SOURCE[w]; if ((SOURCE[w] > max)) max = SOURCE[w]; surf += 1; sumndg += SOURCE[w]; for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE1))) { LifoPush(LIFO, y); Set(y, TRAITE1); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ moy = (int32_t)(sumndg/surf); LifoPush(LIFO, x); Set(x, TRAITE2); mintrouve = 0; maxtrouve = 0; moytrouve = 0; while (! LifoVide(LIFO)) /* RE-parcourt la CC */ { w = LifoPop(LIFO); switch (function) { case MIN: SOURCE[w] = min; break; case MAX: SOURCE[w] = max; break; case MOY: SOURCE[w] = moy; break; default: fprintf(stderr, "%s: bad argument\n", F_NAME); return(0); } for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { /* pour les demarquer (TRAITE1) */ y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == 0) && (IsSet(y, TRAITE1))) UnSet(y, TRAITE1); } /* for k ... */ for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE2))) { LifoPush(LIFO, y); Set(y, TRAITE2); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (MASK[x] && (!IsSet(x, TRAITE1))) */ } /* for (x = 0; x < N; x++) */ } /* if (mask->data_storage_type == VFF_TYP_1_BYTE) */ else if (mask->data_storage_type == VFF_TYP_4_BYTE) { for (x = 0; x < N; x++) /* recherche dans toute l'image */ { if (!MASKLONG[x]) SOURCE[x] = NDG_MIN; if (MASKLONG[x] && (!IsSet(x, TRAITE1))) /* on est dans une CC non traitee */ { valcomplong = MASKLONG[x]; LifoPush(LIFO, x); Set(x, TRAITE1); #ifdef DEBUG printf("Set TRAITE1 %d (%d,%d)\n",x, x%rs, x/rs); #endif min = SOURCE[x]; max = SOURCE[x]; sumndg = 0; surf = 0; while (! LifoVide(LIFO)) /* parcourt la CC */ { w = LifoPop(LIFO); if ((SOURCE[w] < min)) min = SOURCE[w]; if ((SOURCE[w] > max)) max = SOURCE[w]; surf += 1; sumndg += SOURCE[w]; for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE1))) { LifoPush(LIFO, y); Set(y, TRAITE1); #ifdef DEBUG printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs); #endif } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ moy = (int32_t)(sumndg/surf); LifoPush(LIFO, x); Set(x, TRAITE2); mintrouve = 0; maxtrouve = 0; moytrouve = 0; while (! LifoVide(LIFO)) /* RE-parcourt la CC */ { w = LifoPop(LIFO); switch (function) { case MIN: SOURCE[w] = min; break; case MAX: SOURCE[w] = max; break; case MOY: SOURCE[w] = moy; break; default: fprintf(stderr, "%s: bad argument\n", F_NAME); return(0); } for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */ { /* pour les demarquer (TRAITE1) */ y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == 0) && (IsSet(y, TRAITE1))) { UnSet(y, TRAITE1); #ifdef DEBUG printf("UnSet TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs); #endif } } /* for k ... */ for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */ { y = voisin(w, k, rs, N); if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE2))) { LifoPush(LIFO, y); Set(y, TRAITE2); } } /* for k ... */ } /* while (! LifoVide(LIFO)) */ } /* if (MASKLONG[x] && (!IsSet(x, TRAITE1))) */ } /* for (x = 0; x < N; x++) */ } /* if (mask->data_storage_type == VFF_TYP_4_BYTE) */ else { fprintf(stderr, "%s: bad storage type\n", F_NAME); return(0); } LifoTermine(LIFO); IndicsTermine(); return(1); } /* lpropgeolong() */
/* mBorderWshed2d was previously called flowLPE2d*/ struct xvimage *mBorderWshed2drapide(struct xvimage *ga) #undef F_NAME #define F_NAME "mBorderWshed2drapide" { int32_t i,j,k,x,y,z,w,u, nlabels, label; struct xvimage *res; // uint32_t *Eminima; int32_t *Vminima; int32_t rs = rowsize(ga); /* taille ligne */ int32_t cs = colsize(ga); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *F = UCHARDATA(ga); /* l'image de depart */ uint8_t *VF; /* fonction indicatrice sur les sommets */ Lifo *L; /******************INITIALISATION*********************/ /* if(!jclabelextrema(ga, &Eminima, 1, &nlabels)) { fprintf(stderr,"%s erreur de label extrema \n",F_NAME); exit(1); }*/ if( (res = allocimage(NULL, rs, cs, 1, VFF_TYP_4_BYTE)) == NULL) { fprintf(stderr,"%s erreur de allocimage \n", F_NAME); exit(1); } Vminima = SLONGDATA(res); if( (VF = malloc(sizeof(uint8_t) * N)) == NULL) { fprintf(stderr,"%s ne peut allouer VF \n", F_NAME); exit(1); } /* Valuation des sommets */ for(i = 0; i < N; i++) { VF[i] = 255; Vminima[i] = -1; for(k = 0; k < 4; k++) if( (u = incidente(i, k, rs, N)) != -1) if(F[u] < VF[i]) VF[i] = F[u]; } /* Initialisation de la FIFO */ L = CreeLifoVide(2*N); /* nbre maximum d'arete ds un ga 4 connexe sans regarder les bords */ /* Calcul des sommets qui sont dans des minima de F */ nlabels = 0; for(x = 0; x < N; x++){ if(Vminima[x] == -1){ /* On trouve un sommet non encore etiquete */ nlabels ++; Vminima[x] = nlabels; LifoPush(L,x); while(!LifoVide(L)) { w = LifoPop(L); label = Vminima[w]; for(k = 0; k < 4; k++) if( (u = incidente(w, k, rs, N)) != -1){ if(F[u] == VF[w]){ switch(k){ case 0: y = w+1; break; /* EST */ case 1: y = w-rs; break; /* NORD */ case 2: y = w-1; break; /* OUEST */ case 3: y = w+rs; break; /* SUD */ } if( (label > 0) && (VF[y] < VF[w]) ){ label = 0; nlabels --; Vminima[w] = label; LifoPush(L,w); } else if(VF[y] == VF[w]){ if( ( (label > 0) && (Vminima[y] == -1) ) || ( (label == 0) && (Vminima[y] != 0)) ){ Vminima[y] = label; LifoPush(L,y); } } } } } } } // printf("nlabels %d \n",nlabels); /* Les aretes adjacentes a un minimum sont inserees dans L */ /* on explore d'abord les aretes horizontales */ for(j = 0; j < cs; j++) for(i = 0; i < rs -1; i++){ u = j * rs + i; x = Sommetx(u,N,rs); y = Sommety(u,N,rs); if( (mcmin(Vminima[x], Vminima[y]) == 0) && /* un des deux sommets non ds un minima */ (mcmax(Vminima[x], Vminima[y]) > 0) ) /* et l'autre dans un minima */ LifoPush(L,u); } /* puis les aretes verticales */ for(j = 0; j < cs -1; j++) for(i = 0; i < rs; i++) { u = N + j * rs + i; x = Sommetx(u,N,rs); y = Sommety(u,N,rs); if( (mcmin(Vminima[x], Vminima[y]) == 0) && /* un des deux sommets non ds un minima */ (mcmax(Vminima[x], Vminima[y]) > 0) ) /* et l'autre dans un minima */ LifoPush(L,u); } /*************BOUCLE PRINCIPALE*****************/ while(!LifoVide(L)) { u = LifoPop(L); x = Sommetx(u, N, rs); y = Sommety(u, N, rs); if (VF[x] > VF[y]) {z = y; y = x; x = z;} if((VF[x] < F[u]) && (VF[y] == F[u])){ /* u est une arete de bord */ F[u] = VF[x]; VF[y] = F[u]; // Eminima[u] = Vminima[x]; Vminima[y] = Vminima[x]; for(k = 0; k < 8; k +=2){ if( (z = voisin(y, k, rs, N)) != -1) if( (Vminima[z] == 0)) LifoPush(L, Arete(y,z,rs,N)); } /* for(k = 0 .. */ } /* if( (VF[x] < ... */ }/* while(!LifoVide... */ // free(Eminima); free(VF); return res; }// mBorderWshed2drapide(...)
/* mBorderWshed2d was previously called flowLPE2d*/ struct xvimage *mBorderWshed2d(struct xvimage *ga) #undef F_NAME #define F_NAME "mBorderWshed2d" { int32_t i,j,k,x,y,z,u, nlabels; struct xvimage *res; uint32_t *Eminima; uint32_t *Vminima; int32_t rs = rowsize(ga); /* taille ligne */ int32_t cs = colsize(ga); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *F = UCHARDATA(ga); /* l'image de depart */ uint8_t *VF; /* fonction indicatrice sur les sommets */ Lifo *L; /******************INITIALISATION*********************/ if(!jclabelextrema(ga, &Eminima, 1, &nlabels)) { fprintf(stderr,"%s erreur de label extrema \n",F_NAME); exit(1); } //printf("nlabels %d \n", nlabels); if( (res = allocimage(NULL, rs, cs, 1, VFF_TYP_4_BYTE)) == NULL) { fprintf(stderr,"%s erreur de allocimage \n", F_NAME); exit(1); } Vminima = SLONGDATA(res); if( (VF = malloc(sizeof(uint8_t) * N)) == NULL) { fprintf(stderr,"%s ne peut allouer VF \n", F_NAME); exit(1); } /* Valuation des sommets et calcul de V_M a partir de E_M */ for(i = 0; i < N; i++) { VF[i] = 255; Vminima[i] = 0; for(k = 0; k < 4; k++) if( (u = incidente(i, k, rs, N)) != -1) { if(F[u] < VF[i]) VF[i] = F[u]; if(Eminima[u] > 0) Vminima[i] = Eminima[u]; } } /* Initialisation de la FIFO */ L = CreeLifoVide(2*N); /* nbre maximum d'arete ds un ga 4 connexe sans regarder les bords */ /* Les aretes adjacentes a un minimum sont inserees dans L */ /* on explore d'abord les aretes horizontales */ for(j = 0; j < cs; j++) for(i = 0; i < rs -1; i++){ u = j * rs + i; x = Sommetx(u,N,rs); y = Sommety(u,N,rs); if( (mcmin(Vminima[x], Vminima[y]) == 0) && /* un des deux sommets non ds un minima */ (mcmax(Vminima[x], Vminima[y]) > 0) ) /* et l'autre dans un minima */ LifoPush(L,u); } /* puis les aretes verticales */ for(j = 0; j < cs -1; j++) for(i = 0; i < rs; i++) { u = N + j * rs + i; x = Sommetx(u,N,rs); y = Sommety(u,N,rs); if( (mcmin(Vminima[x], Vminima[y]) == 0) && /* un des deux sommets non ds un minima */ (mcmax(Vminima[x], Vminima[y]) > 0) ) /* et l'autre dans un minima */ LifoPush(L,u); } /*************BOUCLE PRINCIPALE*****************/ while(!LifoVide(L)) { u = LifoPop(L); x = Sommetx(u, N, rs); y = Sommety(u, N, rs); if (VF[x] > VF[y]) {z = y; y = x; x = z;} if((VF[x] < F[u]) && (VF[y] == F[u])){ /* u est une arete de bord */ F[u] = VF[x]; VF[y] = F[u]; Eminima[u] = Vminima[x]; Vminima[y] = Vminima[x]; for(k = 0; k < 8; k +=2){ if( (z = voisin(y, k, rs, N)) != -1) if( (Vminima[z] == 0)) LifoPush(L, Arete(y,z,rs,N)); } /* for(k = 0 .. */ } /* if( (VF[x] < ... */ }/* while(!LifoVide... */ free(Eminima); free(VF); return res; }
/* ==================================== */ void saturation(int32_t rs, int32_t cs, int32_t N, uint8_t *F, Fahp * FAHP) /* ==================================== */ { int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t k; /* index muet */ int32_t t4mm, t4m, t8p, t8pp; int32_t level; #ifdef DEBUG uint8_t oldFx; #endif while (!FahpVide(FAHP)) { level = FahpNiveau(FAHP); x = FahpPop(FAHP); UnSet(x, EN_FAHP); UnSet(x, EN_FAHP2); if ((F[x] > 0) && (level <= NDG_MAX)) { nbtopoh(F, x, 1, rs, N, &t4mm, &t4m, &t8p, &t8pp); if (t4mm == 1) { if (pdestr4(F, x, rs, N)) { #ifdef DEBUG oldFx = F[x]; #endif if (!ridge(F, x, rs, N)) F[x] = 0; else F[x] = alpha8m(F, x, rs, N); #ifdef DEBUG printf("point %d (%d %d), val = %d --> %d\n", x, x%rs, x/rs, oldFx, F[x]); #endif for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (F[y] > 0) && (! IsSet(y, EN_FAHP))) { FahpPush(FAHP, y, F[y]); Set(y, EN_FAHP); } /* if y */ } /* for k */ } /* if (pdestr4(F, x, rs, N)) */ } /* if (t4mm == 1) */ else /* t4mm != 1 */ { if (pdestr4(F, x, rs, N)) /* point divergent */ { F[x] = alpha8m(F, x, rs, N); for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (F[y] > 0) && (! IsSet(y, EN_FAHP))) { FahpPush(FAHP, y, F[y]); Set(y, EN_FAHP); } /* if y */ } /* for k */ } /* if (pdestr4(F, x, rs, N)) */ } /* else if (t4mm == 1) */ } /* ((F[x] > 0) && (F[x] <= NDG_MAX)) */ } /* while (! (FifoVide(FAHP) ...)) */ } /* saturation() */
/* ==================================== */ static void Watershed(struct xvimage *image, int32_t connex, Fahs * FAHS, int32_t *CM, ctree * CT) /* ==================================== */ // // inondation a partir des voisins des maxima, suivant les ndg decroissants // nouvelle (08/03) caracterisation des points destructibles // nouvelle (09/03) construction de l'arbre des composantes // Nouvelle (05/05) lca en temps constant + qq optimisation de l'article JMIV (najmanl) #undef F_NAME #define F_NAME "Watershed" { uint8_t *F = UCHARDATA(image); int32_t rs = rowsize(image); int32_t ps = rs * colsize(image); int32_t N = ps * depth(image); int32_t i, k, x, y; int32_t c; /* une composante */ int32_t tabcomp[26]; /* liste de composantes */ int32_t nbelev; /* nombre d'elevations effectuees */ int32_t lcalevel; /* niveau du lca */ int32_t incr_vois; #ifndef LCASLOW int32_t logn, nbRepresent; int32_t *Euler, *Depth, *Represent, *Number, **Minim; #endif // INITIALISATIONS FahsFlush(FAHS); // Re-initialise la FAHS #ifndef LCASLOW Euler = (int32_t *)calloc(2*CT->nbnodes-1, sizeof(int32_t)); Represent = (int32_t *)calloc(CT->nbnodes, sizeof(int32_t)); Depth = (int32_t *)calloc(CT->nbnodes, sizeof(int32_t)); Number = (int32_t *)calloc(CT->nbnodes, sizeof(int32_t)); if ((Euler == NULL) || (Represent == NULL) || (Depth == NULL) || (Number == NULL)) { fprintf(stderr, "%s : malloc failed\n", F_NAME); return; } Minim = LCApreprocess(CT, Euler, Depth, Represent, Number, &nbRepresent, &logn); #ifdef _DEBUG_ printf("Comparison Slow/Fast lca\n"); { int32_t i,j, anc; int32_t nbErrors = 0; for (i=0; i<CT->nbnodes; i++) for (j=0; j<CT->nbnodes; j++) { if ((CT->tabnodes[i].nbsons > -1) && (CT->tabnodes[j].nbsons > -1)) { anc = Represent[LowComAncFast(i,j,Euler,Number,Depth,Minim)]; if (anc != LowComAncSlow(CT,i,j)) { nbErrors++; printf("Error node lca(%d, %d) = %d ou %d ?\n", i, j, anc, LowComAncSlow(CT,i,j)); } else { printf("Ok node lca(%d, %d) = %d\n", i, j, anc); } } } printf("Nb errors = %d\n",nbErrors); } fflush(stdout); #endif // _DEBUG_ #endif //ifndef LCASLOW switch (connex) { case 4: incr_vois = 2; break; case 8: incr_vois = 1; break; } /* switch (connex) */ // etiquetage des c-maxima (doit pouvoir se faire au vol lors de la construction de l'arbre) for (i = 0; i < N; i++) { c = CM[i]; if (CT->tabnodes[c].nbsons == 0) { Set(i,MASSIF); } } // for (i = 0; i < N; i++) // empile les points for (i = 0; i < N; i++) { #ifdef OLDVERSION // empile tous les points Set(i,EN_FAHS); FahsPush(FAHS, i, NDG_MAX - F[i]); #else // empile les points voisins d'un minima char flag=0; switch (connex) { case 4: case 8: for (k = 0; (k < 8) && (flag == 0); k += incr_vois) { y = voisin(i, k, rs, N); if ((y != -1) && (IsSet(y,MASSIF))) { flag = 1; } } break; case 6: for (k = 0; k <= 10; k += 2) { y = voisin6(i, k, rs, ps, N); if ((y != -1) && (IsSet(y,MASSIF))) { flag = 1; } } break; case 18: for (k = 0; k < 18; k += 1) { y = voisin18(i, k, rs, ps, N); if ((y != -1) && (IsSet(y,MASSIF))) { flag = 1; } } break; case 26: for (k = 0; k < 26; k += 1) { y = voisin26(i, k, rs, ps, N); if ((y != -1) && (IsSet(y,MASSIF))) { flag = 1; } } break; } /* switch (connex) */ if (flag) { Set(i,EN_FAHS); FahsPush(FAHS, i, NDG_MAX - F[i]); } #endif } // for (i = 0; i < N; i++) // BOUCLE PRINCIPALE nbelev = 0; while (!FahsVide(FAHS)) { x = FahsPop(FAHS); UnSet(x,EN_FAHS); W_Constructible(x, F, rs, ps, N, connex, CT, CM, tabcomp, &c, &lcalevel #ifndef LCASLOW , Euler, Represent, Depth, Number, Minim #endif ); if (c != -1) { nbelev++; F[x] = lcalevel; // eleve le niveau du point x CM[x] = c; // maj pointeur image -> composantes Set(x,MODIFIE); if (CT->tabnodes[c].nbsons == 0) // feuille { Set(x,MASSIF); } // if feuille else if (CT->tabnodes[c].nbsons > 1) // noeud { } #ifdef PARANO else printf("%s : ERREUR COMPOSANTE BRANCHE!!!\n", F_NAME); #endif // empile les c-voisins de x non marques MASSIF ni EN_FAHS switch (connex) { case 4: case 8: for (k = 0; k < 8; k += incr_vois) { y = voisin(x, k, rs, N); if ((y != -1) && (!IsSet(y,MASSIF)) && (!IsSet(y,EN_FAHS))) { Set(y,EN_FAHS); FahsPush(FAHS, y, NDG_MAX - F[y]); } } break; case 6: for (k = 0; k <= 10; k += 2) { y = voisin6(x, k, rs, ps, N); if ((y != -1) && (!IsSet(y,MASSIF)) && (!IsSet(y,EN_FAHS))) { Set(y,EN_FAHS); FahsPush(FAHS, y, NDG_MAX - F[y]); } } break; case 18: for (k = 0; k < 18; k += 1) { y = voisin18(x, k, rs, ps, N); if ((y != -1) && (!IsSet(y,MASSIF)) && (!IsSet(y,EN_FAHS))) { Set(y,EN_FAHS); FahsPush(FAHS, y, NDG_MAX - F[y]); } } break; case 26: for (k = 0; k < 26; k += 1) { y = voisin26(x, k, rs, ps, N); if ((y != -1) && (!IsSet(y,MASSIF)) && (!IsSet(y,EN_FAHS))) { Set(y,EN_FAHS); FahsPush(FAHS, y, NDG_MAX - F[y]); } } break; } /* switch (connex) */ } // if (c != -1)} } // while (!FahsVide(FAHS)) #ifdef VERBOSE printf("Nombre d'elevations %d\n", nbelev); #endif #ifndef LCASLOW free(Euler); free(Represent); free(Depth); free(Number); free(Minim[0]); free(Minim); #endif //LCASLOW } // Watershed()
/* ==================================== */ int32_t lremspnoise( struct xvimage *image, int32_t g, int32_t k) /* g : nombre de niveaux d'ecart */ /* k : nombre de voisins consideres */ /* ==================================== */ { int32_t i, v, n, j, m, nv; uint8_t *pt; int32_t rs = image->row_size; int32_t cs = image->col_size; int32_t N = rs * cs; uint8_t *imagetmp; if (depth(image) != 1) { fprintf(stderr, "lhtkern: cette version ne traite pas les images volumiques\n"); exit(0); } pt = UCHARDATA(image); imagetmp = (uint8_t *)calloc(1,N*sizeof(char)); if (imagetmp == NULL) { printf("lremspnoise() : malloc failed\n"); return(0); } /* ---------------------------------------------------------- */ /* calcul du resultat */ /* ---------------------------------------------------------- */ for (i = 0; i < N; i++) { /* detection du bruit : compte le nombre de voisins qui different de plus de g niveaux */ n = 0; nv = 0; m = 0; for (v = 0; v < 8; v++) /* 8-voisins */ if ((j = voisin(i, v, rs, N)) != -1) { if (mcabs(((int32_t)pt[i] - (int32_t)pt[j]) >= g)) n++; nv++; /* compte les voisins */ m += pt[j]; /* pour le calcul de la moyenne */ } if (n >= k) { /* moyennage : remplace la valeur du point par la moyenne de ses 8 voisins */ imagetmp[i] = (uint8_t)(m / nv); } else imagetmp[i] = pt[i]; } for (i = 0; i < N; i++) pt[i] = imagetmp[i]; free(imagetmp); return 1; }
/* waterfall vu comme une succession de LPE sur les aretes*/ int32_t main_cascade(struct xvimage *image, struct xvimage *ga, int32_t param) /* 4 connexite uniquement Construit le graphe d'arete de saillance pour les cascades*/ /* ==================================== */ #undef F_NAME #define F_NAME "main_cascade" { int32_t rs = rowsize(image); /* taille ligne */ int32_t cs = colsize(image); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *F = UCHARDATA(image); /* l'image de depart */ uint8_t *G = UCHARDATA(ga); /* le GA de sortie */ int32_t *Label1, *Label2; struct GrapheValue *g1, *g2; int32_t i,k,y; int32_t nbregions; if ( (Label1 = malloc(sizeof(int32_t) * N)) == NULL){ fprintf(stderr, "%s: Erreur de malloc\n", F_NAME); exit(0); } if ( (Label2 = malloc(sizeof(int32_t) * N)) == NULL){ fprintf(stderr, "%s: Erreur de malloc\n", F_NAME); exit(0); } for(i = 0; i < 2*N; i++) G[i] = 0; //printf("Initialisation du Ga out done \n"); g1 = initGrapheValue(N, 4*N - 2*rs - 2*cs); /* nbre d'arete du graphe 4-connexe symetrique correspondant */ //printf("Initialisation du graphe utile \n"); for(i = 0; i < N; i++){ Label1[i] = i; for (k = 0; k < 4; k += 2){ if((y = voisin(i, k, rs, N)) != -1) switch(param){ case 0: updateArcValue(g1,i, y, (uint8_t)mcmax(F[i],F[y])); break; case 1: updateArcValue(g1,i, y, (uint8_t)mcabs((int32_t)F[i] - (int32_t)F[y])); break; default: fprintf(stderr,"%s: Mauvais parametre \n", F_NAME); exit(0); } } } //printf("Graphe utile calcule \n"); nbregions = (int32_t)lpeGrapheAreteValuee(g1, Label2); //printf("LPE du graphe utile done et nb regions %d\n",nbregions); fflush(stdout); while(nbregions > 1){ //printf("Un etage de la hierarchie \n"); g2 = initGrapheValue((int32_t)nbregions, (int32_t)mcmin(nbregions*(nbregions-1), (int32_t)(4*N - 2*rs - 2*cs)) ); //printf("2eme graphe initialise \n"); for(i = 0; i < N; i++){ for(k=0; k < 2; k++) if((y = voisin(i, 2*k, rs, N)) != -1){ if(Label2[Label1[i]] != Label2[Label1[y]]){ // Mise a jour de la carte de saillance du waterfall G[incidente(i,k,rs,N)] ++; switch(param){ case 0: updateArcValue(g2,Label2[Label1[i]], Label2[Label1[y]], mcmax(F[i],F[y])); break; case 1: updateArcValue(g2,Label2[Label1[i]], Label2[Label1[y]], (uint8_t)mcabs((int32_t)F[i] - (int32_t)F[y])); break; default: fprintf(stderr,"%s: Mauvais parametre \n", F_NAME); exit(0); } } } } for(i = 0; i < N; i++){ Label1[i] = Label2[Label1[i]]; } termineGrapheValue(g1); g1 = g2; nbregions = (int32_t)lpeGrapheAreteValuee(g1, Label2); } termineGrapheValue(g1); free(Label1); free(Label2); return 1; }
/* ==================================== */ int32_t lsquelsmoothval(struct xvimage *image, // entree/sortie: image originale / squelette struct xvimage *dx, // entree/sortie: distance / distance topologique struct xvimage *ni, // entree/sortie: niveaux - image 1D struct xvimage *gr, // entree: gradient int32_t connex, int32_t val_inhibit, int32_t rayon) /* ==================================== */ #undef F_NAME #define F_NAME "lsquelsmoothval" { int32_t k; int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t rs = rowsize(image); /* taille ligne */ int32_t cs = colsize(image); /* taille colonne */ int32_t N = rs * cs; /* taille image */ struct xvimage *dt; /* pour le calcul de la "distance topologique" */ uint32_t *DT; /* fonction "distance topologique" */ uint8_t *IM = UCHARDATA(image); /* l'image de depart */ uint32_t *DX = ULONGDATA(dx); /* fonction distance au complementaire de IM */ uint8_t *NI = UCHARDATA(ni); /* fonction niveau (1D) - taille N * 1 */ uint8_t *GR = UCHARDATA(gr); /* fonction gradient */ uint32_t d; Rbt * RBT; int32_t taillemaxrbt; Liste * cx; // pour le cercle de centre x Liste * cy; // pour le cercle de centre y uint32_t dmax; IndicsInit(N); if ((rowsize(dx) != rs) || (colsize(dx) != cs) || (depth(dx) != 1)) { fprintf(stderr, "%s() : bad size for dx\n", F_NAME); return(0); } if (datatype(dx) != VFF_TYP_4_BYTE) { fprintf(stderr, "%s() : datatype(dx) must be uint32_t\n", F_NAME); return(0); } if ((rowsize(ni) != N) || (colsize(ni) != 1) || (depth(ni) != 1)) { fprintf(stderr, "%s() : bad size for ni\n", F_NAME); return(0); } dt = copyimage(dx); DT = ULONGDATA(dt); taillemaxrbt = 2 * rs + 2 * cs ; /* cette taille est indicative, le RBT est realloue en cas de depassement */ RBT = mcrbt_CreeRbtVide(taillemaxrbt); if (RBT == NULL) { fprintf(stderr, "%s() : mcrbt_CreeRbtVide failed\n", F_NAME); return(0); } for (dmax = 0, x = 0; x < N; x++) if (DX[x] > dmax) dmax = DX[x]; // INITIALISATION DT for (x = 0; x < N; x++) if (IM[x]) DT[x] = INFINI; else DT[x] = 0; // INITIALISATION DU RBT for (x = 0; x < N; x++) if (IM[x] && (DX[x] != val_inhibit) && bordext8(IM, x, rs, N)) { mcrbt_RbtInsert(&RBT, DX[x], x); Set(x, EN_RBT); } // if, for cx = CreeListeVide(2*rs + 2*cs); cy = CreeListeVide(2*rs + 2*cs); d = 1; if (connex == 4) { while (!mcrbt_RbtVide(RBT)) { x = RbtPopMin(RBT); UnSet(x, EN_RBT); #ifdef DEBUG printf("pop x = %d,%d, im = %d, dx = %ld\n", x%rs, x/rs, IM[x], DX[x]); #endif if (simple4(IM, x, rs, N)) { if (smooth(image, x, rayon, cx, cy)) { NI[d] = GR[x]; DT[x] = d; IM[x] = 0; d++; for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (IM[y]) && (DX[y] != val_inhibit) && (! IsSet(y, EN_RBT))) { mcrbt_RbtInsert(&RBT, DX[y], y); Set(y, EN_RBT); } /* if y */ } /* for k */ } else { DX[x] += INCR_PRIO; if (DX[x] > dmax) break; mcrbt_RbtInsert(&RBT, DX[x], x); Set(x, EN_RBT); } } // if (simple4(IM, x, rs, N)) } /* while (!mcrbt_RbtVide(RBT)) */ } /* if (connex == 4) */ else if (connex == 8) { printf("connex 8 NYI\n"); } /* if (connex == 8) */ // RECUPERATION DU RESULTAT d = 0; // valeur pour l'infini: plus grande valeur finie + 1 for (x = 0; x < N; x++) if ((DT[x] > d) && (DT[x] < INFINI)) d = DT[x]; d += 1; for (x = 0; x < N; x++) if (DT[x] == INFINI) DX[x] = d; else DX[x] = DT[x]; /* ================================================ */ /* UN PEU DE MENAGE */ /* ================================================ */ IndicsTermine(); mcrbt_RbtTermine(RBT); freeimage(dt); ListeTermine(cx); ListeTermine(cy); return(1); } /* lsquelsmoothval() */
/* ==================================== */ int32_t lgeodilat( struct xvimage *g, struct xvimage *f, int32_t connex, int32_t niter) /* dilatation geodesique de g sous f */ /* g : image marqueur */ /* f : image masque */ /* connex : 4 ou 8 */ /* niter : nombre d'iterations (ou -1 pour saturation) */ /* resultat dans g */ /* ==================================== */ #undef F_NAME #define F_NAME "lgeodilat" { int32_t nbchang, iter; int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t k; /* index muet */ int32_t rs = rowsize(g); /* taille ligne */ int32_t cs = colsize(g); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *G = UCHARDATA(g); /* l'image marqueur */ uint8_t *F = UCHARDATA(f); /* l'image masque */ uint8_t *H; /* image de travail */ uint8_t *temp; uint8_t sup; Fifo * FIFO[2]; int32_t incr_vois; switch (connex) { case 4: incr_vois = 2; break; case 8: incr_vois = 1; break; } /* switch (connex) */ if ((rowsize(f) != rs) || (colsize(f) != cs)) { fprintf(stderr, "%s: incompatible sizes\n", F_NAME); return 0; } if (depth(f) != 1) { fprintf(stderr, "%s: only works for 2d images\n", F_NAME); return 0; } FIFO[0] = CreeFifoVide(N); FIFO[1] = CreeFifoVide(N); if ((FIFO[0] == NULL) || (FIFO[1] == NULL)) { fprintf(stderr,"%s : CreeFifoVide failed\n", F_NAME); return(0); } IndicsInit(N); for (x = 0; x < N; x++) /* mise en fifo initiale de tous les points */ { FifoPush(FIFO[1], x); Set(x, 1); } H = (uint8_t *)calloc(1,N*sizeof(char)); if (H == NULL) { fprintf(stderr,"%s : malloc failed for H\n", F_NAME); return(0); } for (x = 0; x < N; x++) /* force G à être <= F */ if (G[x] > F[x]) G[x] = F[x]; iter = 0; do { iter += 1; nbchang = 0; while (! FifoVide(FIFO[iter % 2])) { x = FifoPop(FIFO[iter % 2]); UnSet(x, iter % 2); sup = G[x]; for (k = 0; k < 8; k += incr_vois) { y = voisin(x, k, rs, N); if ((y != -1) && (G[y] > sup)) sup = G[y]; } /* for k */ sup = mcmin(sup, F[x]); if (G[x] != sup) /* changement: on enregistre x ainsi que ses voisins */ { nbchang += 1; if (! IsSet(x, (iter + 1) % 2)) { FifoPush(FIFO[(iter + 1) % 2], x); Set(x, (iter + 1) % 2); } for (k = 0; k < 8; k += 1) { y = voisin(x, k, rs, N); if ((y != -1) && (! IsSet(y, (iter + 1) % 2))) { FifoPush(FIFO[(iter + 1) % 2], y); Set(y, (iter + 1) % 2); } } /* for k */ } H[x] = sup; } /* while ! FifoVide */ /* echange les roles de G et H */ temp = G; G = H; H = temp; #ifdef VERBOSE printf("iteration %d, nbchang %d\n", iter, nbchang); #endif } while (((niter == -1) || (iter < niter)) && (nbchang != 0)); /* remet le resultat dans g si necessaire */ if (G != UCHARDATA(g)) { for (x = 0; x < N; x++) (UCHARDATA(g))[x] = G[x]; free(G); } else free(H); FifoTermine(FIFO[0]); FifoTermine(FIFO[1]); IndicsTermine(); return 1; } /* lgeodilat() */
/* ==================================== */ static int32_t TrouveComposantes(int32_t x, uint8_t *F, int32_t rs, int32_t ps, int32_t N, int32_t connex, int32_t *CM, int32_t *tabcomp) /* ==================================== */ // variante sans simplification // place la plus haute composante (ou l'une des plus hautes) en premier { int32_t k, y, n = 1, maxval = F[x], first = 1; switch (connex) { case 4: for (k = 0; k < 8; k += 2) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin(x, k, rs, N); if ((y != -1) && (F[y] > maxval)) maxval = F[y]; } /* for (k = 0; k < 8; k += 2) */ if (maxval == F[x]) return 0; for (k = 0; k < 8; k += 2) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin(x, k, rs, N); if ((y != -1) && (F[y] > F[x])) { if (first && (F[y] == maxval)) { tabcomp[0] = CM[y]; first = 0; } else { tabcomp[n] = CM[y]; n++; } } } break; case 8: for (k = 0; k < 8; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin(x, k, rs, N); if ((y != -1) && (F[y] > maxval)) maxval = F[y]; } /* for (k = 0; k < 8; k += 1) */ if (maxval == F[x]) return 0; for (k = 0; k < 8; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin(x, k, rs, N); if ((y != -1) && (F[y] > F[x])) { if (first && (F[y] == maxval)) { tabcomp[0] = CM[y]; first = 0; } else { tabcomp[n] = CM[y]; n++; } } } break; case 6: for (k = 0; k <= 10; k += 2) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin6(x, k, rs, ps, N); if ((y != -1) && (F[y] > maxval)) maxval = F[y]; } if (maxval == F[x]) return 0; for (k = 0; k <= 10; k += 2) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin6(x, k, rs, ps, N); if ((y != -1) && (F[y] > F[x])) { if (first && (F[y] == maxval)) { tabcomp[0] = CM[y]; first = 0; } else { tabcomp[n] = CM[y]; n++; } } } break; case 18: for (k = 0; k < 18; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin18(x, k, rs, ps, N); if ((y != -1) && (F[y] > maxval)) maxval = F[y]; } if (maxval == F[x]) return 0; for (k = 0; k < 18; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin18(x, k, rs, ps, N); if ((y != -1) && (F[y] > F[x])) { if (first && (F[y] == maxval)) { tabcomp[0] = CM[y]; first = 0; } else { tabcomp[n] = CM[y]; n++; } } } break; case 26: for (k = 0; k < 26; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin26(x, k, rs, ps, N); if ((y != -1) && (F[y] > maxval)) maxval = F[y]; } if (maxval == F[x]) return 0; for (k = 0; k < 26; k += 1) // parcourt les c-voisins y de x d'un niveau > F[x] { y = voisin26(x, k, rs, ps, N); if ((y != -1) && (F[y] > F[x])) { if (first && (F[y] == maxval)) { tabcomp[0] = CM[y]; first = 0; } else { tabcomp[n] = CM[y]; n++; } } } break; } // switch (connex) return n; } // TrouveComposantes()
/* ==================================== */ int32_t lsquel(struct xvimage *image, int32_t seuil, int32_t niseuil) /* ==================================== */ { int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t rs = rowsize(image); /* taille ligne */ int32_t cs = colsize(image); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *SOURCE = UCHARDATA(image); /* l'image de depart */ struct xvimage *lab; int32_t *M; /* l'image d'etiquettes de composantes connexes */ int32_t nminima; /* nombre de minima differents */ Fifo * FIFOn; Fifo * FIFOs; Fifo * FIFOe; Fifo * FIFOo; Fifo * FIFOna; Fifo * FIFOsa; Fifo * FIFOea; Fifo * FIFOoa; Fifo * FIFOtmp; Fifo * FIFO; int32_t niter; #ifdef PERF chrono chrono1; #endif if (depth(image) != 1) { fprintf(stderr, "lsquel: cette version ne traite pas les images volumiques\n"); exit(0); } #ifdef PERF start_chrono(&chrono1); /* pour l'analyse de performances */ #endif lab = allocimage(NULL, rs, cs, 1, VFF_TYP_4_BYTE); if (lab == NULL) { fprintf(stderr, "lhtkern: allocimage failed\n"); return 0; } M = SLONGDATA(lab); if (!llabelextrema(image, 4, LABMIN, lab, &nminima)) { fprintf(stderr, "lhtkern: llabelextrema failed\n"); return 0; } IndicsInit(N); FIFO = CreeFifoVide(N); FIFOn = CreeFifoVide(N/2); FIFOs = CreeFifoVide(N/2); FIFOe = CreeFifoVide(N/2); FIFOo = CreeFifoVide(N/2); if ((FIFO == NULL) && (FIFOn == NULL) && (FIFOs == NULL) && (FIFOe == NULL) && (FIFOo == NULL)) { fprintf(stderr, "lsquel() : CreeFifoVide failed\n"); return(0); } /* ================================================ */ /* DEBUT ALGO */ /* ================================================ */ /* ========================================================= */ /* INITIALISATION DES FIFOs: empile les voisins des minima */ /* ========================================================= */ for (x = 0; x < N; x++) { if (M[x] != 0) /* le pixel appartient a un minimum */ { Set(x, MINI); y = voisin(x, NORD, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOn, y); Set(y, EN_FIFO); } #ifdef DIAG y = voisin(x, NORD+1, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOn, y); Set(y, EN_FIFO); } #endif y = voisin(x, EST, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOe, y); Set(y, EN_FIFO); } #ifdef DIAG y = voisin(x, EST+1, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOe, y); Set(y, EN_FIFO); } #endif y = voisin(x, SUD, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOs, y); Set(y, EN_FIFO); } #ifdef DIAG y = voisin(x, SUD+1, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOs, y); Set(y, EN_FIFO); } #endif y = voisin(x, OUEST, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOo, y); Set(y, EN_FIFO); } #ifdef DIAG y = voisin(x, OUEST+1, rs, N); if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N)) { FifoPush(FIFOo, y); Set(y, EN_FIFO); } #endif } /* if (M[x] != 0) */ } /* for x */ freeimage(lab); FIFOna = CreeFifoVide(N/4); FIFOsa = CreeFifoVide(N/4); FIFOea = CreeFifoVide(N/4); FIFOoa = CreeFifoVide(N/4); if ((FIFOna == NULL) && (FIFOsa == NULL) && (FIFOea == NULL) && (FIFOoa == NULL)) { fprintf(stderr, "lsquel() : CreeFifoVide failed\n"); return(0); } /* ================================================ */ /* DEBUT SATURATION */ /* ================================================ */ niter = 0; while (! (FifoVide(FIFOn) && FifoVide(FIFOe) && FifoVide(FIFOs) && FifoVide(FIFOo))) { niter++; while (! FifoVide(FIFOn)) { x = FifoPop(FIFOn); UnSet(x, EN_FIFO); if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) { /* modifie l'image le cas echeant */ testmini(SOURCE, x, rs, N, FIFO); /* reactualise l'image MINI */ empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa); } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */ } /* while (! FifoVide(FIFOn)) */ while (! FifoVide(FIFOs)) { x = FifoPop(FIFOs); UnSet(x, EN_FIFO); if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) { /* modifie l'image le cas echeant */ testmini(SOURCE, x, rs, N, FIFO); /* reactualise l'image MINI */ empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa); } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */ } /* while (! FifoVide(FIFOs)) */ while (! FifoVide(FIFOe)) { x = FifoPop(FIFOe); UnSet(x, EN_FIFO); if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) { /* modifie l'image le cas echeant */ testmini(SOURCE, x, rs, N, FIFO); /* reactualise l'image MINI */ empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa); } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */ } /* while (! FifoVide(FIFOe)) */ while (! FifoVide(FIFOo)) { x = FifoPop(FIFOo); UnSet(x, EN_FIFO); if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) { /* modifie l'image le cas echeant */ testmini(SOURCE, x, rs, N, FIFO); /* reactualise l'image MINI */ empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa); } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */ } /* while (! FifoVide(FIFOo)) */ FIFOtmp = FIFOn; FIFOn = FIFOna; FIFOna = FIFOtmp; FIFOtmp = FIFOe; FIFOe = FIFOea; FIFOea = FIFOtmp; FIFOtmp = FIFOs; FIFOs = FIFOsa; FIFOsa = FIFOtmp; FIFOtmp = FIFOo; FIFOo = FIFOoa; FIFOoa = FIFOtmp; } /* while (! (FifoVide(FIFOn) && FifoVide(FIFOe) && FifoVide(FIFOs) && FifoVide(FIFOo))) */ /* ================================================ */ /* UN PEU DE MENAGE */ /* ================================================ */ IndicsTermine(); FifoTermine(FIFO); FifoTermine(FIFOn); FifoTermine(FIFOe); FifoTermine(FIFOs); FifoTermine(FIFOo); FifoTermine(FIFOna); FifoTermine(FIFOea); FifoTermine(FIFOsa); FifoTermine(FIFOoa); #ifdef PERF save_time(N, read_chrono(&chrono1), "lsquel", image->name); #endif return(1); }
/* ==================================== */ int32_t lkern(struct xvimage *image, int32_t connex) /* ==================================== */ { int32_t x; /* index muet de pixel */ int32_t y; /* index muet (generalement un voisin de x) */ int32_t k; /* index muet */ int32_t rs = rowsize(image); /* taille ligne */ int32_t cs = colsize(image); /* taille colonne */ int32_t N = rs * cs; /* taille image */ uint8_t *F = UCHARDATA(image); /* l'image de depart */ Fahp * FAHP; int32_t t4mm, t4m, t8p, t8pp; #ifdef DEBUG uint8_t oldFx; #endif if (depth(image) != 1) { fprintf(stderr, "lkern: cette version ne traite pas les images volumiques\n"); exit(0); } IndicsInit(N); FAHP = CreeFahpVide(N); if (FAHP == NULL) { fprintf(stderr, "lkern() : CreeFahpVide failed\n"); return(0); } /* ================================================ */ /* DEBUT ALGO */ /* ================================================ */ /* empile tous les voisins des points du bord */ for (x = rs + 1, y = (cs-2) * rs + 1; x < 2*rs-1; x++, y++) { FahpPush(FAHP, x, F[x]); Set(x, EN_FAHP); FahpPush(FAHP, y, F[y]); Set(y, EN_FAHP); } for (x = 2*rs+1 , y = 3*rs-2; x < (cs-2)*rs+1; y += rs, x += rs) { FahpPush(FAHP, x, F[x]); Set(x, EN_FAHP); FahpPush(FAHP, y, F[y]); Set(y, EN_FAHP); } saturation(rs, cs, N, F, FAHP); /* met a 0 les puits et les interieurs de plateaux (T-- = 0) */ /* et empile les voisins */ for (x = 0; x < N; x++) if ((x%rs != rs-1) && (x >= rs) && (x%rs != 0) && (x < N-rs) && /* non point de bord */ (F[x] != 0)) { nbtopo(F, x, rs, N, &t4mm, &t4m, &t8p, &t8pp); if (t4mm == 0) { F[x] = 0; for (k = 0; k < 8; k += 1) /* parcourt les voisins en 8-connexite */ { /* pour empiler les voisins */ y = voisin(x, k, rs, N); /* non deja empiles */ if ((y != -1) && (F[y] > 0) && (! IsSet(y, EN_FAHP))) { FahpPush(FAHP, y, F[y]); Set(y, EN_FAHP); } /* if y */ } /* for k */ } /* if (t4mm == 0) */ saturation(rs, cs, N, F, FAHP); } /* for (x = 0; x < N; x++) */ /* ================================================ */ /* UN PEU DE MENAGE */ /* ================================================ */ IndicsTermine(); FahpTermine(FAHP); return(1); }
/* ==================================== */ int32_t lamont( struct xvimage *m, struct xvimage *f, int32_t connex, int32_t strict) /* connex : 4, 8 (en 2D), 6, 18, 26 (en 3D) */ /* ==================================== */ #undef F_NAME #define F_NAME "lamont" { int32_t i, j, k; /* index muet de pixel */ int32_t rs = rowsize(f); /* taille ligne */ int32_t cs = colsize(f); /* taille colonne */ int32_t ds = depth(f); /* nb plans */ int32_t ps = rs * cs; /* taille plan */ int32_t N = ps * ds; /* taille image */ int32_t *F = SLONGDATA(f); uint8_t *M = UCHARDATA(m); Fifo * FIFO; int32_t incr_vois; if ((rowsize(m) != rs) || (colsize(m) != cs) || (depth(m) != ds)) { fprintf(stderr, "%s: incompatible sizes\n", F_NAME); return 0; } if ((datatype(m) != VFF_TYP_1_BYTE) || (datatype(f) != VFF_TYP_4_BYTE)) { fprintf(stderr, "%s: incompatible types\n", F_NAME); return 0; } switch (connex) { case 4: incr_vois = 2; break; case 8: incr_vois = 1; break; } /* switch (connex) */ FIFO = CreeFifoVide(N); if (FIFO == NULL) { fprintf(stderr,"%s : CreeFifoVide failed\n", F_NAME); return(0); } for (i = 0; i < N; i++) if (M[i]) FifoPush(FIFO, i); if ((connex == 4) || (connex == 8)) { if (ds != 1) { fprintf(stderr,"%s : connexity 4 or 8 not defined for 3D\n", F_NAME); return(0); } if (strict) while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 8; k += incr_vois) { j = voisin(i, k, rs, N); if ((j != -1) && !M[j] && (F[j] > F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ else while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 8; k += incr_vois) { j = voisin(i, k, rs, N); //printf("i=%d ; j=%d ; Mj=%d ; Fj=%ld ; Fi=%ld\n", i, j, M[j], F[j], F[i]); if ((j != -1) && !M[j] && (F[j] >= F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 6) { if (ds == 1) { fprintf(stderr,"%s : connexity 6 not defined for 2D\n", F_NAME); return(0); } if (strict) while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k <= 10; k += 2) { j = voisin6(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] > F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ else while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k <= 10; k += 2) { j = voisin6(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] >= F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 18) { if (ds == 1) { fprintf(stderr,"%s : connexity 18 not defined for 2D\n", F_NAME); return(0); } if (strict) while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 18; k += 1) { j = voisin18(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] > F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ else while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 18; k += 1) { j = voisin18(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] >= F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 26) { if (ds == 1) { fprintf(stderr,"%s : connexity 26 not defined for 2D\n", F_NAME); return(0); } if (strict) while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 26; k += 1) { j = voisin26(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] > F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ else while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 26; k += 1) { j = voisin26(i, k, rs, ps, N); if ((j != -1) && !M[j] && (F[j] >= F[i])) { FifoPush(FIFO, j); M[j] = 255; } } /* for k */ } /* while ! FifoVide */ } FifoTermine(FIFO); return 1; } /* lamont() */
/* ==================================== */ int32_t lselectcomp( struct xvimage *f, int32_t connex, int32_t x, int32_t y, int32_t z) /* extrait la composante connexe de f (image binaire) qui contient le point (x,y,z) */ /* connex : 4, 8 (en 2D), 6, 18, 26 (en 3D) */ /* connex : 60, 260 (en 3D): idem 6 et 26 mais dans le plan xy seulement */ /* ==================================== */ #undef F_NAME #define F_NAME "lselectcomp" { int32_t i; /* index muet de pixel */ int32_t j; /* index muet (generalement un voisin de x) */ int32_t k; /* index muet */ int32_t rs = rowsize(f); /* taille ligne */ int32_t cs = colsize(f); /* taille colonne */ int32_t ds = depth(f); /* nb plans */ int32_t ps = rs * cs; /* taille plan */ int32_t N = ps * ds; /* taille image */ uint8_t *F = UCHARDATA(f); Fifo * FIFO; int32_t incr_vois; switch (connex) { case 4: incr_vois = 2; break; case 8: incr_vois = 1; break; } /* switch (connex) */ FIFO = CreeFifoVide(N); if (FIFO == NULL) { fprintf(stderr,"%s : CreeFifoVide failed\n", F_NAME); return(0); } for (i = 0; i < N; i++) if (F[i]) F[i] = 254; i = z*ps + y*rs + x; if (F[i]) { FifoPush(FIFO, i); F[i] += 1; } if ((connex == 4) || (connex == 8)) { if (ds != 1) { fprintf(stderr,"%s : connexity 4 or 8 not defined for 3D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 8; k += incr_vois) { j = voisin(i, k, rs, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 6) { if (ds == 1) { fprintf(stderr,"%s : connexity 6 not defined for 2D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k <= 10; k += 2) { j = voisin6(i, k, rs, ps, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 18) { if (ds == 1) { fprintf(stderr,"%s : connexity 18 not defined for 2D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 18; k += 1) { j = voisin18(i, k, rs, ps, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 26) { if (ds == 1) { fprintf(stderr,"%s : connexity 26 not defined for 2D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k < 26; k += 1) { j = voisin26(i, k, rs, ps, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 60) { if (ds == 1) { fprintf(stderr,"%s : connexity 6 not defined for 2D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 0; k <= 6; k += 2) { j = voisin6(i, k, rs, ps, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } else if (connex == 260) { if (ds == 1) { fprintf(stderr,"%s : connexity 26 not defined for 2D\n", F_NAME); return(0); } while (! FifoVide(FIFO)) { i = FifoPop(FIFO); for (k = 9; k <= 16; k += 1) { j = voisin26(i, k, rs, ps, N); if ((j != -1) && (F[j]==254)) { FifoPush(FIFO, j); F[j] += 1; } } /* for k */ } /* while ! FifoVide */ } FifoTermine(FIFO); for (i = 0; i < N; i++) if (F[i] != 255) F[i] = 0; return 1; } /* lselectcomp() */
/*=====================================================================================*/ float * Overlap(struct xvimage * Isegment, struct xvimage * Imask, int nb_classes) /*=====================================================================================*/ // Computes the overlap score between a segment and the ground truth. // Overlap scores are given for each classes and stacked in a tensor. // inputs : * segment: binary image: foreground backround segmentation // * mask: ground truth image: integers between 1 and 22 { int i, j, k, p, q; // get pointer to Isegment and Imask uint8_t *segment = UCHARDATA(Isegment); uint8_t *mask = UCHARDATA(Imask); int rs = rowsize(Isegment); int cs = colsize(Isegment); int N = rs*cs; Lifo * LIFO; LIFO = CreeLifoVide(N); if (LIFO == NULL) { fprintf(stderr, "Overlap : CreeLifoVide failed\n"); exit(0); } float * overlaping_class = (float*)calloc(nb_classes ,sizeof(float)); float * union_class = (float*)calloc(nb_classes ,sizeof(float)); uint8_t * Mrk = (uint8_t*)calloc(N ,sizeof(uint8_t)); if (Mrk == NULL) { fprintf(stderr, "Overlap : malloc failed\n"); exit(0); } // first pass to count the nb of different ground truth class intersecting with the segment for (i=0;i<N;i++) if (segment[i]==255) overlaping_class[mask[i]-1]++; // useful for inter // second pass to compute the union for each present class for (j=0;j<nb_classes;j++) { if (overlaping_class[j]>0.5) //for each class present in the segment { for (i=0;i<N;i++) // for each pixel { if ((segment[i]==255)&&(mask[i]==j+1)) { LifoPush(LIFO, i); Mrk[i] = true; } } union_class[j] = overlaping_class[j]; while (!LifoVide(LIFO)) { p = LifoPop(LIFO); Mrk[p]=true; for (k = 0; k < 8; k += 2) { q = voisin(p, k, rs, N); if (q!=-1) if ((Mrk[q]==false)&&(mask[q]==mask[p])) { union_class[j]++; LifoPush(LIFO, q); Mrk[q]=true; } } } //last pass: overlap = intersection/union overlaping_class[j]=overlaping_class[j]/union_class[j]; } } LifoTermine(LIFO); free(Mrk); free(union_class); return overlaping_class; }