tesseract  5.0.0-alpha-619-ge9db
boxword.cpp
Go to the documentation of this file.
1 // File: boxword.cpp
3 // Description: Class to represent the bounding boxes of the output.
4 // Author: Ray Smith
5 //
6 // (C) Copyright 2010, Google Inc.
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
18 
19 #include "blobs.h"
20 #include "boxword.h"
21 #include "host.h" // for NearlyEqual
22 #include "normalis.h"
23 #include "ocrblock.h"
24 #include "pageres.h"
25 
26 namespace tesseract {
27 
28 // Clip output boxes to input blob boxes for bounds that are within this
29 // tolerance. Otherwise, the blob may be chopped and we have to just use
30 // the word bounding box.
31 const int kBoxClipTolerance = 2;
32 
33 BoxWord::BoxWord() : length_(0) {
34 }
35 
37  CopyFrom(src);
38 }
39 
41  CopyFrom(src);
42  return *this;
43 }
44 
45 void BoxWord::CopyFrom(const BoxWord& src) {
46  bbox_ = src.bbox_;
47  length_ = src.length_;
48  boxes_.clear();
49  boxes_.reserve(length_);
50  for (int i = 0; i < length_; ++i)
51  boxes_.push_back(src.boxes_[i]);
52 }
53 
54 // Factory to build a BoxWord from a TWERD using the DENORMs on each blob to
55 // switch back to original image coordinates.
57  auto* boxword = new BoxWord();
58  // Count the blobs.
59  boxword->length_ = tessword->NumBlobs();
60  // Allocate memory.
61  boxword->boxes_.reserve(boxword->length_);
62 
63  for (int b = 0; b < boxword->length_; ++b) {
64  TBLOB* tblob = tessword->blobs[b];
65  TBOX blob_box;
66  for (TESSLINE* outline = tblob->outlines; outline != nullptr;
67  outline = outline->next) {
68  EDGEPT* edgept = outline->loop;
69  // Iterate over the edges.
70  do {
71  if (!edgept->IsHidden() || !edgept->prev->IsHidden()) {
72  ICOORD pos(edgept->pos.x, edgept->pos.y);
73  TPOINT denormed;
74  tblob->denorm().DenormTransform(nullptr, edgept->pos, &denormed);
75  pos.set_x(denormed.x);
76  pos.set_y(denormed.y);
77  TBOX pt_box(pos, pos);
78  blob_box += pt_box;
79  }
80  edgept = edgept->next;
81  } while (edgept != outline->loop);
82  }
83  boxword->boxes_.push_back(blob_box);
84  }
85  boxword->ComputeBoundingBox();
86  return boxword;
87 }
88 
89 // Clean up the bounding boxes from the polygonal approximation by
90 // expanding slightly, then clipping to the blobs from the original_word
91 // that overlap. If not null, the block provides the inverse rotation.
92 void BoxWord::ClipToOriginalWord(const BLOCK* block, WERD* original_word) {
93  for (int i = 0; i < length_; ++i) {
94  TBOX box = boxes_[i];
95  // Expand by a single pixel, as the poly approximation error is 1 pixel.
96  box = TBOX(box.left() - 1, box.bottom() - 1,
97  box.right() + 1, box.top() + 1);
98  // Now find the original box that matches.
99  TBOX original_box;
100  C_BLOB_IT b_it(original_word->cblob_list());
101  for (b_it.mark_cycle_pt(); !b_it.cycled_list(); b_it.forward()) {
102  TBOX blob_box = b_it.data()->bounding_box();
103  if (block != nullptr)
104  blob_box.rotate(block->re_rotation());
105  if (blob_box.major_overlap(box)) {
106  original_box += blob_box;
107  }
108  }
109  if (!original_box.null_box()) {
110  if (NearlyEqual<int>(original_box.left(), box.left(), kBoxClipTolerance))
111  box.set_left(original_box.left());
112  if (NearlyEqual<int>(original_box.right(), box.right(),
114  box.set_right(original_box.right());
115  if (NearlyEqual<int>(original_box.top(), box.top(), kBoxClipTolerance))
116  box.set_top(original_box.top());
117  if (NearlyEqual<int>(original_box.bottom(), box.bottom(),
119  box.set_bottom(original_box.bottom());
120  }
121  original_box = original_word->bounding_box();
122  if (block != nullptr)
123  original_box.rotate(block->re_rotation());
124  boxes_[i] = box.intersection(original_box);
125  }
126  ComputeBoundingBox();
127 }
128 
129 // Merges the boxes from start to end, not including end, and deletes
130 // the boxes between start and end.
131 void BoxWord::MergeBoxes(int start, int end) {
132  start = ClipToRange(start, 0, length_);
133  end = ClipToRange(end, 0, length_);
134  if (end <= start + 1)
135  return;
136  for (int i = start + 1; i < end; ++i) {
137  boxes_[start] += boxes_[i];
138  }
139  int shrinkage = end - 1 - start;
140  length_ -= shrinkage;
141  for (int i = start + 1; i < length_; ++i)
142  boxes_[i] = boxes_[i + shrinkage];
143  boxes_.truncate(length_);
144 }
145 
146 // Inserts a new box before the given index.
147 // Recomputes the bounding box.
148 void BoxWord::InsertBox(int index, const TBOX& box) {
149  if (index < length_)
150  boxes_.insert(box, index);
151  else
152  boxes_.push_back(box);
153  length_ = boxes_.size();
154  ComputeBoundingBox();
155 }
156 
157 // Changes the box at the given index to the new box.
158 // Recomputes the bounding box.
159 void BoxWord::ChangeBox(int index, const TBOX& box) {
160  boxes_[index] = box;
161  ComputeBoundingBox();
162 }
163 
164 // Deletes the box with the given index, and shuffles up the rest.
165 // Recomputes the bounding box.
166 void BoxWord::DeleteBox(int index) {
167  ASSERT_HOST(0 <= index && index < length_);
168  boxes_.remove(index);
169  --length_;
170  ComputeBoundingBox();
171 }
172 
173 // Deletes all the boxes stored in BoxWord.
175  length_ = 0;
176  boxes_.clear();
177  bbox_ = TBOX();
178 }
179 
180 // Computes the bounding box of the word.
181 void BoxWord::ComputeBoundingBox() {
182  bbox_ = TBOX();
183  for (int i = 0; i < length_; ++i)
184  bbox_ += boxes_[i];
185 }
186 
187 // This and other putatively are the same, so call the (permanent) callback
188 // for each blob index where the bounding boxes match.
189 // The callback is deleted on completion.
191  std::function<void(int)> cb) const {
192  for (int i = 0; i < length_ && i < other.NumBlobs(); ++i) {
193  TBOX blob_box = other.blobs[i]->bounding_box();
194  if (blob_box == boxes_[i])
195  cb(i);
196  }
197 }
198 
199 } // namespace tesseract.
TBOX
Definition: cleanapi_test.cc:19
GenericVector::remove
void remove(int index)
Definition: genericvector.h:765
tesseract::BoxWord::BoxWord
BoxWord()
Definition: boxword.cpp:33
ClipToRange
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:106
ICOORD::set_x
void set_x(int16_t xin)
rewrite function
Definition: points.h:60
normalis.h
pageres.h
TBOX::intersection
TBOX intersection(const TBOX &box) const
Definition: rect.cpp:83
host.h
TPOINT
Definition: blobs.h:49
tesseract::BoxWord::DeleteBox
void DeleteBox(int index)
Definition: boxword.cpp:166
tesseract::BoxWord::CopyFromNormalized
static BoxWord * CopyFromNormalized(TWERD *tessword)
Definition: boxword.cpp:56
TWERD
Definition: blobs.h:416
ASSERT_HOST
#define ASSERT_HOST(x)
Definition: errcode.h:87
WERD::bounding_box
TBOX bounding_box() const
Definition: werd.cpp:147
TBLOB::outlines
TESSLINE * outlines
Definition: blobs.h:398
GenericVector::insert
void insert(const T &t, int index)
Definition: genericvector.h:750
TBLOB::denorm
const DENORM & denorm() const
Definition: blobs.h:361
EDGEPT::IsHidden
bool IsHidden() const
Definition: blobs.h:174
ICOORD
integer coordinate
Definition: points.h:30
TESSLINE
Definition: blobs.h:201
TBOX::top
int16_t top() const
Definition: rect.h:57
TBOX::set_top
void set_top(int y)
Definition: rect.h:60
tesseract::BoxWord::ClipToOriginalWord
void ClipToOriginalWord(const BLOCK *block, WERD *original_word)
Definition: boxword.cpp:92
TESSLINE::next
TESSLINE * next
Definition: blobs.h:279
blobs.h
ICOORD::set_y
void set_y(int16_t yin)
rewrite function
Definition: points.h:64
TBOX::rotate
void rotate(const FCOORD &vec)
Definition: rect.h:196
tesseract::BoxWord::CopyFrom
void CopyFrom(const BoxWord &src)
Definition: boxword.cpp:45
WERD::cblob_list
C_BLOB_LIST * cblob_list()
Definition: werd.h:94
EDGEPT::prev
EDGEPT * prev
Definition: blobs.h:191
TBOX::set_right
void set_right(int x)
Definition: rect.h:81
GenericVector::push_back
int push_back(T object)
Definition: genericvector.h:799
BLOCK
Definition: ocrblock.h:28
TPOINT::x
int16_t x
Definition: blobs.h:91
DENORM::DenormTransform
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
Definition: normalis.cpp:389
tesseract::BoxWord::ProcessMatchedBlobs
void ProcessMatchedBlobs(const TWERD &other, std::function< void(int)> cb) const
Definition: boxword.cpp:190
tesseract::kBoxClipTolerance
const int kBoxClipTolerance
Definition: boxword.cpp:31
TPOINT::y
int16_t y
Definition: blobs.h:92
TWERD::blobs
GenericVector< TBLOB * > blobs
Definition: blobs.h:457
TBOX::bottom
int16_t bottom() const
Definition: rect.h:64
tesseract
Definition: baseapi.h:65
GenericVector::reserve
void reserve(int size)
Definition: genericvector.h:679
tesseract::BoxWord::InsertBox
void InsertBox(int index, const TBOX &box)
Definition: boxword.cpp:148
TBLOB
Definition: blobs.h:282
tesseract::BoxWord::ChangeBox
void ChangeBox(int index, const TBOX &box)
Definition: boxword.cpp:159
TBOX::major_overlap
bool major_overlap(const TBOX &box) const
Definition: rect.h:362
WERD
Definition: werd.h:55
GenericVector::truncate
void truncate(int size)
Definition: genericvector.h:132
TBOX::left
int16_t left() const
Definition: rect.h:71
ocrblock.h
GenericVector::clear
void clear()
Definition: genericvector.h:857
TBOX::right
int16_t right() const
Definition: rect.h:78
tesseract::BoxWord::DeleteAllBoxes
void DeleteAllBoxes()
Definition: boxword.cpp:174
EDGEPT
Definition: blobs.h:97
tesseract::BoxWord::operator=
BoxWord & operator=(const BoxWord &src)
Definition: boxword.cpp:40
TBOX::set_bottom
void set_bottom(int y)
Definition: rect.h:67
tesseract::BoxWord::MergeBoxes
void MergeBoxes(int start, int end)
Definition: boxword.cpp:131
BLOCK::re_rotation
FCOORD re_rotation() const
Definition: ocrblock.h:133
GenericVector::size
int size() const
Definition: genericvector.h:71
boxword.h
EDGEPT::pos
TPOINT pos
Definition: blobs.h:184
TWERD::NumBlobs
int NumBlobs() const
Definition: blobs.h:446
EDGEPT::next
EDGEPT * next
Definition: blobs.h:190
TBOX::set_left
void set_left(int x)
Definition: rect.h:74
TBOX
Definition: rect.h:33
tesseract::BoxWord
Definition: boxword.h:36