tesseract v5.3.3.20231005
matrix.h
Go to the documentation of this file.
1/******************************************************************************
2 * File: matrix.h
3 * Description: Generic 2-d array/matrix and banded triangular matrix class.
4 * Author: Ray Smith
5 * TODO(rays) Separate from ratings matrix, which it also contains:
6 *
7 * Description: Ratings matrix class (specialization of banded matrix).
8 * Segmentation search matrix of lists of BLOB_CHOICE.
9 * Author: Mark Seaman, OCR Technology
10 *
11 * (c) Copyright 1990, Hewlett-Packard Company.
12 ** Licensed under the Apache License, Version 2.0 (the "License");
13 ** you may not use this file except in compliance with the License.
14 ** You may obtain a copy of the License at
15 ** http://www.apache.org/licenses/LICENSE-2.0
16 ** Unless required by applicable law or agreed to in writing, software
17 ** distributed under the License is distributed on an "AS IS" BASIS,
18 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 ** See the License for the specific language governing permissions and
20 ** limitations under the License.
21 *
22 *****************************************************************************/
23
24#ifndef TESSERACT_CCSTRUCT_MATRIX_H_
25#define TESSERACT_CCSTRUCT_MATRIX_H_
26
27#include "errcode.h" // for ASSERT_HOST
28#include "helpers.h" // for ReverseN, ClipToRange
29#include "kdpair.h" // for KDPairInc
30#include "points.h" // for ICOORD
31
32#include "serialis.h" // for TFile
33
34#include <algorithm> // for max, min
35#include <cmath> // for sqrt, fabs, isfinite
36#include <cstdint> // for int32_t
37#include <cstdio> // for FILE
38#include <cstring> // for memcpy
39
40namespace tesseract {
41
42class BLOB_CHOICE_LIST;
43class UNICHARSET;
44
45#define NOT_CLASSIFIED static_cast<BLOB_CHOICE_LIST *>(nullptr)
46
47// A generic class to hold a 2-D matrix with entries of type T, but can also
48// act as a base class for other implementations, such as a triangular or
49// banded matrix.
50template <class T>
52public:
53 // Initializes the array size, and empty element, but cannot allocate memory
54 // for the subclasses or initialize because calls to the num_elements
55 // member will be routed to the base class implementation. Subclasses can
56 // either pass the memory in, or allocate after by calling Resize().
57 GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty, T *array)
58 : empty_(empty), dim1_(dim1), dim2_(dim2), array_(array) {
60 }
61 // Original constructor for a full rectangular matrix DOES allocate memory
62 // and initialize it to empty.
63 GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty) : empty_(empty), dim1_(dim1), dim2_(dim2) {
64 int new_size = dim1 * dim2;
65 array_ = new T[new_size];
66 size_allocated_ = new_size;
67 for (int i = 0; i < size_allocated_; ++i) {
68 array_[i] = empty_;
69 }
70 }
71 // Default constructor for array allocation. Use Resize to set the size.
73 : array_(nullptr), empty_(static_cast<T>(0)), dim1_(0), dim2_(0), size_allocated_(0) {}
75 : array_(nullptr), empty_(static_cast<T>(0)), dim1_(0), dim2_(0), size_allocated_(0) {
76 *this = src;
77 }
79 delete[] array_;
80 }
81
82 void operator=(const GENERIC_2D_ARRAY<T> &src) {
83 ResizeNoInit(src.dim1(), src.dim2());
84 int size = num_elements();
85 if (size > 0) {
86 memcpy(array_, src.array_, size * sizeof(array_[0]));
87 }
88 }
89
90 // Reallocates the array to the given size. Does not keep old data, but does
91 // not initialize the array either.
92 // The allocated memory is expanded on the end by pad, allowing deliberate
93 // access beyond the bounds of the array.
94 void ResizeNoInit(int size1, int size2, int pad = 0) {
95 int new_size = size1 * size2 + pad;
96 if (new_size > size_allocated_) {
97 delete[] array_;
98 array_ = new T[new_size];
99 size_allocated_ = new_size;
100 }
101 dim1_ = size1;
102 dim2_ = size2;
103 // Fill the padding data so it isn't uninitialized.
104 for (int i = size1 * size2; i < new_size; ++i) {
105 array_[i] = empty_;
106 }
107 }
108
109 // Reallocate the array to the given size. Does not keep old data.
110 void Resize(int size1, int size2, const T &empty) {
111 empty_ = empty;
112 ResizeNoInit(size1, size2);
113 Clear();
114 }
115
116 // Reallocate the array to the given size, keeping old data.
117 void ResizeWithCopy(int size1, int size2) {
118 if (size1 != dim1_ || size2 != dim2_) {
119 int new_size = size1 * size2;
120 T *new_array = new T[new_size];
121 for (int col = 0; col < size1; ++col) {
122 for (int row = 0; row < size2; ++row) {
123 int old_index = col * dim2() + row;
124 int new_index = col * size2 + row;
125 if (col < dim1_ && row < dim2_) {
126 new_array[new_index] = array_[old_index];
127 } else {
128 new_array[new_index] = empty_;
129 }
130 }
131 }
132 delete[] array_;
133 array_ = new_array;
134 dim1_ = size1;
135 dim2_ = size2;
136 size_allocated_ = new_size;
137 }
138 }
139
140 // Sets all the elements of the array to the empty value.
141 void Clear() {
142 int total_size = num_elements();
143 for (int i = 0; i < total_size; ++i) {
144 array_[i] = empty_;
145 }
146 }
147
148 // Writes to the given file. Returns false in case of error.
149 // Only works with bitwise-serializeable types!
150 bool Serialize(FILE *fp) const {
151 if (!SerializeSize(fp)) {
152 return false;
153 }
154 if (!tesseract::Serialize(fp, &empty_)) {
155 return false;
156 }
157 int size = num_elements();
158 return tesseract::Serialize(fp, &array_[0], size);
159 }
160
161 bool Serialize(TFile *fp) const {
162 if (!SerializeSize(fp)) {
163 return false;
164 }
165 if (!fp->Serialize(&empty_)) {
166 return false;
167 }
168 int size = num_elements();
169 return fp->Serialize(&array_[0], size);
170 }
171
172 // Reads from the given file. Returns false in case of error.
173 // Only works with bitwise-serializeable types!
174 // If swap is true, assumes a big/little-endian swap is needed.
175 bool DeSerialize(bool swap, FILE *fp) {
176 if (!DeSerializeSize(swap, fp)) {
177 return false;
178 }
179 if (!tesseract::DeSerialize(fp, &empty_)) {
180 return false;
181 }
182 if (swap) {
183 ReverseN(&empty_, sizeof(empty_));
184 }
185 int size = num_elements();
186 if (!tesseract::DeSerialize(fp, &array_[0], size)) {
187 return false;
188 }
189 if (swap) {
190 for (int i = 0; i < size; ++i) {
191 ReverseN(&array_[i], sizeof(array_[i]));
192 }
193 }
194 return true;
195 }
196
197 bool DeSerialize(TFile *fp) {
198 return DeSerializeSize(fp) && fp->DeSerialize(&empty_) &&
199 fp->DeSerialize(&array_[0], num_elements());
200 }
201
202 // Writes to the given file. Returns false in case of error.
203 // Assumes a T::Serialize(FILE*) const function.
204 bool SerializeClasses(FILE *fp) const {
205 if (!SerializeSize(fp)) {
206 return false;
207 }
208 if (!empty_.Serialize(fp)) {
209 return false;
210 }
211 int size = num_elements();
212 for (int i = 0; i < size; ++i) {
213 if (!array_[i].Serialize(fp)) {
214 return false;
215 }
216 }
217 return true;
218 }
219
220 // Reads from the given file. Returns false in case of error.
221 // Assumes a T::DeSerialize(bool swap, FILE*) function.
222 // If swap is true, assumes a big/little-endian swap is needed.
223 bool DeSerializeClasses(bool swap, FILE *fp) {
224 if (!DeSerializeSize(swap, fp)) {
225 return false;
226 }
227 if (!empty_.DeSerialize(swap, fp)) {
228 return false;
229 }
230 int size = num_elements();
231 for (int i = 0; i < size; ++i) {
232 if (!array_[i].DeSerialize(swap, fp)) {
233 return false;
234 }
235 }
236 return true;
237 }
238
239 // Provide the dimensions of this rectangular matrix.
240 int dim1() const {
241 return dim1_;
242 }
243 int dim2() const {
244 return dim2_;
245 }
246 // Returns the number of elements in the array.
247 // Banded/triangular matrices may override.
248 virtual int num_elements() const {
249 return dim1_ * dim2_;
250 }
251
252 // Expression to select a specific location in the matrix. The matrix is
253 // stored COLUMN-major, so the left-most index is the most significant.
254 // This allows [][] access to use indices in the same order as (,).
255 virtual int index(int column, int row) const {
256 return (column * dim2_ + row);
257 }
258
259 // Put a list element into the matrix at a specific location.
260 void put(ICOORD pos, const T &thing) {
261 array_[this->index(pos.x(), pos.y())] = thing;
262 }
263 void put(int column, int row, const T &thing) {
264 array_[this->index(column, row)] = thing;
265 }
266
267 // Get the item at a specified location from the matrix.
268 T get(ICOORD pos) const {
269 return array_[this->index(pos.x(), pos.y())];
270 }
271 T get(int column, int row) const {
272 return array_[this->index(column, row)];
273 }
274 // Return a reference to the element at the specified location.
275 const T &operator()(int column, int row) const {
276 return array_[this->index(column, row)];
277 }
278 T &operator()(int column, int row) {
279 return array_[this->index(column, row)];
280 }
281 // Allow access using array[column][row]. NOTE that the indices are
282 // in the same left-to-right order as the () indexing.
283 T *operator[](int column) {
284 return &array_[this->index(column, 0)];
285 }
286 const T *operator[](int column) const {
287 return &array_[this->index(column, 0)];
288 }
289
290 // Adds addend to *this, element-by-element.
291 void operator+=(const GENERIC_2D_ARRAY<T> &addend) {
292 if (dim2_ == addend.dim2_) {
293 // Faster if equal size in the major dimension.
294 int size = std::min(num_elements(), addend.num_elements());
295 for (int i = 0; i < size; ++i) {
296 array_[i] += addend.array_[i];
297 }
298 } else {
299 for (int x = 0; x < dim1_; x++) {
300 for (int y = 0; y < dim2_; y++) {
301 (*this)(x, y) += addend(x, y);
302 }
303 }
304 }
305 }
306 // Subtracts minuend from *this, element-by-element.
307 void operator-=(const GENERIC_2D_ARRAY<T> &minuend) {
308 if (dim2_ == minuend.dim2_) {
309 // Faster if equal size in the major dimension.
310 int size = std::min(num_elements(), minuend.num_elements());
311 for (int i = 0; i < size; ++i) {
312 array_[i] -= minuend.array_[i];
313 }
314 } else {
315 for (int x = 0; x < dim1_; x++) {
316 for (int y = 0; y < dim2_; y++) {
317 (*this)(x, y) -= minuend(x, y);
318 }
319 }
320 }
321 }
322 // Adds addend to all elements.
323 void operator+=(const T &addend) {
324 int size = num_elements();
325 for (int i = 0; i < size; ++i) {
326 array_[i] += addend;
327 }
328 }
329 // Multiplies *this by factor, element-by-element.
330 void operator*=(const T &factor) {
331 int size = num_elements();
332 for (int i = 0; i < size; ++i) {
333 array_[i] *= factor;
334 }
335 }
336 // Clips *this to the given range.
337 void Clip(const T &rangemin, const T &rangemax) {
338 int size = num_elements();
339 for (int i = 0; i < size; ++i) {
340 array_[i] = ClipToRange(array_[i], rangemin, rangemax);
341 }
342 }
343 // Returns true if all elements of *this are within the given range.
344 // Only uses operator<
345 bool WithinBounds(const T &rangemin, const T &rangemax) const {
346 int size = num_elements();
347 for (int i = 0; i < size; ++i) {
348 const T &value = array_[i];
349 if (value < rangemin || rangemax < value) {
350 return false;
351 }
352 }
353 return true;
354 }
355 // Normalize the whole array.
356 double Normalize() {
357 int size = num_elements();
358 if (size <= 0) {
359 return 0.0;
360 }
361 // Compute the mean.
362 double mean = 0.0;
363 for (int i = 0; i < size; ++i) {
364 mean += array_[i];
365 }
366 mean /= size;
367 // Subtract the mean and compute the standard deviation.
368 double sd = 0.0;
369 for (int i = 0; i < size; ++i) {
370 double normed = array_[i] - mean;
371 array_[i] = normed;
372 sd += normed * normed;
373 }
374 sd = sqrt(sd / size);
375 if (sd > 0.0) {
376 // Divide by the sd.
377 for (int i = 0; i < size; ++i) {
378 array_[i] /= sd;
379 }
380 }
381 return sd;
382 }
383
384 // Returns the maximum value of the array.
385 T Max() const {
386 int size = num_elements();
387 if (size <= 0) {
388 return empty_;
389 }
390 // Compute the max.
391 T max_value = array_[0];
392 for (int i = 1; i < size; ++i) {
393 const T &value = array_[i];
394 if (value > max_value) {
395 max_value = value;
396 }
397 }
398 return max_value;
399 }
400
401 // Returns the maximum absolute value of the array.
402 T MaxAbs() const {
403 int size = num_elements();
404 if (size <= 0) {
405 return empty_;
406 }
407 // Compute the max.
408 T max_abs = static_cast<T>(0);
409 for (int i = 0; i < size; ++i) {
410 T value = static_cast<T>(fabs(array_[i]));
411 if (value > max_abs) {
412 max_abs = value;
413 }
414 }
415 return max_abs;
416 }
417
418 // Accumulates the element-wise sums of squares of src into *this.
419 void SumSquares(const GENERIC_2D_ARRAY<T> &src, const T &decay_factor) {
420 T update_factor = 1 - decay_factor;
421 int size = num_elements();
422 for (int i = 0; i < size; ++i) {
423 array_[i] = array_[i] * decay_factor + update_factor * src.array_[i] * src.array_[i];
424 }
425 }
426
427 // Scales each element using the adam algorithm, ie array_[i] by
428 // sqrt(sqsum[i] + epsilon)).
430 const T &epsilon) {
431 int size = num_elements();
432 for (int i = 0; i < size; ++i) {
433 array_[i] += sum.array_[i] / (sqrt(sqsum.array_[i]) + epsilon);
434 }
435 }
436
437 void AssertFinite() const {
438 int size = num_elements();
439 for (int i = 0; i < size; ++i) {
440 ASSERT_HOST(isfinite(array_[i]));
441 }
442 }
443
444 // REGARDLESS OF THE CURRENT DIMENSIONS, treats the data as a
445 // num_dims-dimensional array/tensor with dimensions given by dims, (ordered
446 // from most significant to least significant, the same as standard C arrays)
447 // and moves src_dim to dest_dim, with the initial dest_dim and any dimensions
448 // in between shifted towards the hole left by src_dim. Example:
449 // Current data content: array_=[0, 1, 2, ....119]
450 // perhaps *this may be of dim[40, 3], with values [[0, 1, 2][3, 4, 5]...
451 // but the current dimensions are irrelevant.
452 // num_dims = 4, dims=[5, 4, 3, 2]
453 // src_dim=3, dest_dim=1
454 // tensor=[[[[0, 1][2, 3][4, 5]]
455 // [[6, 7][8, 9][10, 11]]
456 // [[12, 13][14, 15][16, 17]]
457 // [[18, 19][20, 21][22, 23]]]
458 // [[[24, 25]...
459 // output dims =[5, 2, 4, 3]
460 // output tensor=[[[[0, 2, 4][6, 8, 10][12, 14, 16][18, 20, 22]]
461 // [[1, 3, 5][7, 9, 11][13, 15, 17][19, 21, 23]]]
462 // [[[24, 26, 28]...
463 // which is stored in the array_ as:
464 // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 1, 3, 5, 7, 9, 11, 13...]
465 // NOTE: the 2 stored matrix dimensions are simply copied from *this. To
466 // change the dimensions after the transpose, use ResizeNoInit.
467 // Higher dimensions above 2 are strictly the responsibility of the caller.
468 void RotatingTranspose(const int *dims, int num_dims, int src_dim, int dest_dim,
469 GENERIC_2D_ARRAY<T> *result) const {
470 int max_d = std::max(src_dim, dest_dim);
471 int min_d = std::min(src_dim, dest_dim);
472 // In a tensor of shape [d0, d1... min_d, ... max_d, ... dn-2, dn-1], the
473 // ends outside of min_d and max_d are unaffected, with [max_d +1, dn-1]
474 // being contiguous blocks of data that will move together, and
475 // [d0, min_d -1] being replicas of the transpose operation.
476 // num_replicas represents the large dimensions unchanged by the operation.
477 // move_size represents the small dimensions unchanged by the operation.
478 // src_step represents the stride in the src between each adjacent group
479 // in the destination.
480 int num_replicas = 1, move_size = 1, src_step = 1;
481 for (int d = 0; d < min_d; ++d) {
482 num_replicas *= dims[d];
483 }
484 for (int d = max_d + 1; d < num_dims; ++d) {
485 move_size *= dims[d];
486 }
487 for (int d = src_dim + 1; d < num_dims; ++d) {
488 src_step *= dims[d];
489 }
490 if (src_dim > dest_dim) {
491 src_step *= dims[src_dim];
492 }
493 // wrap_size is the size of a single replica, being the amount that is
494 // handled num_replicas times.
495 int wrap_size = move_size;
496 for (int d = min_d; d <= max_d; ++d) {
497 wrap_size *= dims[d];
498 }
499 result->ResizeNoInit(dim1_, dim2_);
500 result->empty_ = empty_;
501 const T *src = array_;
502 T *dest = result->array_;
503 for (int replica = 0; replica < num_replicas; ++replica) {
504 for (int start = 0; start < src_step; start += move_size) {
505 for (int pos = start; pos < wrap_size; pos += src_step) {
506 memcpy(dest, src + pos, sizeof(*dest) * move_size);
507 dest += move_size;
508 }
509 }
510 src += wrap_size;
511 }
512 }
513
514 // Delete objects pointed to by array_[i].
516 int size = num_elements();
517 for (int i = 0; i < size; ++i) {
518 T matrix_cell = array_[i];
519 if (matrix_cell != empty_) {
520 delete matrix_cell;
521 }
522 }
523 }
524
525protected:
526 // Factored helper to serialize the size.
527 bool SerializeSize(FILE *fp) const {
528 uint32_t size = dim1_;
529 if (!tesseract::Serialize(fp, &size)) {
530 return false;
531 }
532 size = dim2_;
533 return tesseract::Serialize(fp, &size);
534 }
535 bool SerializeSize(TFile *fp) const {
536 uint32_t size = dim1_;
537 if (!fp->Serialize(&size)) {
538 return false;
539 }
540 size = dim2_;
541 return fp->Serialize(&size);
542 }
543 // Factored helper to deserialize the size.
544 // If swap is true, assumes a big/little-endian swap is needed.
545 bool DeSerializeSize(bool swap, FILE *fp) {
546 uint32_t size1, size2;
547 if (!tesseract::DeSerialize(fp, &size1)) {
548 return false;
549 }
550 if (!tesseract::DeSerialize(fp, &size2)) {
551 return false;
552 }
553 if (swap) {
554 ReverseN(&size1, sizeof(size1));
555 ReverseN(&size2, sizeof(size2));
556 }
557 // Arbitrarily limit the number of elements to protect against bad data.
558 if (size1 > UINT16_MAX) {
559 return false;
560 }
561 if (size2 > UINT16_MAX) {
562 return false;
563 }
564 Resize(size1, size2, empty_);
565 return true;
566 }
568 int32_t size1, size2;
569 if (!fp->DeSerialize(&size1)) {
570 return false;
571 }
572 if (!fp->DeSerialize(&size2)) {
573 return false;
574 }
575 // Arbitrarily limit the number of elements to protect against bad data.
576 if (size1 > UINT16_MAX) {
577 return false;
578 }
579 if (size2 > UINT16_MAX) {
580 return false;
581 }
582 Resize(size1, size2, empty_);
583 return true;
584 }
585
587 T empty_; // The unused cell.
588 int dim1_; // Size of the 1st dimension in indexing functions.
589 int dim2_; // Size of the 2nd dimension in indexing functions.
590 // The total size to which the array can be expanded before a realloc is
591 // needed. If Resize is used, memory is retained so it can be re-expanded
592 // without a further alloc, and this stores the allocated size.
594};
595
596// A generic class to store a banded triangular matrix with entries of type T.
597// In this array, the nominally square matrix is dim1_ x dim1_, and dim2_ is
598// the number of bands, INCLUDING the diagonal. The storage is thus of size
599// dim1_ * dim2_ and index(col, row) = col * dim2_ + row - col, and an
600// assert will fail if row < col or row - col >= dim2.
601template <class T>
603public:
604 // Allocate a piece of memory to hold a 2d-array of the given dimension.
605 // Initialize all the elements of the array to empty instead of assuming
606 // that a default constructor can be used.
607 BandTriMatrix(int dim1, int dim2, const T &empty) : GENERIC_2D_ARRAY<T>(dim1, dim2, empty) {}
608 // The default destructor will do.
609
610 // Provide the dimensions of this matrix.
611 // dimension is the size of the nominally square matrix.
612 int dimension() const {
613 return this->dim1_;
614 }
615 // bandwidth is the number of bands in the matrix, INCLUDING the diagonal.
616 int bandwidth() const {
617 return this->dim2_;
618 }
619
620 // Expression to select a specific location in the matrix. The matrix is
621 // stored COLUMN-major, so the left-most index is the most significant.
622 // This allows [][] access to use indices in the same order as (,).
623 int index(int column, int row) const override {
624 ASSERT_HOST(row >= column);
625 ASSERT_HOST(row - column < this->dim2_);
626 return column * this->dim2_ + row - column;
627 }
628
629 // Appends array2 corner-to-corner to *this, making an array of dimension
630 // equal to the sum of the individual dimensions.
631 // array2 is not destroyed, but is left empty, as all elements are moved
632 // to *this.
634 int new_dim1 = this->dim1_ + array2->dim1_;
635 int new_dim2 = std::max(this->dim2_, array2->dim2_);
636 T *new_array = new T[new_dim1 * new_dim2];
637 for (int col = 0; col < new_dim1; ++col) {
638 for (int j = 0; j < new_dim2; ++j) {
639 int new_index = col * new_dim2 + j;
640 if (col < this->dim1_ && j < this->dim2_) {
641 new_array[new_index] = this->get(col, col + j);
642 } else if (col >= this->dim1_ && j < array2->dim2_) {
643 new_array[new_index] = array2->get(col - this->dim1_, col - this->dim1_ + j);
644 array2->put(col - this->dim1_, col - this->dim1_ + j, nullptr);
645 } else {
646 new_array[new_index] = this->empty_;
647 }
648 }
649 }
650 delete[] this->array_;
651 this->array_ = new_array;
652 this->dim1_ = new_dim1;
653 this->dim2_ = new_dim2;
654 }
655};
656
657class MATRIX : public BandTriMatrix<BLOB_CHOICE_LIST *> {
658public:
660 : BandTriMatrix<BLOB_CHOICE_LIST *>(dimension, bandwidth, NOT_CLASSIFIED) {}
661
662 ~MATRIX() override;
663
664 // Returns true if there are any real classification results.
665 bool Classified(int col, int row, int wildcard_id) const;
666
667 // Expands the existing matrix in-place to make the band wider, without
668 // losing any existing data.
669 void IncreaseBandSize(int bandwidth);
670
671 // Returns a bigger MATRIX with a new column and row in the matrix in order
672 // to split the blob at the given (ind,ind) diagonal location.
673 // Entries are relocated to the new MATRIX using the transformation defined
674 // by MATRIX_COORD::MapForSplit.
675 // Transfers the pointer data to the new MATRIX and deletes *this.
677
678 // Makes and returns a deep copy of *this, including all the BLOB_CHOICEs
679 // on the lists, but not any LanguageModelState that may be attached to the
680 // BLOB_CHOICEs.
681 MATRIX *DeepCopy() const;
682
683 // Print a shortened version of the contents of the matrix.
684 void print(const UNICHARSET &unicharset) const;
685};
686
688 static void Delete(void *arg) {
689 auto *c = static_cast<MATRIX_COORD *>(arg);
690 delete c;
691 }
692 // Default constructor required by GenericHeap.
693 MATRIX_COORD() : col(0), row(0) {}
694 MATRIX_COORD(int c, int r) : col(c), row(r) {}
695 ~MATRIX_COORD() = default;
696
697 bool Valid(const MATRIX &m) const {
698 return 0 <= col && col < m.dimension() && col <= row && row < col + m.bandwidth() &&
699 row < m.dimension();
700 }
701
702 // Remaps the col,row pair to split the blob at the given (ind,ind) diagonal
703 // location.
704 // Entries at (i,j) for i in [0,ind] and j in [ind,dim) move to (i,j+1),
705 // making a new row at ind.
706 // Entries at (i,j) for i in [ind+1,dim) and j in [i,dim) move to (i+i,j+1),
707 // making a new column at ind+1.
708 void MapForSplit(int ind) {
709 ASSERT_HOST(row >= col);
710 if (col > ind) {
711 ++col;
712 }
713 if (row >= ind) {
714 ++row;
715 }
716 ASSERT_HOST(row >= col);
717 }
718
719 int col;
720 int row;
721};
722
723// The MatrixCoordPair contains a MATRIX_COORD and its priority.
725
726} // namespace tesseract
727
728#endif // TESSERACT_CCSTRUCT_MATRIX_H_
#define ASSERT_HOST(x)
Definition: errcode.h:54
#define NOT_CLASSIFIED
Definition: matrix.h:45
int value
const double y
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:184
bool DeSerialize(bool swap, FILE *fp, std::vector< T > &data)
Definition: helpers.h:205
bool Serialize(FILE *fp, const std::vector< T > &data)
Definition: helpers.h:236
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:105
dest
Definition: upload.py:409
T & operator()(int column, int row)
Definition: matrix.h:278
void Clip(const T &rangemin, const T &rangemax)
Definition: matrix.h:337
bool DeSerializeClasses(bool swap, FILE *fp)
Definition: matrix.h:223
virtual int num_elements() const
Definition: matrix.h:248
const T & operator()(int column, int row) const
Definition: matrix.h:275
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty, T *array)
Definition: matrix.h:57
void AdamUpdate(const GENERIC_2D_ARRAY< T > &sum, const GENERIC_2D_ARRAY< T > &sqsum, const T &epsilon)
Definition: matrix.h:429
void AssertFinite() const
Definition: matrix.h:437
void operator+=(const GENERIC_2D_ARRAY< T > &addend)
Definition: matrix.h:291
bool DeSerialize(bool swap, FILE *fp)
Definition: matrix.h:175
bool DeSerializeSize(bool swap, FILE *fp)
Definition: matrix.h:545
bool WithinBounds(const T &rangemin, const T &rangemax) const
Definition: matrix.h:345
const T * operator[](int column) const
Definition: matrix.h:286
void operator*=(const T &factor)
Definition: matrix.h:330
virtual ~GENERIC_2D_ARRAY()
Definition: matrix.h:78
bool Serialize(TFile *fp) const
Definition: matrix.h:161
void SumSquares(const GENERIC_2D_ARRAY< T > &src, const T &decay_factor)
Definition: matrix.h:419
bool SerializeSize(TFile *fp) const
Definition: matrix.h:535
void Resize(int size1, int size2, const T &empty)
Definition: matrix.h:110
void put(int column, int row, const T &thing)
Definition: matrix.h:263
bool DeSerializeSize(TFile *fp)
Definition: matrix.h:567
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty)
Definition: matrix.h:63
void operator=(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:82
void ResizeNoInit(int size1, int size2, int pad=0)
Definition: matrix.h:94
void operator+=(const T &addend)
Definition: matrix.h:323
void ResizeWithCopy(int size1, int size2)
Definition: matrix.h:117
void RotatingTranspose(const int *dims, int num_dims, int src_dim, int dest_dim, GENERIC_2D_ARRAY< T > *result) const
Definition: matrix.h:468
bool SerializeSize(FILE *fp) const
Definition: matrix.h:527
T get(ICOORD pos) const
Definition: matrix.h:268
T * operator[](int column)
Definition: matrix.h:283
bool SerializeClasses(FILE *fp) const
Definition: matrix.h:204
GENERIC_2D_ARRAY(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:74
virtual int index(int column, int row) const
Definition: matrix.h:255
void put(ICOORD pos, const T &thing)
Definition: matrix.h:260
T get(int column, int row) const
Definition: matrix.h:271
bool Serialize(FILE *fp) const
Definition: matrix.h:150
bool DeSerialize(TFile *fp)
Definition: matrix.h:197
void operator-=(const GENERIC_2D_ARRAY< T > &minuend)
Definition: matrix.h:307
int dimension() const
Definition: matrix.h:612
void AttachOnCorner(BandTriMatrix< T > *array2)
Definition: matrix.h:633
BandTriMatrix(int dim1, int dim2, const T &empty)
Definition: matrix.h:607
int bandwidth() const
Definition: matrix.h:616
int index(int column, int row) const override
Definition: matrix.h:623
MATRIX * ConsumeAndMakeBigger(int ind)
Definition: matrix.cpp:61
bool Classified(int col, int row, int wildcard_id) const
Definition: matrix.cpp:36
MATRIX * DeepCopy() const
Definition: matrix.cpp:97
~MATRIX() override
MATRIX(int dimension, int bandwidth)
Definition: matrix.h:659
void IncreaseBandSize(int bandwidth)
Definition: matrix.cpp:52
void print(const UNICHARSET &unicharset) const
Definition: matrix.cpp:115
void MapForSplit(int ind)
Definition: matrix.h:708
static void Delete(void *arg)
Definition: matrix.h:688
bool Valid(const MATRIX &m) const
Definition: matrix.h:697
MATRIX_COORD(int c, int r)
Definition: matrix.h:694
integer coordinate
Definition: points.h:36
TDimension y() const
access_function
Definition: points.h:62
TDimension x() const
access function
Definition: points.h:58
bool DeSerialize(std::string &data)
Definition: serialis.cpp:94
bool Serialize(const std::string &data)
Definition: serialis.cpp:107