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