25 #include "allheaders.h" 56 static bool atan_table_init =
false;
58 if (!atan_table_init) {
63 atan_table_init =
true;
71 return FCOORD(cos_table[theta], sin_table[theta]);
86 &cn_features, fx_info, NULL);
90 int num_features = fx_info->
NumCN;
91 if (num_features > 0) {
98 topleft.
x = box.
left();
99 topleft.
y = box.
top();
102 TPOINT original_topleft, original_botright;
105 sample->set_bounding_box(
TBOX(original_topleft.
x, original_botright.
y,
106 original_botright.
x, original_topleft.
y));
137 FCOORD center, second_moments;
139 if (fx_info != NULL) {
149 1.0f, 1.0f, 128.0f, 128.0f);
151 if (nonlinear_norm) {
159 0.0f, 0.0f, x_coords, y_coords);
162 center.
x(), center.
y(),
163 51.2f / second_moments.
x(),
164 51.2f / second_moments.
y(),
176 unnormed_end += unnormed_pos;
177 FCOORD normed_pos, normed_end;
178 denorm.
NormTransform(root_denorm, unnormed_pos, &normed_pos);
179 denorm.
NormTransform(root_denorm, unnormed_end, &normed_end);
180 normed_end -= normed_pos;
187 static FCOORD MeanDirectionVector(
const LLSQ& point_diffs,
const LLSQ& dirs,
191 if (dirs.
count() > 0) {
196 double mean_dir = 0.0;
198 mean_dir = mean_pt.
x();
200 mean_dir = mean_pt.
y() + 128;
207 FCOORD feature_dir(end_pt - start_pt);
209 if (fit_vector.
x() == 0.0f && fit_vector.
y() == 0.0f) {
211 fit_vector = feature_dir;
216 FCOORD fit_vector2 = !fit_vector;
219 if (fit_vector % feature_dir < 0.0)
220 fit_vector = -fit_vector;
221 if (fit_vector2 % feature_dir < 0.0)
222 fit_vector2 = -fit_vector2;
225 if (fit_vector2 % feature_dir > fit_vector % feature_dir)
226 fit_vector = fit_vector2;
236 static int ComputeFeatures(
const FCOORD& start_pt,
const FCOORD& end_pt,
237 double feature_length,
239 FCOORD feature_vector(end_pt - start_pt);
240 if (feature_vector.x() == 0.0f && feature_vector.y() == 0.0f)
return 0;
242 uinT8 theta = feature_vector.to_direction();
244 double target_length = feature_vector.length();
245 int num_features =
IntCastRounded(target_length / feature_length);
246 if (num_features == 0)
return 0;
248 double lambda_step = 1.0 / num_features;
249 double lambda = lambda_step / 2.0;
250 for (
int f = 0; f < num_features; ++f, lambda += lambda_step) {
251 FCOORD feature_pt(start_pt);
252 feature_pt += feature_vector * lambda;
273 static int GatherPoints(
const C_OUTLINE* outline,
double feature_length,
275 int start_index,
int end_index,
279 ICOORD step = outline->
step(start_index % step_length);
288 for (index = start_index; index <= end_index; ++index, *pos += step) {
289 step = outline->
step(index % step_length);
291 if (edge_weight == 0) {
298 if (num_points == 0) {
300 prev_normed = *pos_normed;
302 FCOORD offset = *pos_normed - prev_normed;
303 float length = offset.
length();
304 if (length > feature_length) {
310 points->
add(pos_normed->
x(), pos_normed->
y(), edge_weight);
329 static void ExtractFeaturesFromRun(
331 const DENORM& denorm,
double feature_length,
bool force_poly,
335 if (outline != NULL && !force_poly) {
339 int total_features = 0;
349 if (end_index <= start_index)
350 end_index += step_length;
354 denorm.
NormTransform(root_denorm, prev_normed_pos, &prev_normed_pos);
358 int index = GatherPoints(outline, feature_length, denorm, root_denorm,
359 start_index, end_index, &pos, &normed_pos,
361 while (index <= end_index) {
370 index = GatherPoints(outline, feature_length, denorm, root_denorm,
371 index, end_index, &pos, &next_normed_pos,
372 &next_points, &next_dirs);
373 LLSQ sum_points(prev_points);
377 sum_points.add(points);
378 sum_points.add(next_points);
379 sum_dirs.add(next_dirs);
380 bool made_features =
false;
382 if (sum_points.count() > 0) {
384 FCOORD fit_pt = sum_points.mean_point();
385 FCOORD fit_vector = MeanDirectionVector(sum_points, sum_dirs,
386 prev_normed_pos, normed_pos);
394 if (total_features == 0 && startpt != endpt) {
398 if (index > end_index && startpt != endpt) {
402 int num_features = ComputeFeatures(start_pos, end_pos, feature_length,
404 if (num_features > 0) {
406 prev_points = points;
408 prev_normed_pos = normed_pos;
409 points = next_points;
411 made_features =
true;
412 total_features += num_features;
415 normed_pos = next_normed_pos;
417 if (!made_features) {
420 points.
add(next_points);
426 const EDGEPT* pt = startpt;
432 ComputeFeatures(start_pos, end_pos, feature_length, features);
433 }
while ((pt = pt->
next) != endpt);
451 DENORM bl_denorm, cn_denorm;
453 &bl_denorm, &cn_denorm, results);
454 if (outline_cn_counts != NULL)
459 EDGEPT* loop_pt = ol->FindBestStartPt();
461 if (pt == NULL)
continue;
467 last_pt = last_pt->
next;
468 }
while (last_pt != loop_pt && !last_pt->
IsHidden() &&
470 last_pt = last_pt->
prev;
478 }
while ((pt = pt->
next) != loop_pt);
479 if (outline_cn_counts != NULL)
521 &bl_features, &cn_features, results,
523 if (bl_features.
empty() || cn_features.
empty() ||
528 memcpy(baseline_features, &bl_features[0],
529 bl_features.
size() *
sizeof(bl_features[0]));
530 memcpy(charnorm_features, &cn_features[0],
531 cn_features.
size() *
sizeof(cn_features[0]));
void from_direction(uinT8 direction)
uinT8 NormalizeDirection(uinT8 dir, const FCOORD &unnormed_pos, const DENORM &denorm, const DENORM *root_denorm)
void GetEdgeCoords(const TBOX &box, GenericVector< GenericVector< int > > *x_coords, GenericVector< GenericVector< int > > *y_coords) const
double y_variance() const
int IntCastRounded(double x)
bool ExtractIntFeat(const TBLOB &blob, bool nonlinear_norm, INT_FEATURE_ARRAY baseline_features, INT_FEATURE_ARRAY charnorm_features, INT_FX_RESULT_STRUCT *results)
void SetupNonLinear(const DENORM *predecessor, const TBOX &box, float target_width, float target_height, float final_xshift, float final_yshift, const GenericVector< GenericVector< int > > &x_coords, const GenericVector< GenericVector< int > > &y_coords)
FCOORD nearest_pt_on_line(const FCOORD &line_point, const FCOORD &dir_vector) const
INT_FEATURE_STRUCT INT_FEATURE_ARRAY[MAX_NUM_INT_FEATURES]
ICOORD position_at_index(int index) const
static void SetupBLCNDenorms(const TBLOB &blob, bool nonlinear_norm, DENORM *bl_denorm, DENORM *cn_denorm, INT_FX_RESULT_STRUCT *fx_info)
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
ICOORD step(int index) const
void SetupNormalization(const BLOCK *block, const FCOORD *rotation, const DENORM *predecessor, float x_origin, float y_origin, float x_scale, float y_scale, float final_xshift, float final_yshift)
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
static TrainingSample * CopyFromFeatures(const INT_FX_RESULT_STRUCT &fx_info, const TBOX &bounding_box, const INT_FEATURE_STRUCT *features, int num_features)
void add(double x, double y)
TBOX bounding_box() const
const double kStandardFeatureLength
float length() const
find length
TrainingSample * BlobToTrainingSample(const TBLOB &blob, bool nonlinear_norm, INT_FX_RESULT_STRUCT *fx_info, GenericVector< INT_FEATURE_STRUCT > *bl_features)
#define MAX_NUM_INT_FEATURES
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
double x_variance() const
tesseract::CCUtilMutex atan_table_mutex
const DENORM & denorm() const
uinT8 to_direction() const
int edge_strength_at_index(int index) const
void GetPreciseBoundingBox(TBOX *precise_box) const
int direction(EDGEPT *point)
FCOORD vector_fit() const
void pad(int xpad, int ypad)
#define INT_CHAR_NORM_RANGE
int ComputeMoments(FCOORD *center, FCOORD *second_moments) const
FCOORD mean_point() const
static void ExtractFeatures(const TBLOB &blob, bool nonlinear_norm, GenericVector< INT_FEATURE_STRUCT > *bl_features, GenericVector< INT_FEATURE_STRUCT > *cn_features, INT_FX_RESULT_STRUCT *results, GenericVector< int > *outline_cn_counts)
FCOORD FeatureDirection(uinT8 theta)
FCOORD sub_pixel_pos_at_index(const ICOORD &pos, int index) const
const DENORM * RootDenorm() const
int direction_at_index(int index) const