All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
feature_chebyshev.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: feature_chebyshev.cpp
3  * Description: Implementation of the Chebyshev coefficients Feature Class
4  * Author: Ahmad Abdulkader
5  * Created: 2008
6  *
7  * (C) Copyright 2008, Google Inc.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string>
24 #include <vector>
25 #include <algorithm>
26 #include "feature_base.h"
27 #include "feature_chebyshev.h"
28 #include "cube_utils.h"
29 #include "const.h"
30 #include "char_samp.h"
31 
32 namespace tesseract {
33 
35  : FeatureBase(params) {
36 }
37 
39 }
40 
41 // Render a visualization of the features to a CharSamp.
42 // This is mainly used by visual-debuggers
44  return char_samp;
45 }
46 
47 // Compute Chebyshev coefficients for the specified vector
48 void FeatureChebyshev::ChebyshevCoefficients(const vector<float> &input,
49  int coeff_cnt, float *coeff) {
50  // re-sample function
51  int input_range = (input.size() - 1);
52  vector<float> resamp(coeff_cnt);
53  for (int samp_idx = 0; samp_idx < coeff_cnt; samp_idx++) {
54  // compute sampling position
55  float samp_pos = input_range *
56  (1 + cos(M_PI * (samp_idx + 0.5) / coeff_cnt)) / 2;
57  // interpolate
58  int samp_start = static_cast<int>(samp_pos);
59  int samp_end = static_cast<int>(samp_pos + 0.5);
60  float func_delta = input[samp_end] - input[samp_start];
61  resamp[samp_idx] = input[samp_start] +
62  ((samp_pos - samp_start) * func_delta);
63  }
64  // compute the coefficients
65  float normalizer = 2.0 / coeff_cnt;
66  for (int coeff_idx = 0; coeff_idx < coeff_cnt; coeff_idx++, coeff++) {
67  double sum = 0.0;
68  for (int samp_idx = 0; samp_idx < coeff_cnt; samp_idx++) {
69  sum += resamp[samp_idx] * cos(M_PI * coeff_idx * (samp_idx + 0.5) /
70  coeff_cnt);
71  }
72  (*coeff) = (normalizer * sum);
73  }
74 }
75 
76 // Compute the features of a given CharSamp
77 bool FeatureChebyshev::ComputeFeatures(CharSamp *char_samp, float *features) {
78  return ComputeChebyshevCoefficients(char_samp, features);
79 }
80 
81 // Compute the Chebyshev coefficients of a given CharSamp
83  float *features) {
84  if (char_samp->NormBottom() <= 0) {
85  return false;
86  }
87  unsigned char *raw_data = char_samp->RawData();
88  int stride = char_samp->Stride();
89  // compute the height of the word
90  int word_hgt = (255 * (char_samp->Top() + char_samp->Height()) /
91  char_samp->NormBottom());
92  // compute left & right profiles
93  vector<float> left_profile(word_hgt, 0.0);
94  vector<float> right_profile(word_hgt, 0.0);
95  unsigned char *line_data = raw_data;
96  for (int y = 0; y < char_samp->Height(); y++, line_data += stride) {
97  int min_x = char_samp->Width();
98  int max_x = -1;
99  for (int x = 0; x < char_samp->Width(); x++) {
100  if (line_data[x] == 0) {
101  UpdateRange(x, &min_x, &max_x);
102  }
103  }
104  left_profile[char_samp->Top() + y] =
105  1.0 * (min_x == char_samp->Width() ? 0 : (min_x + 1)) /
106  char_samp->Width();
107  right_profile[char_samp->Top() + y] =
108  1.0 * (max_x == -1 ? 0 : char_samp->Width() - max_x) /
109  char_samp->Width();
110  }
111 
112  // compute top and bottom profiles
113  vector<float> top_profile(char_samp->Width(), 0);
114  vector<float> bottom_profile(char_samp->Width(), 0);
115  for (int x = 0; x < char_samp->Width(); x++) {
116  int min_y = word_hgt;
117  int max_y = -1;
118  line_data = raw_data;
119  for (int y = 0; y < char_samp->Height(); y++, line_data += stride) {
120  if (line_data[x] == 0) {
121  UpdateRange(y + char_samp->Top(), &min_y, &max_y);
122  }
123  }
124  top_profile[x] = 1.0 * (min_y == word_hgt ? 0 : (min_y + 1)) / word_hgt;
125  bottom_profile[x] = 1.0 * (max_y == -1 ? 0 : (word_hgt - max_y)) / word_hgt;
126  }
127 
128  // compute the chebyshev coefficients of each profile
129  ChebyshevCoefficients(left_profile, kChebychevCoefficientCnt, features);
131  features + kChebychevCoefficientCnt);
133  features + (2 * kChebychevCoefficientCnt));
135  features + (3 * kChebychevCoefficientCnt));
136  return true;
137 }
138 } // namespace tesseract
static const int kChebychevCoefficientCnt
virtual bool ComputeFeatures(CharSamp *samp, float *features)
unsigned char * RawData() const
Definition: bmp_8.h:51
void ChebyshevCoefficients(const vector< float > &input, int coeff_cnt, float *coeff)
void UpdateRange(const T1 &x, T2 *lower_bound, T2 *upper_bound)
Definition: helpers.h:125
FeatureChebyshev(TuningParams *params)
unsigned short Width() const
Definition: bmp_8.h:48
bool ComputeChebyshevCoefficients(CharSamp *samp, float *features)
unsigned short NormBottom() const
Definition: char_samp.h:52
unsigned short Top() const
Definition: char_samp.h:48
unsigned short Stride() const
Definition: bmp_8.h:49
unsigned short Height() const
Definition: bmp_8.h:50
virtual CharSamp * ComputeFeatureBitmap(CharSamp *samp)