/usr/include/tesseract/colpartition.h is in libtesseract-dev 3.02.01-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | ///////////////////////////////////////////////////////////////////////
// File: colpartition.h
// Description: Class to hold partitions of the page that correspond
// roughly to text lines.
// Author: Ray Smith
// Created: Thu Aug 14 10:50:01 PDT 2008
//
// (C) Copyright 2008, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
#ifndef TESSERACT_TEXTORD_COLPARTITION_H__
#define TESSERACT_TEXTORD_COLPARTITION_H__
#include "bbgrid.h"
#include "blobbox.h" // For BlobRegionType.
#include "ndminx.h"
#include "ocrblock.h"
#include "rect.h" // For TBOX.
#include "scrollview.h"
#include "tabfind.h" // For WidthCallback.
#include "tabvector.h" // For BLOBNBOX_CLIST.
namespace tesseract {
// Number of colors in the color1, color2 arrays.
const int kRGBRMSColors = 4;
class ColPartition;
class ColPartitionSet;
class ColPartitionGrid;
class WorkingPartSet;
class WorkingPartSet_LIST;
// An enum to indicate how a partition sits on the columns.
// The order of flowing/heading/pullout must be kept consistent with
// PolyBlockType.
enum ColumnSpanningType {
CST_NOISE, // Strictly between columns.
CST_FLOWING, // Strictly within a single column.
CST_HEADING, // Spans multiple columns.
CST_PULLOUT, // Touches multiple columns, but doesn't span them.
CST_COUNT // Number of entries.
};
ELIST2IZEH(ColPartition)
CLISTIZEH(ColPartition)
/**
* ColPartition is a partition of a horizontal slice of the page.
* It starts out as a collection of blobs at a particular y-coord in the grid,
* but ends up (after merging and uniquing) as an approximate text line.
* ColPartitions are also used to hold a partitioning of the page into
* columns, each representing one column. Although a ColPartition applies
* to a given y-coordinate range, eventually, a ColPartitionSet of ColPartitions
* emerges, which represents the columns over a wide y-coordinate range.
*/
class ColPartition : public ELIST2_LINK {
public:
ColPartition() {
// This empty constructor is here only so that the class can be ELISTIZED.
// TODO(rays) change deep_copy in elst.h line 955 to take a callback copier
// and eliminate CLASSNAME##_copier.
}
/**
* @param blob_type is the blob_region_type_ of the blobs in this partition.
* @param vertical is the direction of logical vertical on the possibly skewed image.
*/
ColPartition(BlobRegionType blob_type, const ICOORD& vertical);
/**
* Constructs a fake ColPartition with no BLOBNBOXes to represent a
* horizontal or vertical line, given a type and a bounding box.
*/
static ColPartition* MakeLinePartition(BlobRegionType blob_type,
const ICOORD& vertical,
int left, int bottom,
int right, int top);
// Constructs and returns a fake ColPartition with a single fake BLOBNBOX,
// all made from a single TBOX.
// WARNING: Despite being on C_LISTs, the BLOBNBOX owns the C_BLOB and
// the ColPartition owns the BLOBNBOX!!!
// Call DeleteBoxes before deleting the ColPartition.
static ColPartition* FakePartition(const TBOX& box,
PolyBlockType block_type,
BlobRegionType blob_type,
BlobTextFlowType flow);
// Constructs and returns a ColPartition with the given real BLOBNBOX,
// and sets it up to be a "big" partition (single-blob partition bigger
// than the surrounding text that may be a dropcap, two or more vertically
// touching characters, or some graphic element.
// If the given list is not NULL, the partition is also added to the list.
static ColPartition* MakeBigPartition(BLOBNBOX* box,
ColPartition_LIST* big_part_list);
~ColPartition();
// Simple accessors.
const TBOX& bounding_box() const {
return bounding_box_;
}
int left_margin() const {
return left_margin_;
}
void set_left_margin(int margin) {
left_margin_ = margin;
}
int right_margin() const {
return right_margin_;
}
void set_right_margin(int margin) {
right_margin_ = margin;
}
int median_top() const {
return median_top_;
}
int median_bottom() const {
return median_bottom_;
}
int median_left() const {
return median_left_;
}
int median_right() const {
return median_right_;
}
int median_size() const {
return median_size_;
}
void set_median_size(int size) {
median_size_ = size;
}
int median_width() const {
return median_width_;
}
void set_median_width(int width) {
median_width_ = width;
}
BlobRegionType blob_type() const {
return blob_type_;
}
void set_blob_type(BlobRegionType t) {
blob_type_ = t;
}
BlobTextFlowType flow() const {
return flow_;
}
void set_flow(BlobTextFlowType f) {
flow_ = f;
}
int good_blob_score() const {
return good_blob_score_;
}
bool good_width() const {
return good_width_;
}
bool good_column() const {
return good_column_;
}
bool left_key_tab() const {
return left_key_tab_;
}
int left_key() const {
return left_key_;
}
bool right_key_tab() const {
return right_key_tab_;
}
int right_key() const {
return right_key_;
}
PolyBlockType type() const {
return type_;
}
void set_type(PolyBlockType t) {
type_ = t;
}
BLOBNBOX_CLIST* boxes() {
return &boxes_;
}
int boxes_count() const {
return boxes_.length();
}
void set_vertical(const ICOORD& v) {
vertical_ = v;
}
ColPartition_CLIST* upper_partners() {
return &upper_partners_;
}
ColPartition_CLIST* lower_partners() {
return &lower_partners_;
}
void set_working_set(WorkingPartSet* working_set) {
working_set_ = working_set;
}
bool block_owned() const {
return block_owned_;
}
void set_block_owned(bool owned) {
block_owned_ = owned;
}
bool desperately_merged() const {
return desperately_merged_;
}
ColPartitionSet* column_set() const {
return column_set_;
}
void set_side_step(int step) {
side_step_ = step;
}
int bottom_spacing() const {
return bottom_spacing_;
}
void set_bottom_spacing(int spacing) {
bottom_spacing_ = spacing;
}
int top_spacing() const {
return top_spacing_;
}
void set_top_spacing(int spacing) {
top_spacing_ = spacing;
}
void set_table_type() {
if (type_ != PT_TABLE) {
type_before_table_ = type_;
type_ = PT_TABLE;
}
}
void clear_table_type() {
if (type_ == PT_TABLE)
type_ = type_before_table_;
}
bool inside_table_column() {
return inside_table_column_;
}
void set_inside_table_column(bool val) {
inside_table_column_ = val;
}
ColPartition* nearest_neighbor_above() const {
return nearest_neighbor_above_;
}
void set_nearest_neighbor_above(ColPartition* part) {
nearest_neighbor_above_ = part;
}
ColPartition* nearest_neighbor_below() const {
return nearest_neighbor_below_;
}
void set_nearest_neighbor_below(ColPartition* part) {
nearest_neighbor_below_ = part;
}
int space_above() const {
return space_above_;
}
void set_space_above(int space) {
space_above_ = space;
}
int space_below() const {
return space_below_;
}
void set_space_below(int space) {
space_below_ = space;
}
int space_to_left() const {
return space_to_left_;
}
void set_space_to_left(int space) {
space_to_left_ = space;
}
int space_to_right() const {
return space_to_right_;
}
void set_space_to_right(int space) {
space_to_right_ = space;
}
uinT8* color1() {
return color1_;
}
uinT8* color2() {
return color2_;
}
bool owns_blobs() const {
return owns_blobs_;
}
void set_owns_blobs(bool owns_blobs) {
// Do NOT change ownership flag when there are blobs in the list.
// Immediately set the ownership flag when creating copies.
ASSERT_HOST(boxes_.empty());
owns_blobs_ = owns_blobs;
}
// Inline quasi-accessors that require some computation.
// Returns the middle y-coord of the bounding box.
int MidY() const {
return (bounding_box_.top() + bounding_box_.bottom()) / 2;
}
// Returns the middle y-coord of the median top and bottom.
int MedianY() const {
return (median_top_ + median_bottom_) / 2;
}
// Returns the middle x-coord of the bounding box.
int MidX() const {
return (bounding_box_.left() + bounding_box_.right()) / 2;
}
// Returns the sort key at any given x,y.
int SortKey(int x, int y) const {
return TabVector::SortKey(vertical_, x, y);
}
// Returns the x corresponding to the sortkey, y pair.
int XAtY(int sort_key, int y) const {
return TabVector::XAtY(vertical_, sort_key, y);
}
// Returns the x difference between the two sort keys.
int KeyWidth(int left_key, int right_key) const {
return (right_key - left_key) / vertical_.y();
}
// Returns the column width between the left and right keys.
int ColumnWidth() const {
return KeyWidth(left_key_, right_key_);
}
// Returns the sort key of the box left edge.
int BoxLeftKey() const {
return SortKey(bounding_box_.left(), MidY());
}
// Returns the sort key of the box right edge.
int BoxRightKey() const {
return SortKey(bounding_box_.right(), MidY());
}
// Returns the left edge at the given y, using the sort key.
int LeftAtY(int y) const {
return XAtY(left_key_, y);
}
// Returns the right edge at the given y, using the sort key.
int RightAtY(int y) const {
return XAtY(right_key_, y);
}
// Returns true if the right edge of this is to the left of the right
// edge of other.
bool IsLeftOf(const ColPartition& other) const {
return bounding_box_.right() < other.bounding_box_.right();
}
// Returns true if the partition contains the given x coordinate at the y.
bool ColumnContains(int x, int y) const {
return LeftAtY(y) - 1 <= x && x <= RightAtY(y) + 1;
}
// Returns true if there are no blobs in the list.
bool IsEmpty() const {
return boxes_.empty();
}
// Returns true if there is a single blob in the list.
bool IsSingleton() const {
return boxes_.singleton();
}
// Returns true if this and other overlap horizontally by bounding box.
bool HOverlaps(const ColPartition& other) const {
return bounding_box_.x_overlap(other.bounding_box_);
}
// Returns true if this and other's bounding boxes overlap vertically.
// TODO(rays) Make HOverlaps and VOverlaps truly symmetric.
bool VOverlaps(const ColPartition& other) const {
return bounding_box_.y_gap(other.bounding_box_) < 0;
}
// Returns the vertical overlap (by median) of this and other.
// WARNING! Only makes sense on horizontal partitions!
int VCoreOverlap(const ColPartition& other) const {
return MIN(median_top_, other.median_top_) -
MAX(median_bottom_, other.median_bottom_);
}
// Returns the horizontal overlap (by median) of this and other.
// WARNING! Only makes sense on vertical partitions!
int HCoreOverlap(const ColPartition& other) const {
return MIN(median_right_, other.median_right_) -
MAX(median_left_, other.median_left_);
}
// Returns true if this and other overlap significantly vertically.
// WARNING! Only makes sense on horizontal partitions!
bool VSignificantCoreOverlap(const ColPartition& other) const {
int overlap = VCoreOverlap(other);
int height = MIN(median_top_ - median_bottom_,
other.median_top_ - other.median_bottom_);
return overlap * 3 > height;
}
// Returns true if this and other can be combined without putting a
// horizontal step in either left or right edge of the resulting block.
bool WithinSameMargins(const ColPartition& other) const {
return left_margin_ <= other.bounding_box_.left() &&
bounding_box_.left() >= other.left_margin_ &&
bounding_box_.right() <= other.right_margin_ &&
right_margin_ >= other.bounding_box_.right();
}
// Returns true if the region types (aligned_text_) match.
// Lines never match anything, as they should never be merged or chained.
bool TypesMatch(const ColPartition& other) const {
return TypesMatch(blob_type_, other.blob_type_);
}
static bool TypesMatch(BlobRegionType type1, BlobRegionType type2) {
return (type1 == type2 || type1 == BRT_UNKNOWN || type2 == BRT_UNKNOWN) &&
!BLOBNBOX::IsLineType(type1) && !BLOBNBOX::IsLineType(type2);
}
// Returns true if the types are similar to each other.
static bool TypesSimilar(PolyBlockType type1, PolyBlockType type2) {
return (type1 == type2 ||
(type1 == PT_FLOWING_TEXT && type2 == PT_INLINE_EQUATION) ||
(type2 == PT_FLOWING_TEXT && type1 == PT_INLINE_EQUATION));
}
// Returns true if partitions is of horizontal line type
bool IsLineType() const {
return PTIsLineType(type_);
}
// Returns true if partitions is of image type
bool IsImageType() const {
return PTIsImageType(type_);
}
// Returns true if partitions is of text type
bool IsTextType() const {
return PTIsTextType(type_);
}
// Returns true if the partition is of an exclusively vertical type.
bool IsVerticalType() const {
return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE;
}
// Returns true if the partition is of a definite horizontal type.
bool IsHorizontalType() const {
return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE;
}
// Returns true is the partition is of a type that cannot be merged.
bool IsUnMergeableType() const {
return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE;
}
// Returns true if this partition is a vertical line
// TODO(nbeato): Use PartitionType enum when Ray's code is submitted.
bool IsVerticalLine() const {
return IsVerticalType() && IsLineType();
}
// Returns true if this partition is a horizontal line
// TODO(nbeato): Use PartitionType enum when Ray's code is submitted.
bool IsHorizontalLine() const {
return IsHorizontalType() && IsLineType();
}
// Adds the given box to the partition, updating the partition bounds.
// The list of boxes in the partition is updated, ensuring that no box is
// recorded twice, and the boxes are kept in increasing left position.
void AddBox(BLOBNBOX* box);
// Removes the given box from the partition, updating the bounds.
void RemoveBox(BLOBNBOX* box);
// Returns the tallest box in the partition, as measured perpendicular to the
// presumed flow of text.
BLOBNBOX* BiggestBox();
// Returns the bounding box excluding the given box.
TBOX BoundsWithoutBox(BLOBNBOX* box);
// Claims the boxes in the boxes_list by marking them with a this owner
// pointer.
void ClaimBoxes();
// NULL the owner of the blobs in this partition, so they can be deleted
// independently of the ColPartition.
void DisownBoxes();
// Delete the boxes that this partition owns.
void DeleteBoxes();
// Reflects the partition in the y-axis, assuming that its blobs have
// already been done. Corrects only a limited part of the members, since
// this function is assumed to be used shortly after initial creation, which
// is before a lot of the members are used.
void ReflectInYAxis();
// Returns true if this is a legal partition - meaning that the conditions
// left_margin <= bounding_box left
// left_key <= bounding box left key
// bounding box left <= bounding box right
// and likewise for right margin and key
// are all met.
bool IsLegal();
// Returns true if the left and right edges are approximately equal.
bool MatchingColumns(const ColPartition& other) const;
// Returns true if the colors match for two text partitions.
bool MatchingTextColor(const ColPartition& other) const;
// Returns true if the sizes match for two text partitions,
// taking orientation into account
bool MatchingSizes(const ColPartition& other) const;
// Returns true if there is no tabstop violation in merging this and other.
bool ConfirmNoTabViolation(const ColPartition& other) const;
// Returns true if other has a similar stroke width to this.
bool MatchingStrokeWidth(const ColPartition& other,
double fractional_tolerance,
double constant_tolerance) const;
// Returns true if candidate is an acceptable diacritic base char merge
// with this as the diacritic.
bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const;
// Sets the sort key using either the tab vector, or the bounding box if
// the tab vector is NULL. If the tab_vector lies inside the bounding_box,
// use the edge of the box as a key any way.
void SetLeftTab(const TabVector* tab_vector);
void SetRightTab(const TabVector* tab_vector);
// Copies the left/right tab from the src partition, but if take_box is
// true, copies the box instead and uses that as a key.
void CopyLeftTab(const ColPartition& src, bool take_box);
void CopyRightTab(const ColPartition& src, bool take_box);
// Returns the left rule line x coord of the leftmost blob.
int LeftBlobRule() const;
// Returns the right rule line x coord of the rightmost blob.
int RightBlobRule() const;
// Returns the density value for a particular BlobSpecialTextType.
float SpecialBlobsDensity(const BlobSpecialTextType type) const;
// Returns the number of blobs for a particular BlobSpecialTextType.
int SpecialBlobsCount(const BlobSpecialTextType type);
// Set the density value for a particular BlobSpecialTextType, should ONLY be
// used for debugging or testing. In production code, use
// ComputeSpecialBlobsDensity instead.
void SetSpecialBlobsDensity(
const BlobSpecialTextType type, const float density);
// Compute the SpecialTextType density of blobs, where we assume
// that the SpecialTextType in the boxes_ has been set.
void ComputeSpecialBlobsDensity();
// Add a partner above if upper, otherwise below.
// Add them uniquely and keep the list sorted by box left.
// Partnerships are added symmetrically to partner and this.
void AddPartner(bool upper, ColPartition* partner);
// Removes the partner from this, but does not remove this from partner.
// This asymmetric removal is so as not to mess up the iterator that is
// working on partner's partner list.
void RemovePartner(bool upper, ColPartition* partner);
// Returns the partner if the given partner is a singleton, otherwise NULL.
ColPartition* SingletonPartner(bool upper);
// Merge with the other partition and delete it.
void Absorb(ColPartition* other, WidthCallback* cb);
// Returns true if the overlap between this and the merged pair of
// merge candidates is sufficiently trivial to be allowed.
// The merged box can graze the edge of this by the ok_box_overlap
// if that exceeds the margin to the median top and bottom.
bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2,
int ok_box_overlap, bool debug);
// Find the blob at which to split this to minimize the overlap with the
// given box. Returns the first blob to go in the second partition.
BLOBNBOX* OverlapSplitBlob(const TBOX& box);
// Split this partition keeping the first half in this and returning
// the second half.
// Splits by putting the split_blob and the blobs that follow
// in the second half, and the rest in the first half.
ColPartition* SplitAtBlob(BLOBNBOX* split_blob);
// Splits this partition at the given x coordinate, returning the right
// half and keeping the left half in this.
ColPartition* SplitAt(int split_x);
// Recalculates all the coordinate limits of the partition.
void ComputeLimits();
// Returns the number of boxes that overlap the given box.
int CountOverlappingBoxes(const TBOX& box);
// Computes and sets the type_, first_column_, last_column_ and column_set_.
// resolution refers to the ppi resolution of the image.
void SetPartitionType(int resolution, ColPartitionSet* columns);
// Returns the PartitionType from the current BlobRegionType and a column
// flow spanning type ColumnSpanningType, generated by
// ColPartitionSet::SpanningType, that indicates how the partition sits
// in the columns.
PolyBlockType PartitionType(ColumnSpanningType flow) const;
// Returns the first and last column touched by this partition.
// resolution refers to the ppi resolution of the image.
void ColumnRange(int resolution, ColPartitionSet* columns,
int* first_col, int* last_col);
// Sets the internal flags good_width_ and good_column_.
void SetColumnGoodness(WidthCallback* cb);
// Determines whether the blobs in this partition mostly represent
// a leader (fixed pitch sequence) and sets the member blobs accordingly.
// Note that height is assumed to have been tested elsewhere, and that this
// function will find most fixed-pitch text as leader without a height filter.
// Leader detection is limited to sequences of identical width objects,
// such as .... or ----, so patterns, such as .-.-.-.-. will not be found.
bool MarkAsLeaderIfMonospaced();
// Given the result of TextlineProjection::EvaluateColPartition, (positive for
// horizontal text, negative for vertical text, and near zero for non-text),
// sets the blob_type_ and flow_ for this partition to indicate whether it
// is strongly or weakly vertical or horizontal text, or non-text.
void SetRegionAndFlowTypesFromProjectionValue(int value);
// Sets all blobs with the partition blob type and flow, but never overwrite
// leader blobs, as we need to be able to identify them later.
void SetBlobTypes();
// Returns true if a decent baseline can be fitted through the blobs.
// Works for both horizontal and vertical text.
bool HasGoodBaseline();
// Adds this ColPartition to a matching WorkingPartSet if one can be found,
// otherwise starts a new one in the appropriate column, ending the previous.
void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright,
int resolution, ColPartition_LIST* used_parts,
WorkingPartSet_LIST* working_set);
// From the given block_parts list, builds one or more BLOCKs and
// corresponding TO_BLOCKs, such that the line spacing is uniform in each.
// Created blocks are appended to the end of completed_blocks and to_blocks.
// The used partitions are put onto used_parts, as they may still be referred
// to in the partition grid. bleft, tright and resolution are the bounds
// and resolution of the original image.
static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright,
int resolution,
ColPartition_LIST* block_parts,
ColPartition_LIST* used_parts,
BLOCK_LIST* completed_blocks,
TO_BLOCK_LIST* to_blocks);
// Constructs a block from the given list of partitions.
// Arguments are as LineSpacingBlocks above.
static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright,
ColPartition_LIST* block_parts,
ColPartition_LIST* used_parts);
// Constructs a block from the given list of vertical text partitions.
// Currently only creates rectangular blocks.
static TO_BLOCK* MakeVerticalTextBlock(const ICOORD& bleft,
const ICOORD& tright,
ColPartition_LIST* block_parts,
ColPartition_LIST* used_parts);
// Returns a copy of everything except the list of boxes. The resulting
// ColPartition is only suitable for keeping in a column candidate list.
ColPartition* ShallowCopy() const;
// Returns a copy of everything with a shallow copy of the blobs.
// The blobs are still owned by their original parent, so they are
// treated as read-only.
ColPartition* CopyButDontOwnBlobs();
// Provides a color for BBGrid to draw the rectangle.
ScrollView::Color BoxColor() const;
// Prints debug information on this.
void Print() const;
// Prints debug information on the colors.
void PrintColors();
// Sets the types of all partitions in the run to be the max of the types.
void SmoothPartnerRun(int working_set_count);
// Cleans up the partners of the given type so that there is at most
// one partner. This makes block creation simpler.
// If get_desperate is true, goes to more desperate merge methods
// to merge flowing text before breaking partnerships.
void RefinePartners(PolyBlockType type, bool get_desparate,
ColPartitionGrid* grid);
// Returns true if this column partition is in the same column as
// part. This function will only work after the SetPartitionType function
// has been called on both column partitions. This is useful for
// doing a SideSearch when you want things in the same page column.
bool IsInSameColumnAs(const ColPartition& part) const;
// Sets the column bounds. Primarily used in testing.
void set_first_column(int column) {
first_column_ = column;
}
void set_last_column(int column) {
last_column_ = column;
}
private:
// enum to refer to the entries in a neigbourhood of lines.
// Used by SmoothSpacings to test for blips with OKSpacingBlip.
enum SpacingNeighbourhood {
PN_ABOVE2,
PN_ABOVE1,
PN_UPPER,
PN_LOWER,
PN_BELOW1,
PN_BELOW2,
PN_COUNT
};
// Cleans up the partners above if upper is true, else below.
// If get_desperate is true, goes to more desperate merge methods
// to merge flowing text before breaking partnerships.
void RefinePartnersInternal(bool upper, bool get_desperate,
ColPartitionGrid* grid);
// Restricts the partners to only desirable types. For text and BRT_HLINE this
// means the same type_ , and for image types it means any image type.
void RefinePartnersByType(bool upper, ColPartition_CLIST* partners);
// Remove transitive partnerships: this<->a, and a<->b and this<->b.
// Gets rid of this<->b, leaving a clean chain.
// Also if we have this<->a and a<->this, then gets rid of this<->a, as
// this has multiple partners.
void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners);
// If multiple text partners can be merged, then do so.
// If desperate is true, then an increase in overlap with the merge is
// allowed. If the overlap increases, then the desperately_merged_ flag
// is set, indicating that the textlines probably need to be regenerated
// by aggressive line fitting/splitting, as there are probably vertically
// joined blobs that cross textlines.
void RefineTextPartnersByMerge(bool upper, bool desperate,
ColPartition_CLIST* partners,
ColPartitionGrid* grid);
// Keep the partner with the biggest overlap.
void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners);
// Return true if bbox belongs better in this than other.
bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other);
// Smoothes the spacings in the list into groups of equal linespacing.
// resolution is the resolution of the original image, used as a basis
// for thresholds in change of spacing. page_height is in pixels.
static void SmoothSpacings(int resolution, int page_height,
ColPartition_LIST* parts);
// Returns true if the parts array of pointers to partitions matches the
// condition for a spacing blip. See SmoothSpacings for what this means
// and how it is used.
static bool OKSpacingBlip(int resolution, int median_spacing,
ColPartition** parts);
// Returns true if both the top and bottom spacings of this match the given
// spacing to within suitable margins dictated by the image resolution.
bool SpacingEqual(int spacing, int resolution) const;
// Returns true if both the top and bottom spacings of this and other
// match to within suitable margins dictated by the image resolution.
bool SpacingsEqual(const ColPartition& other, int resolution) const;
// Returns true if the sum spacing of this and other match the given
// spacing (or twice the given spacing) to within a suitable margin dictated
// by the image resolution.
bool SummedSpacingOK(const ColPartition& other,
int spacing, int resolution) const;
// Returns a suitable spacing margin that can be applied to bottoms of
// text lines, based on the resolution and the stored side_step_.
int BottomSpacingMargin(int resolution) const;
// Returns a suitable spacing margin that can be applied to tops of
// text lines, based on the resolution and the stored side_step_.
int TopSpacingMargin(int resolution) const;
// Returns true if the median text sizes of this and other agree to within
// a reasonable multiplicative factor.
bool SizesSimilar(const ColPartition& other) const;
// Computes and returns in start, end a line segment formed from a
// forwards-iterated group of left edges of partitions that satisfy the
// condition that the rightmost left margin is to the left of the
// leftmost left bounding box edge.
// TODO(rays) Not good enough. Needs improving to tightly wrap text in both
// directions, and to loosely wrap images.
static void LeftEdgeRun(ColPartition_IT* part_it,
ICOORD* start, ICOORD* end);
// Computes and returns in start, end a line segment formed from a
// backwards-iterated group of right edges of partitions that satisfy the
// condition that the leftmost right margin is to the right of the
// rightmost right bounding box edge.
// TODO(rays) Not good enough. Needs improving to tightly wrap text in both
// directions, and to loosely wrap images.
static void RightEdgeRun(ColPartition_IT* part_it,
ICOORD* start, ICOORD* end);
// The margins are determined by the position of the nearest vertically
// overlapping neighbour to the side. They indicate the maximum extent
// that the block/column may be extended without touching something else.
// Leftmost coordinate that the region may occupy over the y limits.
int left_margin_;
// Rightmost coordinate that the region may occupy over the y limits.
int right_margin_;
// Bounding box of all blobs in the partition.
TBOX bounding_box_;
// Median top and bottom of blobs in this partition.
int median_bottom_;
int median_top_;
// Median height of blobs in this partition.
// TODO(rays) rename median_height_.
int median_size_;
// Median left and right of blobs in this partition.
int median_left_;
int median_right_;
// Median width of blobs in this partition.
int median_width_;
// blob_region_type_ for the blobs in this partition.
BlobRegionType blob_type_;
BlobTextFlowType flow_; // Quality of text flow.
// Total of GoodTextBlob results for all blobs in the partition.
int good_blob_score_;
// True if this partition has a common width.
bool good_width_;
// True if this is a good column candidate.
bool good_column_;
// True if the left_key_ is from a tab vector.
bool left_key_tab_;
// True if the right_key_ is from a tab vector.
bool right_key_tab_;
// Left and right sort keys for the edges of the partition.
// If the respective *_key_tab_ is true then this key came from a tab vector.
// If not, then the class promises to keep the key equal to the sort key
// for the respective edge of the bounding box at the MidY, so that
// LeftAtY and RightAtY always returns an x coordinate on the line parallel
// to vertical_ through the bounding box edge at MidY.
int left_key_;
int right_key_;
// Type of this partition after looking at its relation to the columns.
PolyBlockType type_;
// All boxes in the partition stored in increasing left edge coordinate.
BLOBNBOX_CLIST boxes_;
// The global vertical skew direction.
ICOORD vertical_;
// The partitions above that matched this.
ColPartition_CLIST upper_partners_;
// The partitions below that matched this.
ColPartition_CLIST lower_partners_;
// The WorkingPartSet it lives in while blocks are being made.
WorkingPartSet* working_set_;
// Flag is true when AddBox is sorting vertically, false otherwise.
bool last_add_was_vertical_;
// True when the partition's ownership has been taken from the grid and
// placed in a working set, or, after that, in the good_parts_ list.
bool block_owned_;
// Flag to indicate that this partition was subjected to a desperate merge,
// and therefore the textlines need rebuilding.
bool desperately_merged_;
// The first and last column that this partition applies to.
// Flowing partitions (see type_) will have an equal first and last value
// of the form 2n + 1, where n is the zero-based index into the partitions
// in column_set_. (See ColPartitionSet::GetColumnByIndex).
// Heading partitions will have unequal values of the same form.
// Pullout partitions will have equal values, but may have even values,
// indicating placement between columns.
int first_column_;
int last_column_;
// Column_set_ is the column layout applicable to this ColPartition.
ColPartitionSet* column_set_;
// Linespacing data.
int side_step_; // Median y-shift to next blob on same line.
int top_spacing_; // Line spacing from median_top_.
int bottom_spacing_; // Line spacing from median_bottom_.
// Type of this partition before considering it as a table cell. This is
// used to revert the type if a partition is first marked as a table cell but
// later filtering steps decide it does not belong to a table
PolyBlockType type_before_table_;
bool inside_table_column_; // Check whether the current partition has been
// assigned to a table column
// Nearest neighbor above with major x-overlap
ColPartition* nearest_neighbor_above_;
// Nearest neighbor below with major x-overlap
ColPartition* nearest_neighbor_below_;
int space_above_; // Distance from nearest_neighbor_above
int space_below_; // Distance from nearest_neighbor_below
int space_to_left_; // Distance from the left edge of the column
int space_to_right_; // Distance from the right edge of the column
// Color foreground/background data.
uinT8 color1_[kRGBRMSColors];
uinT8 color2_[kRGBRMSColors];
bool owns_blobs_; // Does the partition own its blobs?
// The density of special blobs.
float special_blobs_densities_[BSTT_COUNT];
};
// Typedef it now in case it becomes a class later.
typedef GridSearch<ColPartition,
ColPartition_CLIST,
ColPartition_C_IT> ColPartitionGridSearch;
} // namespace tesseract.
#endif // TESSERACT_TEXTORD_COLPARTITION_H__
|