tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/ccstruct/matrix.h
Go to the documentation of this file.
00001 /* -*-C-*-
00002  ******************************************************************************
00003  *
00004  * File:        matrix.h  (Formerly matrix.h)
00005  * Description:  Ratings matrix code. (Used by associator)
00006  * Author:       Mark Seaman, OCR Technology
00007  * Created:      Wed May 16 13:22:06 1990
00008  * Modified:     Tue Mar 19 16:00:20 1991 (Mark Seaman) marks@hpgrlt
00009  * Language:     C
00010  * Package:      N/A
00011  * Status:       Experimental (Do Not Distribute)
00012  *
00013  * (c) Copyright 1990, Hewlett-Packard Company.
00014  ** Licensed under the Apache License, Version 2.0 (the "License");
00015  ** you may not use this file except in compliance with the License.
00016  ** You may obtain a copy of the License at
00017  ** http://www.apache.org/licenses/LICENSE-2.0
00018  ** Unless required by applicable law or agreed to in writing, software
00019  ** distributed under the License is distributed on an "AS IS" BASIS,
00020  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021  ** See the License for the specific language governing permissions and
00022  ** limitations under the License.
00023  *
00024  *********************************************************************************/
00025 #ifndef TESSERACT_CCSTRUCT_MATRIX_H__
00026 #define TESSERACT_CCSTRUCT_MATRIX_H__
00027 
00028 #include "kdpair.h"
00029 #include "unicharset.h"
00030 
00031 class BLOB_CHOICE_LIST;
00032 
00033 #define NOT_CLASSIFIED reinterpret_cast<BLOB_CHOICE_LIST*>(NULL)
00034 
00035 // A generic class to hold a 2-D matrix with entries of type T, but can also
00036 // act as a base class for other implementations, such as a triangular or
00037 // banded matrix.
00038 template <class T>
00039 class GENERIC_2D_ARRAY {
00040  public:
00041   // Initializes the array size, and empty element, but cannot allocate memory
00042   // for the subclasses or initialize because calls to the num_elements
00043   // member will be routed to the base class implementation. Subclasses can
00044   // either pass the memory in, or allocate after by calling Resize().
00045   GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty, T* array)
00046     : empty_(empty), dim1_(dim1), dim2_(dim2), array_(array)  {
00047   }
00048   // Original constructor for a full rectangular matrix DOES allocate memory
00049   // and initialize it to empty.
00050   GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty)
00051     : empty_(empty), dim1_(dim1), dim2_(dim2)  {
00052     array_ = new T[dim1_ * dim2_];
00053     for (int x = 0; x < dim1_; x++)
00054       for (int y = 0; y < dim2_; y++)
00055         this->put(x, y, empty_);
00056   }
00057   virtual ~GENERIC_2D_ARRAY() { delete[] array_; }
00058 
00059   // Reallocate the array to the given size. Does not keep old data.
00060   void Resize(int size1, int size2, const T& empty) {
00061     empty_ = empty;
00062     if (size1 != dim1_ || size2 != dim2_) {
00063       dim1_ = size1;
00064       dim2_ = size2;
00065       delete [] array_;
00066       array_ = new T[dim1_ * dim2_];
00067     }
00068     Clear();
00069   }
00070 
00071   // Reallocate the array to the given size, keeping old data.
00072   void ResizeWithCopy(int size1, int size2) {
00073     if (size1 != dim1_ || size2 != dim2_) {
00074       T* new_array = new T[size1 * size2];
00075       for (int col = 0; col < size1; ++col) {
00076         for (int row = 0; row < size2; ++row) {
00077           int old_index = col * dim2() + row;
00078           int new_index = col * size2 + row;
00079           if (col < dim1_ && row < dim2_) {
00080             new_array[new_index] = array_[old_index];
00081           } else {
00082             new_array[new_index] = empty_;
00083           }
00084         }
00085       }
00086       delete[] array_;
00087       array_ = new_array;
00088       dim1_ = size1;
00089       dim2_ = size2;
00090     }
00091   }
00092 
00093   // Sets all the elements of the array to the empty value.
00094   void Clear() {
00095     int total_size = num_elements();
00096     for (int i = 0; i < total_size; ++i)
00097       array_[i] = empty_;
00098   }
00099 
00100   // Writes to the given file. Returns false in case of error.
00101   // Only works with bitwise-serializeable types!
00102   bool Serialize(FILE* fp) const {
00103     if (!SerializeSize(fp)) return false;
00104     if (fwrite(&empty_, sizeof(empty_), 1, fp) != 1) return false;
00105     int size = num_elements();
00106     if (fwrite(array_, sizeof(*array_), size, fp) != size) return false;
00107     return true;
00108   }
00109 
00110   // Reads from the given file. Returns false in case of error.
00111   // Only works with bitwise-serializeable typ
00112   // If swap is true, assumes a big/little-endian swap is needed.
00113   bool DeSerialize(bool swap, FILE* fp) {
00114     if (!DeSerializeSize(swap, fp)) return false;
00115     if (fread(&empty_, sizeof(empty_), 1, fp) != 1) return false;
00116     if (swap) ReverseN(&empty_, sizeof(empty_));
00117     int size = num_elements();
00118     if (fread(array_, sizeof(*array_), size, fp) != size) return false;
00119     if (swap) {
00120       for (int i = 0; i < size; ++i)
00121         ReverseN(&array_[i], sizeof(array_[i]));
00122     }
00123     return true;
00124   }
00125 
00126   // Writes to the given file. Returns false in case of error.
00127   // Assumes a T::Serialize(FILE*) const function.
00128   bool SerializeClasses(FILE* fp) const {
00129     if (!SerializeSize(fp)) return false;
00130     if (!empty_.Serialize(fp)) return false;
00131     int size = num_elements();
00132     for (int i = 0; i < size; ++i) {
00133       if (!array_[i].Serialize(fp)) return false;
00134     }
00135     return true;
00136   }
00137 
00138   // Reads from the given file. Returns false in case of error.
00139   // Assumes a T::DeSerialize(bool swap, FILE*) function.
00140   // If swap is true, assumes a big/little-endian swap is needed.
00141   bool DeSerializeClasses(bool swap, FILE* fp) {
00142     if (!DeSerializeSize(swap, fp)) return false;
00143     if (!empty_.DeSerialize(swap, fp)) return false;
00144     int size = num_elements();
00145     for (int i = 0; i < size; ++i) {
00146       if (!array_[i].DeSerialize(swap, fp)) return false;
00147     }
00148     return true;
00149   }
00150 
00151   // Provide the dimensions of this rectangular matrix.
00152   int dim1() const { return dim1_; }
00153   int dim2() const { return dim2_; }
00154   // Returns the number of elements in the array.
00155   // Banded/triangular matrices may override.
00156   virtual int num_elements() const { return dim1_ * dim2_; }
00157 
00158   // Expression to select a specific location in the matrix. The matrix is
00159   // stored COLUMN-major, so the left-most index is the most significant.
00160   // This allows [][] access to use indices in the same order as (,).
00161   virtual int index(int column, int row) const {
00162     return (column * dim2_ + row);
00163   }
00164 
00165   // Put a list element into the matrix at a specific location.
00166   void put(int column, int row, const T& thing) {
00167     array_[this->index(column, row)] = thing;
00168   }
00169 
00170   // Get the item at a specified location from the matrix.
00171   T get(int column, int row) const {
00172     return array_[this->index(column, row)];
00173   }
00174   // Return a reference to the element at the specified location.
00175   const T& operator()(int column, int row) const {
00176     return array_[this->index(column, row)];
00177   }
00178   T& operator()(int column, int row) {
00179     return array_[this->index(column, row)];
00180   }
00181   // Allow access using array[column][row]. NOTE that the indices are
00182   // in the same left-to-right order as the () indexing.
00183   T* operator[](int column) {
00184     return &array_[this->index(column, 0)];
00185   }
00186   const T* operator[](int column) const {
00187     return &array_[this->index(column, 0)];
00188   }
00189 
00190   // Delete objects pointed to by array_[i].
00191   void delete_matrix_pointers() {
00192     int size = num_elements();
00193     for (int i = 0; i < size; ++i) {
00194       T matrix_cell = array_[i];
00195       if (matrix_cell != empty_)
00196         delete matrix_cell;
00197     }
00198   }
00199 
00200  protected:
00201   // Factored helper to serialize the size.
00202   bool SerializeSize(FILE* fp) const {
00203     inT32 size = dim1_;
00204     if (fwrite(&size, sizeof(size), 1, fp) != 1) return false;
00205     size = dim2_;
00206     if (fwrite(&size, sizeof(size), 1, fp) != 1) return false;
00207     return true;
00208   }
00209   // Factored helper to deserialize the size.
00210   // If swap is true, assumes a big/little-endian swap is needed.
00211   bool DeSerializeSize(bool swap, FILE* fp) {
00212     inT32 size1, size2;
00213     if (fread(&size1, sizeof(size1), 1, fp) != 1) return false;
00214     if (fread(&size2, sizeof(size2), 1, fp) != 1) return false;
00215     if (swap) {
00216       ReverseN(&size1, sizeof(size1));
00217       ReverseN(&size2, sizeof(size2));
00218     }
00219     Resize(size1, size2, empty_);
00220     return true;
00221   }
00222 
00223   T* array_;
00224   T empty_;   // The unused cell.
00225   int dim1_;  // Size of the 1st dimension in indexing functions.
00226   int dim2_;  // Size of the 2nd dimension in indexing functions.
00227 };
00228 
00229 // A generic class to store a banded triangular matrix with entries of type T.
00230 // In this array, the nominally square matrix is dim1_ x dim1_, and dim2_ is
00231 // the number of bands, INCLUDING the diagonal. The storage is thus of size
00232 // dim1_ * dim2_ and index(col, row) = col * dim2_ + row - col, and an
00233 // assert will fail if row < col or row - col >= dim2.
00234 template <class T>
00235 class BandTriMatrix : public GENERIC_2D_ARRAY<T> {
00236  public:
00237   // Allocate a piece of memory to hold a 2d-array of the given dimension.
00238   // Initialize all the elements of the array to empty instead of assuming
00239   // that a default constructor can be used.
00240   BandTriMatrix(int dim1, int dim2, const T& empty)
00241     : GENERIC_2D_ARRAY<T>(dim1, dim2, empty)  {
00242   }
00243   // The default destructor will do.
00244 
00245   // Provide the dimensions of this matrix.
00246   // dimension is the size of the nominally square matrix.
00247   int dimension() const { return this->dim1_; }
00248   // bandwidth is the number of bands in the matrix, INCLUDING the diagonal.
00249   int bandwidth() const { return this->dim2_; }
00250 
00251   // Expression to select a specific location in the matrix. The matrix is
00252   // stored COLUMN-major, so the left-most index is the most significant.
00253   // This allows [][] access to use indices in the same order as (,).
00254   virtual int index(int column, int row) const {
00255     ASSERT_HOST(row >= column);
00256     ASSERT_HOST(row - column < this->dim2_);
00257     return column * this->dim2_ + row - column;
00258   }
00259 
00260   // Appends array2 corner-to-corner to *this, making an array of dimension
00261   // equal to the sum of the individual dimensions.
00262   // array2 is not destroyed, but is left empty, as all elements are moved
00263   // to *this.
00264   void AttachOnCorner(BandTriMatrix<T>* array2) {
00265     int new_dim1 = this->dim1_ + array2->dim1_;
00266     int new_dim2 = MAX(this->dim2_, array2->dim2_);
00267     T* new_array = new T[new_dim1 * new_dim2];
00268     for (int col = 0; col < new_dim1; ++col) {
00269       for (int j = 0; j < new_dim2; ++j) {
00270         int new_index = col * new_dim2 + j;
00271         if (col < this->dim1_ && j < this->dim2_) {
00272           new_array[new_index] = this->get(col, col + j);
00273         } else if (col >= this->dim1_ && j < array2->dim2_) {
00274           new_array[new_index] = array2->get(col - this->dim1_,
00275                                              col - this->dim1_ + j);
00276           array2->put(col - this->dim1_, col - this->dim1_ + j, NULL);
00277         } else {
00278           new_array[new_index] = this->empty_;
00279         }
00280       }
00281     }
00282     delete[] this->array_;
00283     this->array_ = new_array;
00284     this->dim1_ = new_dim1;
00285     this->dim2_ = new_dim2;
00286   }
00287 };
00288 
00289 class MATRIX : public BandTriMatrix<BLOB_CHOICE_LIST *> {
00290  public:
00291   MATRIX(int dimension, int bandwidth)
00292     : BandTriMatrix<BLOB_CHOICE_LIST *>(dimension, bandwidth, NOT_CLASSIFIED) {}
00293 
00294   // Returns true if there are any real classification results.
00295   bool Classified(int col, int row, int wildcard_id) const;
00296 
00297   // Expands the existing matrix in-place to make the band wider, without
00298   // losing any existing data.
00299   void IncreaseBandSize(int bandwidth);
00300 
00301   // Returns a bigger MATRIX with a new column and row in the matrix in order
00302   // to split the blob at the given (ind,ind) diagonal location.
00303   // Entries are relocated to the new MATRIX using the transformation defined
00304   // by MATRIX_COORD::MapForSplit.
00305   // Transfers the pointer data to the new MATRIX and deletes *this.
00306   MATRIX* ConsumeAndMakeBigger(int ind);
00307 
00308   // Makes and returns a deep copy of *this, including all the BLOB_CHOICEs
00309   // on the lists, but not any LanguageModelState that may be attached to the
00310   // BLOB_CHOICEs.
00311   MATRIX* DeepCopy() const;
00312 
00313   // Print a shortened version of the contents of the matrix.
00314   void print(const UNICHARSET &unicharset) const;
00315 };
00316 
00317 struct MATRIX_COORD {
00318   static void Delete(void *arg) {
00319     MATRIX_COORD *c = static_cast<MATRIX_COORD *>(arg);
00320     delete c;
00321   }
00322   // Default constructor required by GenericHeap.
00323   MATRIX_COORD() : col(0), row(0) {}
00324   MATRIX_COORD(int c, int r): col(c), row(r) {}
00325   ~MATRIX_COORD() {}
00326 
00327   bool Valid(const MATRIX &m) const {
00328     return 0 <= col && col < m.dimension() &&
00329            col <= row && row < col + m.bandwidth() && row < m.dimension();
00330   }
00331 
00332   // Remaps the col,row pair to split the blob at the given (ind,ind) diagonal
00333   // location.
00334   // Entries at (i,j) for i in [0,ind] and j in [ind,dim) move to (i,j+1),
00335   // making a new row at ind.
00336   // Entries at (i,j) for i in [ind+1,dim) and j in [i,dim) move to (i+i,j+1),
00337   // making a new column at ind+1.
00338   void MapForSplit(int ind) {
00339     ASSERT_HOST(row >= col);
00340     if (col > ind) ++col;
00341     if (row >= ind) ++row;
00342     ASSERT_HOST(row >= col);
00343   }
00344 
00345   int col;
00346   int row;
00347 };
00348 
00349 // The MatrixCoordPair contains a MATRIX_COORD and its priority.
00350 typedef tesseract::KDPairInc<float, MATRIX_COORD> MatrixCoordPair;
00351 
00352 #endif  // TESSERACT_CCSTRUCT_MATRIX_H__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines