Exemple #1
0
/**********************************************************************
 * blobs_widths
 *
 * Compute the widths of a list of blobs. Return an array of the widths
 * and gaps.
 **********************************************************************/
WIDTH_RECORD *blobs_widths(TBLOB *blobs) {  /*blob to compute on */
  WIDTH_RECORD *width_record;
  TPOINT topleft;                /*bounding box */
  TPOINT botright;
  int i = 0;
  int blob_end;
  int num_blobs = count_blobs (blobs);

  /* Get memory */
  width_record = (WIDTH_RECORD *) memalloc (sizeof (int) * num_blobs * 2);
  width_record->num_chars = num_blobs;

  blob_bounding_box(blobs, &topleft, &botright); 
  width_record->widths[i++] = botright.x - topleft.x;
  /* First width */
  blob_end = botright.x;

  for (TBLOB* blob = blobs->next; blob != NULL; blob = blob->next) {
    blob_bounding_box(blob, &topleft, &botright); 
    width_record->widths[i++] = topleft.x - blob_end;
    width_record->widths[i++] = botright.x - topleft.x;
    blob_end = botright.x;
  }
  return (width_record);
}
Exemple #2
0
/**
 * @name start_seam_list
 *
 * Initialize a list of seams that match the original number of blobs
 * present in the starting segmentation.  Each of the seams created
 * by this routine have location information only.
 */
SEAMS start_seam_list(TBLOB *blobs) {
  TBLOB *blob;
  SEAMS seam_list;
  TPOINT topleft;
  TPOINT botright;
  TPOINT location;
  /* Seam slot per char */
  seam_list = new_seam_list ();

  for (blob = blobs; blob->next != NULL; blob = blob->next) {

    blob_bounding_box(blob, &topleft, &botright);
    location.x = botright.x;
    location.y = botright.y + topleft.y;
    blob_bounding_box (blob->next, &topleft, &botright);
    location.x += topleft.x;
    location.y += botright.y + topleft.y;
    location.x /= 2;
    location.y /= 4;

    seam_list = add_seam (seam_list,
      new_seam (0.0, location, NULL, NULL, NULL));
  }

  return (seam_list);
}
Exemple #3
0
/**********************************************************************
 * total_containment
 *
 * Check to see if one of these outlines is totally contained within
 * the bounding box of the other.
 **********************************************************************/
inT16 total_containment(TBLOB *blob1, TBLOB *blob2) {
  TPOINT topleft1;
  TPOINT botright1;
  TPOINT topleft2;
  TPOINT botright2;

  blob_bounding_box(blob1, &topleft1, &botright1);
  blob_bounding_box(blob2, &topleft2, &botright2);

  return (bounds_inside (topleft1, botright1, topleft2, botright2) ||
    bounds_inside (topleft2, botright2, topleft1, botright1));
}
Exemple #4
0
TBOX TBLOB::bounding_box() const {
  TPOINT topleft;
  TPOINT botright;
  blob_bounding_box(this, &topleft, &botright);
  TBOX box(topleft.x, botright.y, botright.x, topleft.y);
  return box;
}
Exemple #5
0
/**********************************************************************
 * blobs_bounding_box
 *
 * Return the smallest extreme point that contain this word.
 **********************************************************************/
void blobs_bounding_box(TBLOB *blobs, TPOINT *topleft, TPOINT *botright) { 
  TPOINT tl;
  TPOINT br;
  /* Start with first blob */
  blob_bounding_box(blobs, topleft, botright); 

  for (TBLOB* blob = blobs; blob != NULL; blob = blob->next) { 
    blob_bounding_box(blob, &tl, &br); 

    if (tl.x < topleft->x)
      topleft->x = tl.x;
    if (tl.y > topleft->y)
      topleft->y = tl.y;
    if (br.x > botright->x)
      botright->x = br.x;
    if (br.y < botright->y)
      botright->y = br.y;
  }
}
Exemple #6
0
/**********************************************************************
 * blob_origin
 *
 * Compute the origin of a compound blob, define to be the centre
 * of the bounding box.
 **********************************************************************/
void blob_origin(TBLOB *blob,       /*blob to compute on */
                 TPOINT *origin) {  /*return value */
  TPOINT topleft;                /*bounding box */
  TPOINT botright;

                                 /*find bounding box */
  blob_bounding_box(blob, &topleft, &botright); 
                                 /*centre of box */
  origin->x = (topleft.x + botright.x) / 2;
  origin->y = (topleft.y + botright.y) / 2;
}
/**********************************************************************
 * record_blob_bounds
 *
 * Set up and initialize an array that holds the bounds of a set of
 * blobs.
 **********************************************************************/
BOUNDS_LIST record_blob_bounds(TBLOB *blobs) { 
  TBLOB *blob;
  BOUNDS_LIST bounds;
  TPOINT topleft;
  TPOINT botright;
  INT16 x = 0;

  bounds = (BOUNDS_LIST) memalloc (count_blobs (blobs) * sizeof (BOUNDS));

  iterate_blobs(blob, blobs) { 
    blob_bounding_box(blob, &topleft, &botright); 
    set_bounds_entry(bounds, x, topleft, botright); 
    x++;
  }
/**********************************************************************
 * choose_best_seam
 *
 * Choose the best seam that can be created by assembling this a
 * collection of splits.  A queue of all the possible seams is
 * maintained.  Each new split received is placed in that queue with
 * its partial priority value.  These values in the seam queue are
 * evaluated and combined until a good enough seam is found.  If no
 * further good seams are being found then this function returns to the
 * caller, who will send more splits.  If this function is called with
 * a split of NULL, then no further splits can be supplied by the
 * caller.
 **********************************************************************/
void choose_best_seam(SEAM_QUEUE seam_queue,
                      SEAM_PILE *seam_pile,
                      SPLIT *split,
                      PRIORITY priority,
                      SEAM **seam_result,
                      TBLOB *blob) {
  SEAM *seam;
  TPOINT topleft;
  TPOINT botright;
  char str[80];
  float my_priority;
  /* Add seam of split */
  my_priority = priority;
  if (split != NULL) {
    seam = new_seam (my_priority,
      (split->point1->pos.x + split->point1->pos.x) / 2,
      split, NULL, NULL);
    if (chop_debug > 1)
      print_seam ("Partial priority    ", seam);
    add_seam_to_queue (seam_queue, seam, (float) my_priority);

    if (my_priority > chop_good_split)
      return;
  }

  blob_bounding_box(blob, &topleft, &botright);
  /* Queue loop */
  while (pop_next_seam (seam_queue, seam, my_priority)) {
    /* Set full priority */
    my_priority = seam_priority (seam, topleft.x, botright.x);
    if (chop_debug) {
      sprintf (str, "Full my_priority %0.0f,  ", my_priority);
      print_seam(str, seam);
    }

    if ((*seam_result == NULL || /* Replace answer */
    (*seam_result)->priority > my_priority) && my_priority < chop_ok_split) {
      /* No crossing */
      if (constrained_split (seam->split1, blob)) {
        delete_seam(*seam_result);
        clone_seam(*seam_result, seam);
        (*seam_result)->priority = my_priority;
      }
      else {
        delete_seam(seam);
        seam = NULL;
        my_priority = BAD_PRIORITY;
      }
    }

    if (my_priority < chop_good_split) {
      if (seam)
        delete_seam(seam);
      return;                    /* Made good answer */
    }

    if (seam) {
                                 /* Combine with others */
      if (array_count (*seam_pile) < MAX_NUM_SEAMS
      /*|| tessedit_truncate_chopper==0 */ ) {
        combine_seam(seam_queue, *seam_pile, seam);
        *seam_pile = array_push (*seam_pile, seam);
      }
      else
        delete_seam(seam);
    }

    my_priority = best_seam_priority (seam_queue);
    if ((my_priority > chop_ok_split) ||
      (my_priority > chop_good_split && split))
      return;
  }
}