21 #define _USE_MATH_DEFINES
24 #include "allheaders.h"
52 static bool atan_table_init =
false;
53 atan_table_mutex.
Lock();
54 if (!atan_table_init) {
59 atan_table_init =
true;
67 return FCOORD(cos_table[theta], sin_table[theta]);
82 &cn_features, fx_info,
nullptr);
86 int num_features = fx_info->
NumCN;
87 if (num_features > 0) {
94 topleft.
x = box.
left();
95 topleft.
y = box.
top();
98 TPOINT original_topleft, original_botright;
101 sample->set_bounding_box(
TBOX(original_topleft.
x, original_botright.
y,
102 original_botright.
x, original_topleft.
y));
133 FCOORD center, second_moments;
135 if (fx_info !=
nullptr) {
145 1.0f, 1.0f, 128.0f, 128.0f);
147 if (nonlinear_norm) {
155 0.0f, 0.0f, x_coords, y_coords);
158 center.
x(), center.
y(),
159 51.2f / second_moments.
x(),
160 51.2f / second_moments.
y(),
167 static uint8_t NormalizeDirection(uint8_t dir,
const FCOORD& unnormed_pos,
169 const DENORM* root_denorm) {
173 unnormed_end += unnormed_pos;
174 FCOORD normed_pos, normed_end;
175 denorm.
NormTransform(root_denorm, unnormed_pos, &normed_pos);
176 denorm.
NormTransform(root_denorm, unnormed_end, &normed_end);
177 normed_end -= normed_pos;
184 static FCOORD MeanDirectionVector(
const LLSQ& point_diffs,
const LLSQ& dirs,
188 if (dirs.
count() > 0) {
193 double mean_dir = 0.0;
195 mean_dir = mean_pt.
x();
197 mean_dir = mean_pt.
y() + 128;
204 FCOORD feature_dir(end_pt - start_pt);
206 if (fit_vector.
x() == 0.0f && fit_vector.
y() == 0.0f) {
208 fit_vector = feature_dir;
213 FCOORD fit_vector2 = !fit_vector;
216 if (fit_vector % feature_dir < 0.0)
217 fit_vector = -fit_vector;
218 if (fit_vector2 % feature_dir < 0.0)
219 fit_vector2 = -fit_vector2;
222 if (fit_vector2 % feature_dir > fit_vector % feature_dir)
223 fit_vector = fit_vector2;
233 static int ComputeFeatures(
const FCOORD& start_pt,
const FCOORD& end_pt,
234 double feature_length,
236 FCOORD feature_vector(end_pt - start_pt);
237 if (feature_vector.x() == 0.0f && feature_vector.y() == 0.0f)
return 0;
239 uint8_t theta = feature_vector.to_direction();
241 double target_length = feature_vector.length();
242 int num_features =
IntCastRounded(target_length / feature_length);
243 if (num_features == 0)
return 0;
245 double lambda_step = 1.0 / num_features;
246 double lambda = lambda_step / 2.0;
247 for (
int f = 0; f < num_features; ++f, lambda += lambda_step) {
248 FCOORD feature_pt(start_pt);
249 feature_pt += feature_vector * lambda;
270 static int GatherPoints(
const C_OUTLINE* outline,
double feature_length,
272 int start_index,
int end_index,
276 ICOORD step = outline->
step(start_index % step_length);
285 for (index = start_index; index <= end_index; ++index, *pos += step) {
286 step = outline->
step(index % step_length);
288 if (edge_weight == 0) {
295 if (num_points == 0) {
297 prev_normed = *pos_normed;
299 FCOORD offset = *pos_normed - prev_normed;
300 float length = offset.
length();
301 if (length > feature_length) {
307 points->
add(pos_normed->
x(), pos_normed->
y(), edge_weight);
309 if (direction >= 0) {
310 direction = NormalizeDirection(direction, f_pos, denorm, root_denorm);
313 dirs->
add(direction,
Modulo(direction + 128, 256));
326 static void ExtractFeaturesFromRun(
328 const DENORM& denorm,
double feature_length,
bool force_poly,
332 if (outline !=
nullptr && !force_poly) {
336 int total_features = 0;
346 if (end_index <= start_index)
347 end_index += step_length;
351 denorm.
NormTransform(root_denorm, prev_normed_pos, &prev_normed_pos);
354 FCOORD normed_pos(0.0f, 0.0f);
355 int index = GatherPoints(outline, feature_length, denorm, root_denorm,
356 start_index, end_index, &pos, &normed_pos,
358 while (index <= end_index) {
366 FCOORD next_normed_pos(0.0f, 0.0f);
367 index = GatherPoints(outline, feature_length, denorm, root_denorm,
368 index, end_index, &pos, &next_normed_pos,
369 &next_points, &next_dirs);
370 LLSQ sum_points(prev_points);
374 sum_points.add(points);
375 sum_points.add(next_points);
376 sum_dirs.add(next_dirs);
377 bool made_features =
false;
379 if (sum_points.count() > 0) {
381 FCOORD fit_pt = sum_points.mean_point();
382 FCOORD fit_vector = MeanDirectionVector(sum_points, sum_dirs,
383 prev_normed_pos, normed_pos);
391 if (total_features == 0 && startpt != endpt) {
395 if (index > end_index && startpt != endpt) {
399 int num_features = ComputeFeatures(start_pos, end_pos, feature_length,
401 if (num_features > 0) {
403 prev_points = points;
405 prev_normed_pos = normed_pos;
406 points = next_points;
408 made_features =
true;
409 total_features += num_features;
412 normed_pos = next_normed_pos;
414 if (!made_features) {
417 points.
add(next_points);
423 const EDGEPT* pt = startpt;
429 ComputeFeatures(start_pos, end_pos, feature_length, features);
430 }
while ((pt = pt->
next) != endpt);
448 DENORM bl_denorm, cn_denorm;
450 &bl_denorm, &cn_denorm, results);
451 if (outline_cn_counts !=
nullptr)
456 EDGEPT* loop_pt = ol->FindBestStartPt();
458 if (pt ==
nullptr)
continue;
464 last_pt = last_pt->
next;
465 }
while (last_pt != loop_pt && !last_pt->
IsHidden() &&
467 last_pt = last_pt->
prev;
475 }
while ((pt = pt->
next) != loop_pt);
476 if (outline_cn_counts !=
nullptr)
int IntCastRounded(double x)
FCOORD FeatureDirection(uint8_t theta)
const double kStandardFeatureLength
#define INT_CHAR_NORM_RANGE
TrainingSample * BlobToTrainingSample(const TBLOB &blob, bool nonlinear_norm, INT_FX_RESULT_STRUCT *fx_info, GenericVector< INT_FEATURE_STRUCT > *bl_features)
TBOX bounding_box() const
void GetEdgeCoords(const TBOX &box, GenericVector< GenericVector< int > > *x_coords, GenericVector< GenericVector< int > > *y_coords) const
int ComputeMoments(FCOORD *center, FCOORD *second_moments) const
const DENORM & denorm() const
void GetPreciseBoundingBox(TBOX *precise_box) const
ICOORD step(int index) const
int direction_at_index(int index) const
int edge_strength_at_index(int index) const
ICOORD position_at_index(int index) const
FCOORD sub_pixel_pos_at_index(const ICOORD &pos, int index) const
int32_t pathlength() const
double y_variance() const
double x_variance() const
void add(double x, double y)
FCOORD mean_point() const
FCOORD vector_fit() const
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)
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
const DENORM * RootDenorm() const
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) 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)
uint8_t to_direction() const
float length() const
find length
void from_direction(uint8_t direction)
FCOORD nearest_pt_on_line(const FCOORD &line_point, const FCOORD &dir_vector) const
void pad(int xpad, int ypad)
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)
static void SetupBLCNDenorms(const TBLOB &blob, bool nonlinear_norm, DENORM *bl_denorm, DENORM *cn_denorm, INT_FX_RESULT_STRUCT *fx_info)
static TrainingSample * CopyFromFeatures(const INT_FX_RESULT_STRUCT &fx_info, const TBOX &bounding_box, const INT_FEATURE_STRUCT *features, int num_features)