/*---------------------------------------------------------------------------*/ /* Vesione dell'Autofill aggiornata al 22.11.94 (Fabrizio Grisoli) */ /*---------------------------------------------------------------------------*/ /* aggiornata il 20.8.98 per CM24 (W.T.) */ #include "autofill.h" #include #include #include #include "toonz/toonzimageutils.h" #include "tw/tw.h" #include "toonz/fill.h" #include "toonz/ttilesaver.h" #include "toonz4.6/tmacro.h" /* #include "tropcm.h" #include "timage_io.h" #include "tlevel_io.h" #include "toonz/txshsimplelevel.h" #include "toonz/tscenehandle.h" #include "tools/tool.h"*/ #ifndef _WIN32 #define PRINTF(args...) #else #define PRINTF #endif struct s_segm { int xa, xb, region; }; typedef struct big { UINT lo, hi; } BIG; #define ADD_BIG(B, X) \ ((B).lo += (UINT)(X), (B).hi += (B).lo >> 30, (B).lo &= 0x3fffffff, (B)) #define ASS_BIG(B, X) \ ((B).lo = (UINT)(X), (B).hi = (B).lo >> 30, (B).lo &= 0x3fffffff, (B)) #define ADD_BIG_BIG(B1, B2) \ ((B1).lo += (B2).lo, (B1).hi += (B2).hi, (B1).hi += (B1).lo >> 30, \ (B1).lo &= 0x3fffffff, (B1)) #define BIG_TO_DOUBLE(B) ((double)(B).hi * (double)0x40000000 + (double)(B).lo) #define BORDER_TOO 1 #define NO_BORDER 0 #define DIM_TRESH 0.00005 #define AMB_TRESH 130000 #define MIN_SIZE 20 struct vicine { int region_id; struct vicine *next; }; struct s_fabri_region { int active, nextfree, x, y, x1, y1, x2, y2, lx, ly, xm, ym, npix, lxa, lxb, tone, color_id, per, holes, match; BIG bx, by; BIG bx2, by2; struct vicine *vicini; }; struct s_fabri_region_list { struct s_fabri_region *array; int size, n, lx, ly; }; static struct s_fabri_region_list F_reference = {0, 0, 0}, F_work = {0, 0, 0}; static int F_ref_bx = 0; static int F_ref_by = 0; static int F_wor_bx = 0; static int F_wor_by = 0; static int Dx_f = 0, DP_f = 0, Df_f = 0; static int Dx_t = 0, DP_t = 0, Df_t = 0; /*---------------------------------------------------------------------------*/ /*-- Local Prototipes -------------------------------------------------------*/ static int trova_migliore_padre(int prob_vector[], int *att_best); static int match(int prob[], int padre, int *fro, int *to); static void scan_fabri_regions(TRasterCM32P ras, struct s_fabri_region_list *rlst, int mode, int x1, int y1, int x2, int y2); static void rinomina(int r1, int r2, int r_num, struct s_fabri_region_list *rl); static void aggiungi(int r1, int r2, struct s_fabri_region_list *rlst); static void rimuovi_tutti(int r1, struct s_fabri_region_list *rlst); static void fondi(struct s_fabri_region_list *rlst, int r1, int r2); static void assign_prob3(int prob[], int i, int j); static void find_best(int prob_vector[], int *col, int to); static void free_list(struct vicine **vic); static int somma_quadrati(int x, int y); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void rect_autofill_learn(const TToonzImageP &imgToLearn, int x1, int y1, int x2, int y2) /*---------------------------------------------------------------------------*/ { int i; double pbx, pby; double abx, aby; int tot_pix = 0; if ((x2 - x1) * (y2 - y1) < MIN_SIZE) return; pbx = pby = 0.0; abx = aby = 0.0; TRasterCM32P ras = imgToLearn->getRaster(); if (F_reference.array) { for (i = 0; i < F_reference.n; i++) free_list(&F_reference.array[i].vicini); free(F_reference.array); } F_reference.array = 0; F_reference.size = 0; F_reference.n = 0; F_reference.lx = 0; F_reference.ly = 0; scan_fabri_regions(ras, &F_reference, 1, x1, y1, x2, y2); for (i = 0; i < F_reference.n; i++) { F_reference.array[i].match = -1; F_reference.array[i].color_id = ras->pixels(F_reference.array[i].y)[F_reference.array[i].x].getPaint(); pbx += BIG_TO_DOUBLE(F_reference.array[i].bx); pby += BIG_TO_DOUBLE(F_reference.array[i].by); abx = BIG_TO_DOUBLE(F_reference.array[i].bx); aby = BIG_TO_DOUBLE(F_reference.array[i].by); tot_pix += F_reference.array[i].npix; } if (tot_pix) { F_ref_bx = pbx / tot_pix; F_ref_by = pby / tot_pix; } else { F_ref_bx = 0; F_ref_by = 0; } } /*----------------------------------------------------------------------------*/ bool rect_autofill_apply(const TToonzImageP &imgToApply, int x1, int y1, int x2, int y2, bool selective, TTileSetCM32 *tileSet) /*----------------------------------------------------------------------------*/ { double pbx, pby; double abx, aby; int i, j; int tot_pix = 0; int *prob_vector; int fro, to; int col; int valore; int padre; // int temp_prob, att_match; TRasterCM32P ras = imgToApply->getRaster(); if ((x2 - x1) * (y2 - y1) < MIN_SIZE) return false; if (F_reference.n <= 0 || F_reference.array == 0) return false; pbx = pby = 0.0; abx = aby = 0.0; /* Resetta gli eventuali accoppiamenti fatti precedentemente */ for (i = 0; i < F_reference.n; i++) F_reference.array[i].match = -1; if (F_work.array) { for (i = 0; i < F_work.n; i++) free_list(&F_work.array[i].vicini); free(F_work.array); } F_work.array = 0; F_work.size = 0; F_work.n = 0; F_work.lx = 0; F_work.ly = 0; scan_fabri_regions(ras, &F_work, 1, x1, y1, x2, y2); if (F_work.n <= 0 || F_work.array == 0) return false; if (abs(F_work.lx * F_work.ly - F_reference.lx * F_reference.ly) > 0.1 * (F_work.lx * F_work.ly + F_reference.lx * F_reference.ly)) return false; for (i = 0; i < F_work.n; i++) { F_work.array[i].match = -1; pbx += BIG_TO_DOUBLE(F_work.array[i].bx); pby += BIG_TO_DOUBLE(F_work.array[i].by); abx = BIG_TO_DOUBLE(F_work.array[i].bx); aby = BIG_TO_DOUBLE(F_work.array[i].by); tot_pix += F_work.array[i].npix; } F_wor_bx = pbx / tot_pix; F_wor_by = pby / tot_pix; prob_vector = (int *)calloc(3 * F_work.n * F_reference.n, sizeof(int)); for (i = 0; i < F_reference.n; i++) for (j = 0; j < F_work.n; j++) assign_prob3(prob_vector, i, j); Dx_f = Dx_f / F_reference.n; DP_f = DP_f / F_reference.n; Df_f = Df_f / F_reference.n; Dx_t = Dx_t / F_work.n; DP_t = DP_t / F_work.n; Df_t = Df_t / F_work.n; #ifdef SELECTIVE if (selective) { // Accoppia non trasparenti for (i = 0; i < F_work.n; i++) if (F_work.array[i].color_id != 0) { temp_prob = 0; att_match = F_reference.n; /* Se non verra' aggiornato in seguito non verra' * * comunque piu' cambiato di colore */ for (j = 0; j < F_reference.n; j++) if ((F_reference.array[i].match < 0) && ((prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[2 * (F_work.n * F_reference.n) + i * F_reference.n + j] / 1500.0) > temp_prob)) { att_match = j; temp_prob = (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[2 * (F_work.n * F_reference.n) + i * F_reference.n + j] / 1500.0); } F_work.array[i].match = att_match; if (att_match < F_reference.n) F_reference.array[att_match].match = i; } /*--------------------------------------------------------------------------*/ } #endif bool recomputeBBox = false; FillParameters params; params.m_emptyOnly = selective; for (i = 0; i < F_reference.n && i < F_work.n; i++) { padre = trova_migliore_padre(prob_vector, &fro); valore = match(prob_vector, padre, &fro, &to); if (valore > AMB_TRESH) { F_work.array[to].match = fro; F_reference.array[fro].match = to; F_work.array[to].color_id = F_reference.array[fro].color_id; if ((F_work.array[to].color_id != 0) && (valore != 0)) { params.m_p = TPoint(F_work.array[to].x, F_work.array[to].y); params.m_styleId = F_work.array[to].color_id; TTileSaverCM32 tileSaver(ras, tileSet); recomputeBBox = fill(ras, params, &tileSaver) || recomputeBBox; } } } /*..........................................................................*/ /* Matching basato sulla probabilita' di colore */ /*..........................................................................*/ if (false) { bool recomputeBBox = false; for (i = 0; i < F_work.n; i++) { if (F_work.array[i].match < 0) { find_best(prob_vector, &col, i); F_work.array[i].match = 1; F_work.array[i].color_id = col; if (F_work.array[i].color_id != 0) { params.m_p = TPoint(F_work.array[i].x, F_work.array[i].y); params.m_styleId = F_work.array[i].color_id; TTileSaverCM32 tileSaver(ras, tileSet); recomputeBBox = fill(ras, params, &tileSaver) || recomputeBBox; } } } } free(prob_vector); return recomputeBBox; } /*---------------------------------------------------------------------------*/ /* Versione del Learning delle aree di Fabrizio */ /*...........................................................................*/ void autofill_learn(const TToonzImageP &imgToLearn) /*---------------------------------------------------------------------------*/ { int i; double pbx, pby; double abx, aby; int tot_pix = 0; pbx = pby = 0.0; abx = aby = 0.0; TRasterCM32P ras = imgToLearn->getRaster(); if (F_reference.array) { for (i = 0; i < F_reference.n; i++) free_list(&F_reference.array[i].vicini); free(F_reference.array); } F_reference.array = 0; F_reference.size = 0; F_reference.n = 0; F_reference.lx = 0; F_reference.ly = 0; scan_fabri_regions(ras, &F_reference, 0, 0, 0, 0, 0); for (i = 0; i < F_reference.n; i++) { F_reference.array[i].match = -1; F_reference.array[i].color_id = ras->pixels(F_reference.array[i].y)[F_reference.array[i].y].getPaint(); pbx += BIG_TO_DOUBLE(F_reference.array[i].bx); pby += BIG_TO_DOUBLE(F_reference.array[i].by); abx = BIG_TO_DOUBLE(F_reference.array[i].bx); aby = BIG_TO_DOUBLE(F_reference.array[i].by); tot_pix += F_reference.array[i].npix; } F_ref_bx = pbx / tot_pix; F_ref_by = pby / tot_pix; } /*-- end of learn_fabrizio --------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Versione del matching delle aree di Fabrizio */ /*...........................................................................*/ bool autofill_apply(const TToonzImageP &imgToApply, bool selective, TTileSetCM32 *tileSet) /*---------------------------------------------------------------------------*/ { double pbx, pby; double abx, aby; int i, j; int tot_pix = 0; int *prob_vector; int fro, to; int col; int valore; int padre; // int temp_prob, att_match; if (F_reference.n <= 0 || F_reference.array == 0) return false; pbx = pby = 0.0; abx = aby = 0.0; TRasterCM32P ras = imgToApply->getRaster(); /* Resetta gli eventuali accoppiamenti fatti precedentemente */ for (i = 0; i < F_reference.n; i++) F_reference.array[i].match = -1; if (F_work.array) { for (i = 0; i < F_work.n; i++) free_list(&F_work.array[i].vicini); free(F_work.array); } F_work.array = 0; F_work.size = 0; F_work.n = 0; F_work.lx = 0; F_work.ly = 0; scan_fabri_regions(ras, &F_work, 0, 0, 0, 0, 0); if (abs(F_work.lx * F_work.ly - F_reference.lx * F_reference.ly) > 0.1 * (F_work.lx * F_work.ly + F_reference.lx * F_reference.ly)) return false; for (i = 0; i < F_work.n; i++) { F_work.array[i].match = -1; pbx += BIG_TO_DOUBLE(F_work.array[i].bx); pby += BIG_TO_DOUBLE(F_work.array[i].by); abx = BIG_TO_DOUBLE(F_work.array[i].bx); aby = BIG_TO_DOUBLE(F_work.array[i].by); tot_pix += F_work.array[i].npix; } F_wor_bx = pbx / tot_pix; F_wor_by = pby / tot_pix; prob_vector = (int *)calloc(3 * F_work.n * F_reference.n, sizeof(int)); for (i = 0; i < F_reference.n; i++) for (j = 0; j < F_work.n; j++) assign_prob3(prob_vector, i, j); Dx_f = Dx_f / F_reference.n; DP_f = DP_f / F_reference.n; Df_f = Df_f / F_reference.n; Dx_t = Dx_t / F_work.n; DP_t = DP_t / F_work.n; Df_t = Df_t / F_work.n; #ifdef SELECTIVE if (selective) { // Accoppia non trasparenti for (i = 0; i < F_work.n; i++) if (F_work.array[i].color_id != 0) { temp_prob = 0; att_match = F_reference.n; /* Se non verra' aggiornato in seguito non verra' * * comunque piu' cambiato di colore */ for (j = 0; j < F_reference.n; j++) if ((F_reference.array[i].match < 0) && ((prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[2 * (F_work.n * F_reference.n) + i * F_reference.n + j] / 1500.0) > temp_prob)) { att_match = j; temp_prob = (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[i * F_reference.n + j] / 1000.0) * (prob_vector[2 * (F_work.n * F_reference.n) + i * F_reference.n + j] / 1500.0); } F_work.array[i].match = att_match; if (att_match < F_reference.n) F_reference.array[att_match].match = i; } /*--------------------------------------------------------------------------*/ } #endif bool recomputeBBox = false; FillParameters params; params.m_emptyOnly = selective; for (i = 0; i < F_reference.n && i < F_work.n; i++) { padre = trova_migliore_padre(prob_vector, &fro); valore = match(prob_vector, padre, &fro, &to); if (valore > AMB_TRESH) { F_work.array[to].match = fro; F_reference.array[fro].match = to; F_work.array[to].color_id = F_reference.array[fro].color_id; if ((F_work.array[to].color_id != 0) && (valore != 0)) { params.m_p = TPoint(F_work.array[to].x, F_work.array[to].y); params.m_styleId = F_work.array[to].color_id; TTileSaverCM32 tileSaver(ras, tileSet); recomputeBBox = fill(ras, params, &tileSaver) || recomputeBBox; } } /*..........................................................................*/ /* Matching basato sulla probabilita' di colore */ /*..........................................................................*/ if (false) { bool recomputeBBox = false; for (i = 0; i < F_work.n; i++) { if (F_work.array[i].match < 0) { find_best(prob_vector, &col, i); F_work.array[i].match = 1; F_work.array[i].color_id = col; if (F_work.array[i].color_id != 0) { params.m_p = TPoint(F_work.array[i].x, F_work.array[i].y); params.m_styleId = F_work.array[i].color_id; TTileSaverCM32 tileSaver(ras, tileSet); recomputeBBox = fill(ras, params, &tileSaver) || recomputeBBox; } } } } } free(prob_vector); return recomputeBBox; } /*-- end of apply_fabrizio --------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Scansione delle aree di Fabrizio */ /*...........................................................................*/ static void scan_fabri_regions(TRasterCM32P ras, struct s_fabri_region_list *rlst, int mode, int ex1, int ey1, int ex2, int ey2) /*---------------------------------------------------------------------------*/ { int firstfree; TPixelCM32 *pix; int xa, xb; int xp, x, y, x1, y1, x2, y2, tmp; int dx, dy, i, j, h, n, tone, maxtone; int rold, rcur, nold, ncur; int precedente; struct s_segm *row[2]; int *ultima_zona; int region_id, region_old, keep, discard, vicina; bool border_tooX1, border_tooY1, border_tooX2, border_tooY2; x1 = ex1; x2 = ex2; y1 = ey1; y2 = ey2; TRect rect = ras->getBounds(); border_tooX1 = x1 == rect.x0; border_tooY1 = y1 == rect.y0; border_tooX2 = x2 == rect.x1; border_tooY2 = y2 == rect.y1; dx = x2 - x1 + 1; dy = y2 - y1 + 1; rlst->lx = dx; rlst->ly = dy; row[0] = (struct s_segm *)calloc(dx, sizeof(struct s_segm)); row[1] = (struct s_segm *)calloc(dx, sizeof(struct s_segm)); ultima_zona = (int *)calloc(dx, sizeof(int)); rold = 1; rcur = 0; nold = ncur = 0; vicina = -1; for (tmp = 0; tmp < dx; tmp++) ultima_zona[tmp] = -1; /*.. Inizializza la struttura * ...............................................*/ rlst->size = 100; rlst->array = (struct s_fabri_region *)calloc(rlst->size, sizeof(struct s_fabri_region)); rlst->n = 0; firstfree = -1; for (tmp = 0; tmp < rlst->size; tmp++) { rlst->array[tmp].vicini = NULL; rlst->array[tmp].holes = 0; } /*...........................................................................*/ for (y = y1; y <= y2; y++) { vicina = -1; pix = ras->pixels(y) + x1; x = x1; PRINTF("Cerca Area \n"); while (x <= x2) { while (x <= x2 && pix->getTone() < pix->getMaxTone()) { pix++; x++; } /*cerca una area */ if (x <= x2) { /* non ho raggiunto il bordo */ PRINTF("Prima del Bordo \n"); xa = x; maxtone = pix->getTone(); xp = x; while (x <= x2 && pix->getTone() >= pix->getMaxTone()) { tone = pix->getTone(); if (tone > maxtone) { maxtone = tone; xp = x; } pix++; x++; } xb = x - 1; PRINTF("Trovata Area \n"); region_id = -1; for (j = 0; j < nold && row[rold][j].xa <= xb; j++) { if (row[rold][j].xb >= xa && row[rold][j].xa <= xb) { region_old = row[rold][j].region; if (region_id == region_old) rlst->array[region_id].holes++; if (region_id < 0) { region_id = region_old; rlst->array[region_id].per += 2 * (xb - xa + 1) + 2 - 2 * (std::min(row[rold][j].xb, xb) - std::max(row[rold][j].xa, xa) + 1); } else if (region_id != region_old) { /* CONTATTO FRA region_id E region_old */ PRINTF("Contatto tra %d e %d \n", region_id, region_old); keep = region_old; discard = region_id; if (keep > discard) { tmp = keep; keep = discard; discard = tmp; } /*.. UNISCO LE DUE REGIONI..................... */ if (rlst->array[discard].x1 < rlst->array[keep].x1) rlst->array[keep].x1 = rlst->array[discard].x1; if (rlst->array[discard].y1 < rlst->array[keep].y1) rlst->array[keep].y1 = rlst->array[discard].y1; if (rlst->array[discard].x2 > rlst->array[keep].x2) rlst->array[keep].x2 = rlst->array[discard].x2; if (rlst->array[discard].y2 > rlst->array[keep].y2) rlst->array[keep].y2 = rlst->array[discard].y2; rlst->array[keep].holes += rlst->array[discard].holes; rlst->array[keep].npix += rlst->array[discard].npix; rlst->array[keep].per += rlst->array[discard].per - 2 * (std::min(row[rold][j].xb, xb) - std::max(row[rold][j].xa, xa) + 1); fondi(rlst, keep, discard); ADD_BIG_BIG(rlst->array[keep].by, rlst->array[discard].by); ADD_BIG_BIG(rlst->array[keep].bx, rlst->array[discard].bx); ADD_BIG_BIG(rlst->array[keep].by2, rlst->array[discard].by2); ADD_BIG_BIG(rlst->array[keep].bx2, rlst->array[discard].bx2); if (rlst->array[keep].tone < rlst->array[discard].tone) { rlst->array[keep].x = rlst->array[discard].x; rlst->array[keep].y = rlst->array[discard].y; rlst->array[keep].tone = rlst->array[discard].tone; } /* OGNI RIFERIMENTO A 'discard' DIVENTA UN RIF. A 'keep' */ for (h = 0; h < nold; h++) if (row[rold][h].region == discard) row[rold][h].region = keep; for (h = 0; h < ncur; h++) if (row[rcur][h].region == discard) row[rcur][h].region = keep; region_id = keep; rinomina(discard, keep, rlst->n, rlst); for (tmp = 0; tmp < dx; tmp++) if (ultima_zona[tmp] == discard) ultima_zona[tmp] = keep; /* AGGIUNGO discard AL POOL DEI LIBERI */ rlst->array[discard].active = 0; rlst->array[discard].nextfree = firstfree; free_list(&rlst->array[discard].vicini); rlst->array[discard].vicini = NULL; firstfree = discard; } /* end elseif */ } /* end of if */ } /* end of for */ PRINTF("Region ID %d %d %d %d \n", region_id, xa, xb, y); PRINTF("Memorizza Area \n"); if (region_id >= 0) { rlst->array[region_id].lxb = xb; rlst->array[region_id].lxa = xa; if (xa < rlst->array[region_id].x1) rlst->array[region_id].x1 = xa; if (xb > rlst->array[region_id].x2) rlst->array[region_id].x2 = xb; if (y < rlst->array[region_id].y1) rlst->array[region_id].y1 = y; if (y > rlst->array[region_id].y2) rlst->array[region_id].y2 = y; rlst->array[region_id].npix += xb - xa + 1; ADD_BIG(rlst->array[region_id].by, (xb - xa + 1) * y); ADD_BIG(rlst->array[region_id].bx, (xb - xa + 1) * (xb + xa) / 2); ADD_BIG(rlst->array[region_id].by2, (xb - xa + 1) * y * y); ADD_BIG(rlst->array[region_id].bx2, somma_quadrati(xa, xb)); if (rlst->array[region_id].tone < maxtone || (rlst->array[region_id].x2 - rlst->array[region_id].x1) < xb - xa) { rlst->array[region_id].x = xp; rlst->array[region_id].y = y; rlst->array[region_id].tone = maxtone; } } else { /* CREO UNA NUOVA REGIONE */ if (firstfree < 0) { if (rlst->n >= rlst->size) { rlst->size += 50; rlst->array = (struct s_fabri_region *)realloc( rlst->array, rlst->size * sizeof(struct s_fabri_region)); for (tmp = rlst->size - 1; tmp >= rlst->size - 50; tmp--) rlst->array[tmp].vicini = NULL; } region_id = rlst->n++; } else { region_id = firstfree; firstfree = rlst->array[region_id].nextfree; } rlst->array[region_id].active = 1; rlst->array[region_id].vicini = NULL; rlst->array[region_id].nextfree = 0; rlst->array[region_id].x = xp; rlst->array[region_id].y = y; rlst->array[region_id].x1 = xa; rlst->array[region_id].y1 = y; rlst->array[region_id].x2 = xb; rlst->array[region_id].y2 = y; rlst->array[region_id].npix = xb - xa + 1; rlst->array[region_id].holes = 0; rlst->array[region_id].per = 2 * (xb - xa + 1) + 2; rlst->array[region_id].lxb = xb; rlst->array[region_id].lxa = xa; ASS_BIG(rlst->array[region_id].by, (xb - xa + 1) * y); ASS_BIG(rlst->array[region_id].bx, (xb - xa + 1) * (xb + xa) / 2); ASS_BIG(rlst->array[region_id].by2, (xb - xa + 1) * y * y); ASS_BIG(rlst->array[region_id].bx2, somma_quadrati(xa, xb)); rlst->array[region_id].tone = maxtone; rlst->array[region_id].color_id = pix->getPaint(); } /* MEMORIZZO LA REGIONE CORRENTE */ precedente = -1; /*----------------------------------------------------- .. Controlla se esiste vicinanza verticale ...........*/ for (tmp = xa; tmp <= xb; tmp++) { if (ultima_zona[tmp - x1] != precedente) { aggiungi(ultima_zona[tmp - x1], region_id, rlst); precedente = ultima_zona[tmp - x1]; } ultima_zona[tmp - x1] = region_id; } /*-----------------------------------------------------*/ aggiungi(vicina, region_id, rlst); vicina = region_id; if (ncur >= dx - 1) { printf("autofill: row overflow dx=%d\n", dx); exit(1); } row[rcur][ncur].xa = xa; row[rcur][ncur].xb = xb; row[rcur][ncur].region = region_id; ncur++; } /* end of if#1 */ } /* end of while#1 */ rcur = 1 - rcur; rold = 1 - rold; nold = ncur; ncur = 0; } /* end of for#1 */ n = 0; /* mostra_vicini(rlst); */ for (i = 0; i < rlst->n; i++) if ((rlst->array[i].active) && ((rlst->array[i].x1 > x1 || border_tooX1) && (rlst->array[i].x2 < x2 || border_tooX2) && (rlst->array[i].y1 > y1 || border_tooY1) && (rlst->array[i].y2 < y2 || border_tooY2))) { if (n < i) { rlst->array[n] = rlst->array[i]; rlst->array[n].vicini = rlst->array[i].vicini; rinomina(i, n, rlst->n, rlst); for (tmp = 0; tmp < dx; tmp++) if (ultima_zona[tmp] == i) ultima_zona[tmp] = n; } rlst->array[n].lx = rlst->array[n].x2 - rlst->array[n].x1 + 1; rlst->array[n].ly = rlst->array[n].y2 - rlst->array[n].y1 + 1; rlst->array[n].xm = (rlst->array[n].x2 + rlst->array[n].x1) / 2; rlst->array[n].ym = (rlst->array[n].y2 + rlst->array[n].y1) / 2; n++; } else rimuovi_tutti(i, rlst); /* mostra_vicini(rlst); */ rlst->n = n; free(row[0]); free(row[1]); free(ultima_zona); } /*- end of scan_fabri_regions --------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Rinomina tutti i vicini regione1 in regione2 */ /*...........................................................................*/ static void rinomina(int regione1, int regione2, int num_regioni, struct s_fabri_region_list *rlst) /*---------------------------------------------------------------------------*/ { struct vicine *appo, *old, appo1; int i; bool trovato = false; PRINTF("Rinomino %d %d Regioni: %d \n", regione1, regione2, num_regioni); /* mostra_vicini(rlst); */ for (i = 0; i < num_regioni; i++) if (rlst->array[i].active) { trovato = ((i == regione2) || (i == regione1)); PRINTF(">> %d \n", i); old = NULL; appo = rlst->array[i].vicini; while (appo != NULL) { if ((appo->region_id == regione2) || (appo->region_id == regione1)) { if (trovato) if (old != NULL) { PRINTF("A%d %d \n", i, appo->region_id); old->next = appo->next; free(appo); appo = old->next; /* mostra_vicini(rlst); */ } else { PRINTF("B%d %d \n", i, appo->region_id); rlst->array[i].vicini = appo->next; appo1 = *appo; free(appo); appo = appo1.next; } else /* non ho ancora trovato */ { PRINTF("S%d \n", appo->region_id); appo->region_id = regione2; old = appo; appo = appo->next; trovato = true; } } else /* region_id non e' region2 o regione 1 */ { PRINTF("D%d \n", appo->region_id); old = appo; appo = appo->next; } } } PRINTF("Rinomino %d %d\n", regione1, regione2); /* mostra_vicini(rlst); */ } /*- end of rinomina ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Aggiunge a regione2 il vicino regione1 e viceversa */ /*...........................................................................*/ static void aggiungi(int regione1, int regione2, struct s_fabri_region_list *rlst) /*---------------------------------------------------------------------------*/ { struct vicine *appo1, *appo2; /* if((regione1==0)||(regione2==0)) */ PRINTF("Aggiungo %d a %d\n", regione1, regione2); if ((regione1 != -1) && (regione2 != -1) && (regione2 != regione1)) { if (rlst->array[regione1].active) { appo1 = rlst->array[regione1].vicini; while ((appo1 != NULL) && (appo1->region_id != regione2)) appo1 = appo1->next; if (appo1 == NULL) { appo1 = (struct vicine *)calloc(1, sizeof(struct vicine)); appo1->next = rlst->array[regione1].vicini; appo1->region_id = regione2; rlst->array[regione1].vicini = appo1; } } if (rlst->array[regione2].active) { appo2 = rlst->array[regione2].vicini; while ((appo2 != NULL) && (appo2->region_id != regione1)) appo2 = appo2->next; if (appo2 == NULL) { appo2 = (struct vicine *)calloc(1, sizeof(struct vicine)); appo2->next = rlst->array[regione2].vicini; appo2->region_id = regione1; rlst->array[regione2].vicini = appo2; } } } PRINTF("Aggiunto %d a %d\n", regione1, regione2); } /*- end of aggiungi ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Aggiunge i vicini di r2 a quelli di r1 */ /*...........................................................................*/ static void fondi(struct s_fabri_region_list *rlst, int r1, int r2) /*---------------------------------------------------------------------------*/ { struct vicine *appo1, *appo2, *appo3; PRINTF("Fondi %d %d \n", r1, r2); /* mostra_vicini(rlst); */ appo2 = rlst->array[r2].vicini; while (appo2 != NULL) { appo1 = rlst->array[r1].vicini; while ((appo1 != NULL) && (appo1->region_id != appo2->region_id) && (appo2->region_id != r1)) appo1 = appo1->next; if (appo1 == NULL) { appo3 = (struct vicine *)calloc(1, sizeof(struct vicine)); appo3->next = rlst->array[r1].vicini; appo3->region_id = appo2->region_id; rlst->array[r1].vicini = appo3; appo2 = appo2->next; } else { appo2 = appo2->next; } } PRINTF("Fuso %d %d \n", r1, r2); /* mostra_vicini(rlst); */ } /*- end of fondi ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Mostra i vicini di ogni regione */ /*...........................................................................*/ static void mostra_vicini(struct s_fabri_region_list *rlst) /*---------------------------------------------------------------------------*/ { int i; struct vicine *appo; for (i = 0; i < rlst->n; i++) if (rlst->array[i].active) { PRINTF("Region: %d ::", i); appo = rlst->array[i].vicini; while (appo != NULL) { PRINTF("%d ", appo->region_id); appo = appo->next; } PRINTF("\n"); } else PRINTF("Region: %d inactive \n", i); } /*- end of mostra_vicini ----------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Rimuove r1 come vicino in ogni regione */ /*...........................................................................*/ static void rimuovi_tutti(int r1, struct s_fabri_region_list *rlst) /*---------------------------------------------------------------------------*/ { struct vicine *appo, *old; int i; PRINTF("Elimino %d \n", r1); /* mostra_vicini(rlst); */ for (i = 0; i < rlst->n; i++) if (rlst->array[i].active) { PRINTF(">> %d \n", i); old = NULL; appo = rlst->array[i].vicini; while (appo != NULL) { if (appo->region_id == r1) { PRINTF("A%d %d\n", appo->region_id, old->region_id); if (old != NULL) { old->next = appo->next; /* free(appo); */ appo = old->next; /* mostra_vicini(rlst); */ } else { rlst->array[i].vicini = appo->next; /* free(appo); */ appo = rlst->array[i].vicini; } } else /* region_id non e' region2 o regione 1 */ { PRINTF("D%d \n", appo->region_id); old = appo; appo = appo->next; } } } /* mostra_vicini(rlst); */ } /*- end of rimuovi_tutti ----------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Assegna la probabilita' di transizione i->j (3) */ /*...........................................................................*/ static void assign_prob3(int prob[], int i, int j) /*---------------------------------------------------------------------------*/ { double delta_posx1, delta_posy1, delta_posx2, delta_posy2; double delta_momx1, delta_momy1, delta_momx2, delta_momy2; int delta_pix, delta_pix_max; double delta_pos, delta_pos_max, delta_forma_mom; int delta_forma1, delta_forma2, delta_forma; delta_posx1 = BIG_TO_DOUBLE(F_reference.array[i].bx) / F_reference.array[i].npix - F_ref_bx; delta_posy1 = BIG_TO_DOUBLE(F_reference.array[i].by) / F_reference.array[i].npix - F_ref_by; delta_posx2 = BIG_TO_DOUBLE(F_work.array[j].bx) / F_work.array[j].npix - F_wor_bx; delta_posy2 = BIG_TO_DOUBLE(F_work.array[j].by) / F_work.array[j].npix - F_wor_by; /* Cosi' calcolo il modulo della differenza */ delta_pos = sqrt((delta_posx2 - delta_posx1) * (delta_posx2 - delta_posx1) + (delta_posy2 - delta_posy1) * (delta_posy2 - delta_posy1)); delta_pos_max = sqrt((double)(F_work.lx * F_work.lx + F_work.ly * F_work.ly)); prob[i + j * F_reference.n] = ROUNDP(1000 * (1 - (delta_pos / delta_pos_max))); delta_pix = abs(F_reference.array[i].npix - F_work.array[j].npix); delta_pix_max = std::max((F_work.lx * F_work.ly), (F_reference.lx * F_reference.ly)); prob[(F_work.n * F_reference.n) + i + (j * F_reference.n)] = ROUNDP(1000 * (1 - ((double)delta_pix / (F_reference.array[i].npix + F_work.array[j].npix)))); delta_momx1 = BIG_TO_DOUBLE(F_reference.array[i].bx2) / F_reference.array[i].npix - (BIG_TO_DOUBLE(F_reference.array[i].bx) / F_reference.array[i].npix * BIG_TO_DOUBLE(F_reference.array[i].bx) / F_reference.array[i].npix); delta_momy1 = BIG_TO_DOUBLE(F_reference.array[i].by2) / F_reference.array[i].npix - (BIG_TO_DOUBLE(F_reference.array[i].by) / F_reference.array[i].npix * BIG_TO_DOUBLE(F_reference.array[i].by) / F_reference.array[i].npix); delta_momx2 = BIG_TO_DOUBLE(F_work.array[j].bx2) / F_work.array[j].npix - (BIG_TO_DOUBLE(F_work.array[j].bx) / F_work.array[j].npix * BIG_TO_DOUBLE(F_work.array[j].bx) / F_work.array[j].npix); delta_momy2 = BIG_TO_DOUBLE(F_work.array[j].by2) / F_work.array[j].npix - (BIG_TO_DOUBLE(F_work.array[j].by) / F_work.array[j].npix * BIG_TO_DOUBLE(F_work.array[j].by) / F_work.array[j].npix); delta_forma_mom = std::abs(sqrt(delta_momx1 + delta_momy1) - sqrt(delta_momx2 + delta_momy2)); delta_forma1 = ROUNDP( 1000 * (((double)F_reference.array[i].per / F_reference.array[i].npix - 2 / sqrt((double)F_reference.array[i].npix / 3.14)) / (2 - 2 / sqrt((double)F_reference.array[i].npix / 3.14)))); delta_forma2 = ROUNDP(1000 * (((double)F_work.array[j].per / F_work.array[j].npix - 2 / sqrt((double)F_work.array[j].npix / 3.14)) / (2 - 2 / sqrt((double)F_work.array[j].npix / 3.14)))); delta_forma = ROUNDP(1000 * (1 - (delta_forma_mom / delta_pos_max))); prob[(2 * F_work.n * F_reference.n) + i + (j * F_reference.n)] = delta_forma; Dx_f += ROUNDP(sqrt(delta_posx1 * delta_posx1 + delta_posy1 * delta_posy1)); DP_f += F_reference.array[i].npix; Df_f += ROUNDP(sqrt(delta_momx1 * delta_momx1 + delta_momy1 * delta_momy1)); Dx_t += ROUNDP(sqrt(delta_posx2 * delta_posx2 + delta_posy2 * delta_posy2)); DP_t += F_work.array[j].npix; Df_t += ROUNDP(sqrt(delta_momx2 * delta_momx2 + delta_momy2 * delta_momy2)); } /*- end of assign_prob ------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Trova il colore migliore per una regione */ /*...........................................................................*/ static void find_best(int prob[], int *col, int to) /*---------------------------------------------------------------------------*/ { float att_max = 0.0; int i, j, numero; float color_value; for (i = 0; i < F_reference.n; i++) { color_value = 0.0; numero = 0; for (j = 0; j < F_reference.n; j++) { if (F_reference.array[i].color_id == F_reference.array[j].color_id) { color_value += (prob[to * F_reference.n + j] / 1000.0) * (prob[to * F_reference.n + j] / 1000.0) * /* (prob[(F_work.n*F_reference.n)+to*F_reference.n+j]/1500.0)* */ (prob[2 * (F_work.n * F_reference.n) + to * F_reference.n + j] / 1500.0); numero++; } } if ((color_value / numero) > att_max) { att_max = color_value / numero; PRINTF("Nuovo Massimo %f \n", att_max); *col = F_reference.array[i].color_id; } } } /*- end of find_best --------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* libera la memoria occupata da una lista */ /*...........................................................................*/ static void free_list(struct vicine **vic) /*---------------------------------------------------------------------------*/ { if (*vic != NULL) { free_list(&(*vic)->next); free(*vic); *vic = NULL; } } /*- end of free_list --------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Somma il quadrato dei numeri da x a y o viceversa */ /*...........................................................................*/ static int somma_quadrati(int x, int y) /*---------------------------------------------------------------------------*/ { int somma = 0; int i; for (i = std::min(x, y); i <= std::max(x, y); i++) somma += i * i; return somma; } /*- end of somma_quadrati ---------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Scegli il punto da cui proseguire l'accoppiamento */ /*...........................................................................*/ static int trova_migliore_padre(int prob_vector[], int *att_my) /*---------------------------------------------------------------------------*/ { int att_best, att_second, att_max_diff = 0; int att_choice = -1, i, j, k; struct vicine *a1, *a2; PRINTF("Inizio Ricerca del Padre \n"); for (k = 0; k < F_reference.n; k++) if (F_reference.array[k].match >= 0) { PRINTF("%d Gia' Accoppiato\n", k); a1 = F_reference.array[k].vicini; while (a1 != NULL) { i = a1->region_id; if (F_reference.array[i].match < 0) { PRINTF("%d vicino di %d Non Accoppiato\n", i, k); a2 = F_work.array[F_reference.array[k].match].vicini; att_best = 0; att_second = 0; while (a2 != NULL) { PRINTF("Coppia %d %d \n", i, j); j = a2->region_id; if (F_work.array[j].match < 0) { if (prob_vector[j * F_reference.n + i] * prob_vector[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob_vector[2 * (F_work.n * F_reference.n) + j * F_reference.n + i] > att_second) att_second = prob_vector[j * F_reference.n + i] * prob_vector[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob_vector[2 * (F_work.n * F_reference.n) + j * F_reference.n + i]; if (prob_vector[j * F_reference.n + i] * prob_vector[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob_vector[2 * (F_work.n * F_reference.n) + j * F_reference.n + i] > att_best) { att_second = att_best; att_best = prob_vector[j * F_reference.n + i] * prob_vector[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob_vector[2 * (F_work.n * F_reference.n) + j * F_reference.n + i]; } } a2 = a2->next; } if ((att_best - att_second) > att_max_diff) { att_max_diff = att_best - att_second; att_choice = F_reference.array[k].match; *att_my = i; PRINTF("Nuovo Coeff.: %d \n", att_max_diff); } } a1 = a1->next; } } PRINTF("Finita Ricerca del Padre \n"); return att_choice; } /*---------------------------------------------------------------------------*/ static int match(int prob[], int padre, int *fro, int *to) /*---------------------------------------------------------------------------*/ { int att_max = 0, i, j; struct vicine *a2; if (padre > -1) { a2 = F_work.array[padre].vicini; while (a2 != NULL) { j = a2->region_id; if ((F_work.array[j].match < 0) && (prob[j * F_reference.n + (*fro)] * prob[(F_work.n * F_reference.n) + j * F_reference.n + (*fro)] * prob[2 * (F_work.n * F_reference.n) + j * F_reference.n + (*fro)] > att_max)) { att_max = prob[j * F_reference.n + (*fro)] * prob[(F_work.n * F_reference.n) + j * F_reference.n + (*fro)] * prob[2 * (F_work.n * F_reference.n) + j * F_reference.n + (*fro)]; *to = j; } a2 = a2->next; } } else { for (i = 0; i < F_reference.n; i++) for (j = 0; j < F_work.n; j++) if ((F_work.array[j].match < 0) && (F_reference.array[i].match < 0) && (F_work.array[j].npix > DIM_TRESH * F_work.lx * F_work.ly) && (F_reference.array[i].npix > DIM_TRESH * F_reference.lx * F_reference.ly)) { if (prob[j * F_reference.n + i] * prob[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob[2 * (F_work.n * F_reference.n) + j * F_reference.n + i] > att_max) { att_max = prob[j * F_reference.n + i] * prob[(F_work.n * F_reference.n) + j * F_reference.n + i] * prob[2 * (F_work.n * F_reference.n) + j * F_reference.n + i]; *fro = i; *to = j; } } } return att_max; }