Esempio n. 1
0
void PageIterator::Orientation(tesseract::Orientation *orientation,
                               tesseract::WritingDirection *writing_direction,
                               tesseract::TextlineOrder *textline_order,
                               float *deskew_angle) const {
  BLOCK* block = it_->block()->block;

  // Orientation
  FCOORD up_in_image(0.0, 1.0);
  up_in_image.unrotate(block->classify_rotation());
  up_in_image.rotate(block->re_rotation());

  if (up_in_image.x() == 0.0F) {
    if (up_in_image.y() > 0.0F) {
      *orientation = ORIENTATION_PAGE_UP;
    } else {
      *orientation = ORIENTATION_PAGE_DOWN;
    }
  } else if (up_in_image.x() > 0.0F) {
    *orientation = ORIENTATION_PAGE_RIGHT;
  } else {
    *orientation = ORIENTATION_PAGE_LEFT;
  }

  // Writing direction
  bool is_vertical_text = (block->classify_rotation().x() == 0.0);
  bool right_to_left = block->right_to_left();
  *writing_direction =
      is_vertical_text
          ? WRITING_DIRECTION_TOP_TO_BOTTOM
          : (right_to_left
                ? WRITING_DIRECTION_RIGHT_TO_LEFT
                : WRITING_DIRECTION_LEFT_TO_RIGHT);

  // Textline Order
  bool is_mongolian = false;  // TODO(eger): fix me
  *textline_order = is_vertical_text
      ? (is_mongolian
         ? TEXTLINE_ORDER_LEFT_TO_RIGHT
         : TEXTLINE_ORDER_RIGHT_TO_LEFT)
      : TEXTLINE_ORDER_TOP_TO_BOTTOM;

  // Deskew angle
  FCOORD skew = block->skew();  // true horizontal for textlines
  *deskew_angle = -skew.angle();
}
Esempio n. 2
0
// Fits a line in the given direction to blobs that are close to the given
// target_offset perpendicular displacement from the direction. The fit
// error is allowed to be cheat_allowance worse than the existing fit, and
// will still be used.
// If cheat_allowance > 0, the new fit will be good and replace the current
// fit if it has better fit (with cheat) OR its error is below
// max_baseline_error_ and the old fit is marked bad.
// Otherwise the new fit will only replace the old if it is really better,
// or the old fit is marked bad and the new fit has sufficient points, as
// well as being within the max_baseline_error_.
void BaselineRow::FitConstrainedIfBetter(int debug,
                                         const FCOORD& direction,
                                         double cheat_allowance,
                                         double target_offset) {
  double halfrange = fit_halfrange_ * direction.length();
  double min_dist = target_offset - halfrange;
  double max_dist = target_offset + halfrange;
  ICOORD line_pt;
  double new_error = fitter_.ConstrainedFit(direction, min_dist, max_dist,
                                            debug > 2, &line_pt);
  // Allow cheat_allowance off the new error
  new_error -= cheat_allowance;
  double old_angle = BaselineAngle();
  double new_angle = direction.angle();
  if (debug > 1) {
    tprintf("Constrained error = %g, original = %g",
            new_error, baseline_error_);
    tprintf(" angles = %g, %g, delta=%g vs threshold %g\n",
            old_angle, new_angle,
            new_angle - old_angle, kMaxSkewDeviation);
  }
  bool new_good_baseline = new_error <= max_baseline_error_ &&
      (cheat_allowance > 0.0 || fitter_.SufficientPointsForIndependentFit());
  // The new will replace the old if any are true:
  // 1. the new error is better
  // 2. the old is NOT good, but the new is
  // 3. there is a wild angular difference between them (assuming that the new
  //    is a better guess at the angle.)
  if (new_error <= baseline_error_ ||
      (!good_baseline_ && new_good_baseline) ||
      fabs(new_angle - old_angle) > kMaxSkewDeviation) {
    baseline_error_ = new_error;
    baseline_pt1_ = line_pt;
    baseline_pt2_ = baseline_pt1_ + direction;
    good_baseline_ = new_good_baseline;
    if (debug > 1) {
      tprintf("Replacing with constrained baseline, good = %d\n",
              good_baseline_);
    }
  } else if (debug > 1) {
    tprintf("Keeping old baseline\n");
  }
}