From e932c2e9b361ad8f27c5ccdad3b6d1c68670fd2b Mon Sep 17 00:00:00 2001 From: JosefMeixner Date: Jun 14 2016 07:18:10 +0000 Subject: Handle more then 3 peg holes (#314) * When there are more then 3 peg holes create additional holes. * When a hole touches the boundary it should still be considered a hole. * Do not compare dot size against fixed size. Will not work in some scan resolutions. Used the same value (PERCENT * max dot size) as later in the code in compare_dots. * When there are more than three peg holes the code looked for the best fit and used that. The problem was, that the middle hole was used as center for auto center. For three peg holes that is correct, but does not work for more than three. Now the best fit is calculated and from there the offset of the middle of the three best fit holes is calculated and applied. * Changed the type of a variable, missed that when I changed the usage of the variable. --- diff --git a/toonz/sources/toonzlib/autopos.cpp b/toonz/sources/toonzlib/autopos.cpp index 33dd585..911b32f 100644 --- a/toonz/sources/toonzlib/autopos.cpp +++ b/toonz/sources/toonzlib/autopos.cpp @@ -563,10 +563,14 @@ visit_bw(int i, int j, int x, int y, int bit, UCHAR *byte), #endif visit_gr8(int i, int j, int x, int y, UCHAR *pix), visit_rgb(int i, int j, int x, int y, TPixel32 *pix), - stampa_dot(DOT *dot); + stampa_dot(DOT const*dot); +//! \brief Find the best matching pegs +//! +//! The found pegs are in array dots. The function checks, which of those best fits the reference in +//! reference. The three best matching dots are returned in parameters i, j, k. static int -compare_dots(DOT dots[], int *ndots, DOT reference[], int ref_dot); +compare_dots(DOT const dots[], int ndots, DOT reference[], int ref_dot, int& i, int& j, int& k); #define REVERSE(byte, bit) \ { \ @@ -1025,8 +1029,8 @@ static int find_dots_rgb(const TRaster32P &img, int strip_width, PEGS_SIDE pegs_ if (Npix < max_area * 3 / 2 && dot_lx > 3 && dot_lx < (xsize >> 1) && dot_ly > 3 && dot_ly < (ysize >> 1) && - Xmin > x0 && Xmax < xlast && - Ymin > y0 && Ymax < ylast) { + Xmin > x0 && Xmax <= xlast && + Ymin > y0 && Ymax <= ylast) { dot_x = (float)(BIG_TO_DOUBLE(Xsum) / BIG_TO_DOUBLE(Weightsum)); dot_y = (float)(BIG_TO_DOUBLE(Ysum) / BIG_TO_DOUBLE(Weightsum)); if (vertical) { @@ -1428,6 +1432,7 @@ static void visit_rgb(int i, int j, int x, int y, TPixel32 *pix) #endif +#define PERCENT (40.0 / 100.0) /*---------------------------------------------------------------------------*/ /* * Attenzione: tutti i controlli e i calcoli vengono fatti in pixel. @@ -1445,8 +1450,8 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, float dx, dy; DOT _dotarray[MAX_DOT]; DOT *dotarray = _dotarray; - int ndot, central; - int max_area; + int ndot; + int max_area, min_area; *p_ang = 0.0; @@ -1458,9 +1463,21 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, } max_area = 0; + if (ref_dot > 0) + { + min_area = ref[0].area; + } for (i = 0; i < ref_dot; i++) + { if (ref[i].area > max_area) + { max_area = ref[i].area; + } + if (ref[i].area < min_area) + { + min_area = ref[i].area; + } + } ndot = find_dots(img, strip_width, pegs_side, dotarray, MAX_DOT, max_area); if (Debug_flag) @@ -1469,7 +1486,7 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, i = 0; while (i < ndot) //elimino i dots troppo piccoli { - if (dotarray[i].area < 500) { + if (dotarray[i].area < min_area * PERCENT) { for (int j = i; j < ndot - 1; j++) dotarray[j] = dotarray[j + 1]; ndot--; @@ -1482,7 +1499,8 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, return FALSE; } - found = compare_dots(dotarray, &ndot, ref, ref_dot); + int indexArray[3] = { 0, 1, 2 }; + found = compare_dots(dotarray, ndot, ref, ref_dot, indexArray[0], indexArray[1], indexArray[2]); if (Debug_flag) for (i = 0; i < ndot; i++) { @@ -1493,12 +1511,10 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, if (!found) return FALSE; - central = ndot / 2; - angle = 0; - for (i = 0; i < ndot - 1; i++) { - dx = dotarray[i + 1].x - dotarray[i].x; - dy = dotarray[i + 1].y - dotarray[i].y; + for (i = 0; i < 2; i++) { + dx = dotarray[indexArray[i + 1]].x - dotarray[indexArray[i]].x; + dy = dotarray[indexArray[i + 1]].y - dotarray[indexArray[i]].y; switch (pegs_side) { case PEGS_LEFT: case PEGS_RIGHT: @@ -1510,9 +1526,16 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, } } - *p_ang = angle / (ndot - 1); - *cx = dotarray[central].x; - *cy = dotarray[central].y; + *p_ang = angle / 2; + + // Now calculate the center, we have to get the offset of the center for the dot at point indexArray[1] + // from the reference and then use the angle to calculate the offsets for the center. + // + // It is assumed, that the holes are all on one line. + float pegWidth = sqrt((ref[ref_dot - 1].x - ref[0].x) * (ref[ref_dot - 1].x - ref[0].x) + (ref[ref_dot - 1].y - ref[0].y) * (ref[ref_dot - 1].y - ref[0].y)); + float refPegOffset = sqrt((ref[indexArray[1]].x - ref[0].x) * (ref[indexArray[1]].x - ref[0].x) + (ref[indexArray[1]].y - ref[0].y) * (ref[indexArray[1]].y - ref[0].y)); + *cx = dotarray[indexArray[1]].x + cos(*p_ang) * (pegWidth / 2.0f - refPegOffset); + *cy = dotarray[indexArray[1]].y + sin(*p_ang) * (pegWidth / 2.0f - refPegOffset); if (Debug_flag) { printf("\nang: %g\ncx : %g\ncy : %g\n\n", *p_ang, *cx, *cy); @@ -1522,53 +1545,49 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, } /*---------------------------------------------------------------------------*/ -#define PERCENT (40.0 / 100.0) #define MIN_V 100.0 -static int compare_dots(DOT dots[], int *ndots, - DOT reference[], int ref_dot) +static int compare_dots(DOT const dots[], int ndots, DOT reference[], int ref_dot, int& i_ok, int& j_ok, int& k_ok) { int found; - int toll, i_ok = 0, j_ok = 0, k_ok = 0; + int toll; float tolld; int i, j, k; - short *dot_ok = 0; + bool *dot_ok = 0; float *ref_dis = 0, dx, dy; float vmin, v, dist_i_j, dist_i_k, dist_j_k, del1, del2; float ref_dis_0_1, ref_dis_1_2; + i_ok = 0; + j_ok = 0; + k_ok = 0; + /* questa funz e' indipendente da posizione e orientamento dei dots */ - if (*ndots < 1 || ref_dot < 1) { + if (ndots < 1 || ref_dot < 1) { goto error; } /* controllo quanti dots sono realmente buoni per il confronto */ - dot_ok = (short *)calloc(*ndots, sizeof(short)); + dot_ok = (bool *)calloc(ndots, sizeof(bool)); found = 0; - for (i = 0; i < *ndots; i++) + for (i = 0; i < ndots; i++) { + dot_ok[i] = false; for (j = 0; j < ref_dot; j++) { toll = (int)((float)reference[j].area * PERCENT); if (abs(dots[i].area - reference[j].area) < toll) { - dot_ok[found] = i; + dot_ok[i] = true; found++; break; } } + } if (!found) { goto error; } - if (found < *ndots) { - for (i = 0; i < found; i++) { - if (dot_ok[i] != i) - *(dots + i) = *(dots + dot_ok[i]); - } - *ndots = found; - } - ref_dis = (float *)calloc(ref_dot, sizeof(float)); /* calcolo le distanze di riferimento e la tolleranza stessa */ @@ -1592,9 +1611,17 @@ static int compare_dots(DOT dots[], int *ndots, i_ok = -1; v = vmin = 10000000.0; - for (i = 0; i < *ndots - 2; i++) - for (j = i + 1; j < *ndots - 1; j++) - for (k = j + 1; k < *ndots; k++) { + for (i = 0; i < ndots - 2; i++) { + if (!dot_ok[i]) + continue; + + for (j = i + 1; j < ndots - 1; j++) { + if (!dot_ok[j]) + continue; + for (k = j + 1; k < ndots; k++) { + if (!dot_ok[k]) + continue; + // Build square discrepancies from the reference relative hole distances dx = dots[i].x - dots[j].x; dy = dots[i].y - dots[j].y; @@ -1618,6 +1645,8 @@ static int compare_dots(DOT dots[], int *ndots, vmin = v; } } + } + } if (Debug_flag) { printf("Ho trovato v = %f su %f per %d %d %d \n", @@ -1647,12 +1676,11 @@ static int compare_dots(DOT dots[], int *ndots, dy = reference[1].y - reference[2].y; ref_dis_1_2 = sqrtf((dx * dx) + (dy * dy)); - if (fabsf(dist_i_j - ref_dis_0_1) < tolld && - fabsf(dist_j_k - ref_dis_1_2) < tolld) { - *ndots = 3; - *(dots) = *(dots + i_ok); - *(dots + 1) = *(dots + j_ok); - *(dots + 2) = *(dots + k_ok); + if (fabsf(dist_i_j - ref_dis_0_1) >= tolld || + fabsf(dist_j_k - ref_dis_1_2) >= tolld) { + i_ok = 0; + j_ok = 1; + k_ok = 2; } } @@ -1672,7 +1700,7 @@ error: } /*---------------------------------------------------------------------------*/ -static void stampa_dot(DOT *dot) +static void stampa_dot(DOT const*dot) { printf("Dimensioni: %d,\t%d\n", dot->lx, dot->ly); printf("Start : %d,\t%d\n", dot->x1, dot->y1); diff --git a/toonz/sources/toonzlib/cleanupparameters.cpp b/toonz/sources/toonzlib/cleanupparameters.cpp index 55166a3..1b010d7 100644 --- a/toonz/sources/toonzlib/cleanupparameters.cpp +++ b/toonz/sources/toonzlib/cleanupparameters.cpp @@ -135,8 +135,8 @@ void FdgManager::loadFieldGuideInfo() sscanf(arg, "%d", &cnt); if (cnt >= (int)fdg_info.dots.size()) { // tmsg_error("load field guide info error: bad hole number"); - break; // return FALSE; + fdg_info.dots.push_back(CleanupTypes::DOT()); } } else if (STR_EQ(label, "X0")) sscanf(arg, "%d", &fdg_info.dots[cnt].x1);