Beispiel #1
0
/** Convert a TESSLINE into the float-based MFOUTLINE micro-feature format. */
MFOUTLINE ConvertOutline(TESSLINE *outline) {
  MFEDGEPT *NewPoint;
  MFOUTLINE MFOutline = NIL_LIST;
  EDGEPT *EdgePoint;
  EDGEPT *StartPoint;
  EDGEPT *NextPoint;

  if (outline == NULL || outline->loop == NULL)
    return MFOutline;

  StartPoint = outline->loop;
  EdgePoint = StartPoint;
  do {
    NextPoint = EdgePoint->next;

    /* filter out duplicate points */
    if (EdgePoint->pos.x != NextPoint->pos.x ||
        EdgePoint->pos.y != NextPoint->pos.y) {
      NewPoint = NewEdgePoint();
      ClearMark(NewPoint);
      NewPoint->Hidden = EdgePoint->IsHidden();
      NewPoint->Point.x = EdgePoint->pos.x;
      NewPoint->Point.y = EdgePoint->pos.y;
      MFOutline = push(MFOutline, NewPoint);
    }
    EdgePoint = NextPoint;
  } while (EdgePoint != StartPoint);

  if (MFOutline != NULL)
    MakeOutlineCircular(MFOutline);
  return MFOutline;
}
Beispiel #2
0
// For all the edge steps in all the outlines, or polygonal approximation
// where there are no edge steps, collects the steps into the bounding_box,
// llsq and/or the x_coords/y_coords. Both are used in different kinds of
// normalization.
// For a description of x_coords, y_coords, see GetEdgeCoords above.
void TBLOB::CollectEdges(const TBOX& box,
                         TBOX* bounding_box, LLSQ* llsq,
                         GenericVector<GenericVector<int> >* x_coords,
                         GenericVector<GenericVector<int> >* y_coords) const {
  // Iterate the outlines.
  for (const TESSLINE* ol = outlines; ol != NULL; ol = ol->next) {
    // Iterate the polygon.
    EDGEPT* loop_pt = ol->FindBestStartPt();
    EDGEPT* pt = loop_pt;
    if (pt == NULL) continue;
    do {
      if (pt->IsHidden()) continue;
      // Find a run of equal src_outline.
      EDGEPT* last_pt = pt;
      do {
        last_pt = last_pt->next;
      } while (last_pt != loop_pt && !last_pt->IsHidden() &&
               last_pt->src_outline == pt->src_outline);
      last_pt = last_pt->prev;
      CollectEdgesOfRun(pt, last_pt, denorm_, box,
                        bounding_box, llsq, x_coords, y_coords);
      pt = last_pt;
    } while ((pt = pt->next) != loop_pt);
  }
}
Beispiel #3
0
// Undoes hide, so the outlines are cut by the SPLIT.
void SPLIT::Reveal() const {
  EDGEPT* edgept = point1;
  do {
    edgept->Reveal();
    edgept = edgept->next;
  } while (!edgept->EqualPos(*point2) && edgept != point1);
  edgept = point2;
  do {
    edgept->Reveal();
    edgept = edgept->next;
  } while (!edgept->EqualPos(*point1) && edgept != point2);
}
Beispiel #4
0
// Returns the first non-hidden EDGEPT that has a different src_outline to
// its predecessor, or, if all the same, the lowest indexed point.
EDGEPT* TESSLINE::FindBestStartPt() const {
  EDGEPT* best_start = loop;
  int best_step = loop->start_step;
  // Iterate the polygon.
  EDGEPT* pt = loop;
  do {
    if (pt->IsHidden()) continue;
    if (pt->prev->IsHidden() || pt->prev->src_outline != pt->src_outline)
      return pt;  // Qualifies as the best.
    if (pt->start_step < best_step) {
      best_step = pt->start_step;
      best_start = pt;
    }
  } while ((pt = pt->next) != loop);
  return best_start;
}
Beispiel #5
0
void TESSLINE::plot(ScrollView* window, ScrollView::Color color,
                    ScrollView::Color child_color) {
  if (is_hole)
    window->Pen(child_color);
  else
    window->Pen(color);
  window->SetCursor(start.x, start.y);
  EDGEPT* pt = loop;
  do {
    bool prev_hidden = pt->IsHidden();
    pt = pt->next;
    if (prev_hidden)
      window->SetCursor(pt->pos.x, pt->pos.y);
    else
      window->DrawTo(pt->pos.x, pt->pos.y);
  } while (pt != loop);
}
Beispiel #6
0
// Extracts sets of 3-D features of length kStandardFeatureLength (=12.8), as
// (x,y) position and angle as measured counterclockwise from the vector
// <-1, 0>, from blob using two normalizations defined by bl_denorm and
// cn_denorm. See SetpuBLCNDenorms for definitions.
// If outline_cn_counts is not nullptr, on return it contains the cumulative
// number of cn features generated for each outline in the blob (in order).
// Thus after the first outline, there were (*outline_cn_counts)[0] features,
// after the second outline, there were (*outline_cn_counts)[1] features etc.
void Classify::ExtractFeatures(const TBLOB& blob,
                               bool nonlinear_norm,
                               GenericVector<INT_FEATURE_STRUCT>* bl_features,
                               GenericVector<INT_FEATURE_STRUCT>* cn_features,
                               INT_FX_RESULT_STRUCT* results,
                               GenericVector<int>* outline_cn_counts) {
  DENORM bl_denorm, cn_denorm;
  tesseract::Classify::SetupBLCNDenorms(blob, nonlinear_norm,
                                        &bl_denorm, &cn_denorm, results);
  if (outline_cn_counts != nullptr)
    outline_cn_counts->truncate(0);
  // Iterate the outlines.
  for (TESSLINE* ol = blob.outlines; ol != nullptr; ol = ol->next) {
    // Iterate the polygon.
    EDGEPT* loop_pt = ol->FindBestStartPt();
    EDGEPT* pt = loop_pt;
    if (pt == nullptr) continue;
    do {
      if (pt->IsHidden()) continue;
      // Find a run of equal src_outline.
      EDGEPT* last_pt = pt;
      do {
        last_pt = last_pt->next;
      } while (last_pt != loop_pt && !last_pt->IsHidden() &&
               last_pt->src_outline == pt->src_outline);
      last_pt = last_pt->prev;
      // Until the adaptive classifier can be weaned off polygon segments,
      // we have to force extraction from the polygon for the bl_features.
      ExtractFeaturesFromRun(pt, last_pt, bl_denorm, kStandardFeatureLength,
                             true, bl_features);
      ExtractFeaturesFromRun(pt, last_pt, cn_denorm, kStandardFeatureLength,
                             false, cn_features);
      pt = last_pt;
    } while ((pt = pt->next) != loop_pt);
    if (outline_cn_counts != nullptr)
      outline_cn_counts->push_back(cn_features->size());
  }
  results->NumBL = bl_features->size();
  results->NumCN = cn_features->size();
  results->YBottom = blob.bounding_box().bottom();
  results->YTop = blob.bounding_box().top();
  results->Width = blob.bounding_box().width();
}
Beispiel #7
0
/**
 * @name vertical_projection_point
 *
 * For one point on the outline, find the corresponding point on the
 * other side of the outline that is a likely projection for a split
 * point.  This is done by iterating through the edge points until the
 * X value of the point being looked at is greater than the X value of
 * the split point.  Ensure that the point being returned is not right
 * next to the split point.  Return the edge point in *best_point as
 * a result, and any points that were newly created are also saved on
 * the new_points list.
 */
void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
                                        EDGEPT** best_point,
                                        EDGEPT_CLIST *new_points) {
  EDGEPT *p;                     /* Iterator */
  EDGEPT *this_edgept;           /* Iterator */
  EDGEPT_C_IT new_point_it(new_points);
  int x = split_point->pos.x;    /* X value of vertical */
  int best_dist = LARGE_DISTANCE;/* Best point found */

  if (*best_point != nullptr)
    best_dist = edgept_dist(split_point, *best_point);

  p = target_point;
  /* Look at each edge point */
  do {
    if (((p->pos.x <= x && x <= p->next->pos.x) ||
         (p->next->pos.x <= x && x <= p->pos.x)) &&
        !same_point(split_point->pos, p->pos) &&
        !same_point(split_point->pos, p->next->pos) &&
        !p->IsChopPt() &&
        (*best_point == nullptr || !same_point((*best_point)->pos, p->pos))) {

      if (near_point(split_point, p, p->next, &this_edgept)) {
        new_point_it.add_before_then_move(this_edgept);
      }

      if (*best_point == nullptr)
        best_dist = edgept_dist (split_point, this_edgept);

      this_edgept =
        pick_close_point(split_point, this_edgept, &best_dist);
      if (this_edgept)
        *best_point = this_edgept;
    }

    p = p->next;
  }
  while (p != target_point);
}
Beispiel #8
0
/**********************************************************************
 * reveal_edge_pair
 *
 * Change the edge points that are referenced by this seam to make
 * them hidden edges.
 **********************************************************************/
void reveal_edge_pair(EDGEPT *pt1, EDGEPT *pt2) {
  EDGEPT *edgept;

  edgept = pt1;
  do {
    edgept->Reveal();
    edgept = edgept->next;
  }
  while (!exact_point (edgept, pt2) && edgept != pt1);
  if (edgept == pt1) {
    /*              tprintf("Hid entire outline at (%d,%d)!!\n",
       edgept->pos.x,edgept->pos.y);                                */
  }
  edgept = pt2;
  do {
    edgept->Reveal();
    edgept = edgept->next;
  }
  while (!exact_point (edgept, pt1) && edgept != pt2);
  if (edgept == pt2) {
    /*              tprintf("Hid entire outline at (%d,%d)!!\n",
       edgept->pos.x,edgept->pos.y);                                */
  }
}