25 #include "allheaders.h" 54 static bool atan_table_init =
false;
56 if (!atan_table_init) {
61 atan_table_init =
true;
69 return FCOORD(cos_table[theta], sin_table[theta]);
84 &cn_features, fx_info,
nullptr);
88 int num_features = fx_info->
NumCN;
89 if (num_features > 0) {
96 topleft.
x = box.
left();
97 topleft.
y = box.
top();
100 TPOINT original_topleft, original_botright;
103 sample->set_bounding_box(
TBOX(original_topleft.
x, original_botright.
y,
104 original_botright.
x, original_topleft.
y));
135 FCOORD center, second_moments;
137 if (fx_info !=
nullptr) {
147 1.0f, 1.0f, 128.0f, 128.0f);
149 if (nonlinear_norm) {
157 0.0f, 0.0f, x_coords, y_coords);
160 center.
x(), center.
y(),
161 51.2f / second_moments.
x(),
162 51.2f / second_moments.
y(),
169 static uint8_t NormalizeDirection(uint8_t dir,
const FCOORD& unnormed_pos,
171 const DENORM* root_denorm) {
175 unnormed_end += unnormed_pos;
176 FCOORD normed_pos, normed_end;
177 denorm.
NormTransform(root_denorm, unnormed_pos, &normed_pos);
178 denorm.
NormTransform(root_denorm, unnormed_end, &normed_end);
179 normed_end -= normed_pos;
186 static FCOORD MeanDirectionVector(
const LLSQ& point_diffs,
const LLSQ& dirs,
190 if (dirs.
count() > 0) {
195 double mean_dir = 0.0;
197 mean_dir = mean_pt.
x();
199 mean_dir = mean_pt.
y() + 128;
206 FCOORD feature_dir(end_pt - start_pt);
208 if (fit_vector.
x() == 0.0f && fit_vector.
y() == 0.0f) {
210 fit_vector = feature_dir;
215 FCOORD fit_vector2 = !fit_vector;
218 if (fit_vector % feature_dir < 0.0)
219 fit_vector = -fit_vector;
220 if (fit_vector2 % feature_dir < 0.0)
221 fit_vector2 = -fit_vector2;
224 if (fit_vector2 % feature_dir > fit_vector % feature_dir)
225 fit_vector = fit_vector2;
235 static int ComputeFeatures(
const FCOORD& start_pt,
const FCOORD& end_pt,
236 double feature_length,
238 FCOORD feature_vector(end_pt - start_pt);
239 if (feature_vector.x() == 0.0f && feature_vector.y() == 0.0f)
return 0;
241 uint8_t theta = feature_vector.to_direction();
243 double target_length = feature_vector.length();
244 int num_features =
IntCastRounded(target_length / feature_length);
245 if (num_features == 0)
return 0;
247 double lambda_step = 1.0 / num_features;
248 double lambda = lambda_step / 2.0;
249 for (
int f = 0; f < num_features; ++f, lambda += lambda_step) {
250 FCOORD feature_pt(start_pt);
251 feature_pt += feature_vector * lambda;
272 static int GatherPoints(
const C_OUTLINE* outline,
double feature_length,
274 int start_index,
int end_index,
278 ICOORD step = outline->
step(start_index % step_length);
287 for (index = start_index; index <= end_index; ++index, *pos += step) {
288 step = outline->
step(index % step_length);
290 if (edge_weight == 0) {
297 if (num_points == 0) {
299 prev_normed = *pos_normed;
301 FCOORD offset = *pos_normed - prev_normed;
302 float length = offset.
length();
303 if (length > feature_length) {
309 points->
add(pos_normed->
x(), pos_normed->
y(), edge_weight);
328 static void ExtractFeaturesFromRun(
330 const DENORM& denorm,
double feature_length,
bool force_poly,
334 if (outline !=
nullptr && !force_poly) {
338 int total_features = 0;
348 if (end_index <= start_index)
349 end_index += step_length;
353 denorm.
NormTransform(root_denorm, prev_normed_pos, &prev_normed_pos);
356 FCOORD normed_pos(0.0f, 0.0f);
357 int index = GatherPoints(outline, feature_length, denorm, root_denorm,
358 start_index, end_index, &pos, &normed_pos,
360 while (index <= end_index) {
368 FCOORD next_normed_pos(0.0f, 0.0f);
369 index = GatherPoints(outline, feature_length, denorm, root_denorm,
370 index, end_index, &pos, &next_normed_pos,
371 &next_points, &next_dirs);
372 LLSQ sum_points(prev_points);
376 sum_points.add(points);
377 sum_points.add(next_points);
378 sum_dirs.add(next_dirs);
379 bool made_features =
false;
381 if (sum_points.count() > 0) {
383 FCOORD fit_pt = sum_points.mean_point();
384 FCOORD fit_vector = MeanDirectionVector(sum_points, sum_dirs,
385 prev_normed_pos, normed_pos);
393 if (total_features == 0 && startpt != endpt) {
397 if (index > end_index && startpt != endpt) {
401 int num_features = ComputeFeatures(start_pos, end_pos, feature_length,
403 if (num_features > 0) {
405 prev_points = points;
407 prev_normed_pos = normed_pos;
408 points = next_points;
410 made_features =
true;
411 total_features += num_features;
414 normed_pos = next_normed_pos;
416 if (!made_features) {
419 points.
add(next_points);
425 const EDGEPT* pt = startpt;
431 ComputeFeatures(start_pos, end_pos, feature_length, features);
432 }
while ((pt = pt->
next) != endpt);
450 DENORM bl_denorm, cn_denorm;
452 &bl_denorm, &cn_denorm, results);
453 if (outline_cn_counts !=
nullptr)
458 EDGEPT* loop_pt = ol->FindBestStartPt();
460 if (pt ==
nullptr)
continue;
466 last_pt = last_pt->
next;
467 }
while (last_pt != loop_pt && !last_pt->
IsHidden() &&
469 last_pt = last_pt->
prev;
477 }
while ((pt = pt->
next) != loop_pt);
478 if (outline_cn_counts !=
nullptr)
FCOORD FeatureDirection(uint8_t theta)
int direction_at_index(int index) const
TrainingSample * BlobToTrainingSample(const TBLOB &blob, bool nonlinear_norm, INT_FX_RESULT_STRUCT *fx_info, GenericVector< INT_FEATURE_STRUCT > *bl_features)
int ComputeMoments(FCOORD *center, FCOORD *second_moments) const
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
static void SetupBLCNDenorms(const TBLOB &blob, bool nonlinear_norm, DENORM *bl_denorm, DENORM *cn_denorm, INT_FX_RESULT_STRUCT *fx_info)
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)
const DENORM * RootDenorm() 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 sub_pixel_pos_at_index(const ICOORD &pos, int index) const
tesseract::CCUtilMutex atan_table_mutex
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)
#define INT_CHAR_NORM_RANGE
static TrainingSample * CopyFromFeatures(const INT_FX_RESULT_STRUCT &fx_info, const TBOX &bounding_box, const INT_FEATURE_STRUCT *features, int num_features)
int direction(EDGEPT *point)
void from_direction(uint8_t direction)
void add(double x, double y)
FCOORD mean_point() const
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
FCOORD vector_fit() const
ICOORD position_at_index(int index) const
int edge_strength_at_index(int index) const
int IntCastRounded(double x)
int32_t pathlength() const
TBOX bounding_box() const
void GetPreciseBoundingBox(TBOX *precise_box) const
double y_variance() const
float length() const
find length
const DENORM & denorm() const
double x_variance() const
const double kStandardFeatureLength
uint8_t to_direction() const
void GetEdgeCoords(const TBOX &box, GenericVector< GenericVector< int > > *x_coords, GenericVector< GenericVector< int > > *y_coords) const
ICOORD step(int index) const
void pad(int xpad, int ypad)
FCOORD nearest_pt_on_line(const FCOORD &line_point, const FCOORD &dir_vector) const