tesseract
3.03
|
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__