tesseract
3.03
|
00001 /********************************************************************** 00002 * File: feature_chebyshev.cpp 00003 * Description: Implementation of the Chebyshev coefficients Feature Class 00004 * Author: Ahmad Abdulkader 00005 * Created: 2008 00006 * 00007 * (C) Copyright 2008, Google Inc. 00008 ** Licensed under the Apache License, Version 2.0 (the "License"); 00009 ** you may not use this file except in compliance with the License. 00010 ** You may obtain a copy of the License at 00011 ** http://www.apache.org/licenses/LICENSE-2.0 00012 ** Unless required by applicable law or agreed to in writing, software 00013 ** distributed under the License is distributed on an "AS IS" BASIS, 00014 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 ** See the License for the specific language governing permissions and 00016 ** limitations under the License. 00017 * 00018 **********************************************************************/ 00019 00020 #include <stdio.h> 00021 #include <stdlib.h> 00022 #include <math.h> 00023 #include <string> 00024 #include <vector> 00025 #include <algorithm> 00026 #include "feature_base.h" 00027 #include "feature_chebyshev.h" 00028 #include "cube_utils.h" 00029 #include "const.h" 00030 #include "char_samp.h" 00031 00032 namespace tesseract { 00033 00034 FeatureChebyshev::FeatureChebyshev(TuningParams *params) 00035 : FeatureBase(params) { 00036 } 00037 00038 FeatureChebyshev::~FeatureChebyshev() { 00039 } 00040 00041 // Render a visualization of the features to a CharSamp. 00042 // This is mainly used by visual-debuggers 00043 CharSamp *FeatureChebyshev::ComputeFeatureBitmap(CharSamp *char_samp) { 00044 return char_samp; 00045 } 00046 00047 // Compute Chebyshev coefficients for the specified vector 00048 void FeatureChebyshev::ChebyshevCoefficients(const vector<float> &input, 00049 int coeff_cnt, float *coeff) { 00050 // re-sample function 00051 int input_range = (input.size() - 1); 00052 vector<float> resamp(coeff_cnt); 00053 for (int samp_idx = 0; samp_idx < coeff_cnt; samp_idx++) { 00054 // compute sampling position 00055 float samp_pos = input_range * 00056 (1 + cos(M_PI * (samp_idx + 0.5) / coeff_cnt)) / 2; 00057 // interpolate 00058 int samp_start = static_cast<int>(samp_pos); 00059 int samp_end = static_cast<int>(samp_pos + 0.5); 00060 float func_delta = input[samp_end] - input[samp_start]; 00061 resamp[samp_idx] = input[samp_start] + 00062 ((samp_pos - samp_start) * func_delta); 00063 } 00064 // compute the coefficients 00065 float normalizer = 2.0 / coeff_cnt; 00066 for (int coeff_idx = 0; coeff_idx < coeff_cnt; coeff_idx++, coeff++) { 00067 double sum = 0.0; 00068 for (int samp_idx = 0; samp_idx < coeff_cnt; samp_idx++) { 00069 sum += resamp[samp_idx] * cos(M_PI * coeff_idx * (samp_idx + 0.5) / 00070 coeff_cnt); 00071 } 00072 (*coeff) = (normalizer * sum); 00073 } 00074 } 00075 00076 // Compute the features of a given CharSamp 00077 bool FeatureChebyshev::ComputeFeatures(CharSamp *char_samp, float *features) { 00078 return ComputeChebyshevCoefficients(char_samp, features); 00079 } 00080 00081 // Compute the Chebyshev coefficients of a given CharSamp 00082 bool FeatureChebyshev::ComputeChebyshevCoefficients(CharSamp *char_samp, 00083 float *features) { 00084 if (char_samp->NormBottom() <= 0) { 00085 return false; 00086 } 00087 unsigned char *raw_data = char_samp->RawData(); 00088 int stride = char_samp->Stride(); 00089 // compute the height of the word 00090 int word_hgt = (255 * (char_samp->Top() + char_samp->Height()) / 00091 char_samp->NormBottom()); 00092 // compute left & right profiles 00093 vector<float> left_profile(word_hgt, 0.0); 00094 vector<float> right_profile(word_hgt, 0.0); 00095 unsigned char *line_data = raw_data; 00096 for (int y = 0; y < char_samp->Height(); y++, line_data += stride) { 00097 int min_x = char_samp->Width(); 00098 int max_x = -1; 00099 for (int x = 0; x < char_samp->Width(); x++) { 00100 if (line_data[x] == 0) { 00101 UpdateRange(x, &min_x, &max_x); 00102 } 00103 } 00104 left_profile[char_samp->Top() + y] = 00105 1.0 * (min_x == char_samp->Width() ? 0 : (min_x + 1)) / 00106 char_samp->Width(); 00107 right_profile[char_samp->Top() + y] = 00108 1.0 * (max_x == -1 ? 0 : char_samp->Width() - max_x) / 00109 char_samp->Width(); 00110 } 00111 00112 // compute top and bottom profiles 00113 vector<float> top_profile(char_samp->Width(), 0); 00114 vector<float> bottom_profile(char_samp->Width(), 0); 00115 for (int x = 0; x < char_samp->Width(); x++) { 00116 int min_y = word_hgt; 00117 int max_y = -1; 00118 line_data = raw_data; 00119 for (int y = 0; y < char_samp->Height(); y++, line_data += stride) { 00120 if (line_data[x] == 0) { 00121 UpdateRange(y + char_samp->Top(), &min_y, &max_y); 00122 } 00123 } 00124 top_profile[x] = 1.0 * (min_y == word_hgt ? 0 : (min_y + 1)) / word_hgt; 00125 bottom_profile[x] = 1.0 * (max_y == -1 ? 0 : (word_hgt - max_y)) / word_hgt; 00126 } 00127 00128 // compute the chebyshev coefficients of each profile 00129 ChebyshevCoefficients(left_profile, kChebychevCoefficientCnt, features); 00130 ChebyshevCoefficients(top_profile, kChebychevCoefficientCnt, 00131 features + kChebychevCoefficientCnt); 00132 ChebyshevCoefficients(right_profile, kChebychevCoefficientCnt, 00133 features + (2 * kChebychevCoefficientCnt)); 00134 ChebyshevCoefficients(bottom_profile, kChebychevCoefficientCnt, 00135 features + (3 * kChebychevCoefficientCnt)); 00136 return true; 00137 } 00138 } // namespace tesseract