tesseract  4.1.1
pitsync1.h File Reference
#include "elst.h"
#include "clst.h"
#include "blobbox.h"
#include "params.h"
#include "statistc.h"
#include "pithsync.h"

Go to the source code of this file.

Classes

class  FPSEGPT
 

Functions

 ELISTIZEH (FPSEGPT) CLISTIZEH(FPSEGPT_LIST) extern int pitsync_linear_version=0
 
double check_pitch_sync (BLOBNBOX_IT *blob_it, int16_t blob_count, int16_t pitch, int16_t pitch_error, STATS *projection, FPSEGPT_LIST *seg_list)
 
void make_illegal_segment (FPSEGPT_LIST *prev_list, TBOX blob_box, BLOBNBOX_IT blob_it, int16_t region_index, int16_t pitch, int16_t pitch_error, FPSEGPT_LIST *seg_list)
 
int16_t vertical_torow_projection (TO_ROW *row, STATS *projection)
 
void vertical_cblob_projection (C_BLOB *blob, STATS *stats)
 
void vertical_coutline_projection (C_OUTLINE *outline, STATS *stats)
 

Variables

double pitsync_joined_edge = 0.75
 
double pitsync_offset_freecut_fraction = 0.25
 
int pitsync_fake_depth = 1
 

Function Documentation

◆ check_pitch_sync()

double check_pitch_sync ( BLOBNBOX_IT *  blob_it,
int16_t  blob_count,
int16_t  pitch,
int16_t  pitch_error,
STATS projection,
FPSEGPT_LIST *  seg_list 
)

Definition at line 143 of file pitsync1.cpp.

150  {
151  int16_t x; //current coord
152  int16_t min_index; //blob number
153  int16_t max_index; //blob number
154  int16_t left_edge; //of word
155  int16_t right_edge; //of word
156  int16_t right_max; //max allowed x
157  int16_t min_x; //in this region
158  int16_t max_x;
159  int16_t region_index;
160  int16_t best_region_index = 0; //for best result
161  int16_t offset; //dist to legal area
162  int16_t left_best_x; //edge of good region
163  int16_t right_best_x; //right edge
164  TBOX min_box; //bounding box
165  TBOX max_box; //bounding box
166  TBOX next_box; //box of next blob
167  FPSEGPT *segpt; //segment point
168  FPSEGPT_LIST *segpts; //points in a segment
169  double best_cost; //best path
170  double mean_sum; //computes result
171  FPSEGPT *best_end; //end of best path
172  BLOBNBOX_IT min_it; //copy iterator
173  BLOBNBOX_IT max_it; //copy iterator
174  FPSEGPT_IT segpt_it; //iterator
175  //output segments
176  FPSEGPT_IT outseg_it = seg_list;
177  FPSEGPT_LIST_CLIST lattice; //list of lists
178  //region iterator
179  FPSEGPT_LIST_C_IT lattice_it = &lattice;
180 
181  // tprintf("Computing sync on word of %d blobs with pitch %d\n",
182  // blob_count, pitch);
183  // if (blob_count==8 && pitch==27)
184  // projection->print(stdout,true);
185  if (pitch < 3)
186  pitch = 3; //nothing ludicrous
187  if ((pitch - 3) / 2 < pitch_error)
188  pitch_error = (pitch - 3) / 2;
189  min_it = *blob_it;
190  min_box = box_next (&min_it); //get box
191  // if (blob_count==8 && pitch==27)
192  // tprintf("1st box at (%d,%d)->(%d,%d)\n",
193  // min_box.left(),min_box.bottom(),
194  // min_box.right(),min_box.top());
195  //left of word
196  left_edge = min_box.left () + pitch_error;
197  for (min_index = 1; min_index < blob_count; min_index++) {
198  min_box = box_next (&min_it);
199  // if (blob_count==8 && pitch==27)
200  // tprintf("Box at (%d,%d)->(%d,%d)\n",
201  // min_box.left(),min_box.bottom(),
202  // min_box.right(),min_box.top());
203  }
204  right_edge = min_box.right (); //end of word
205  max_x = left_edge;
206  //min permissible
207  min_x = max_x - pitch + pitch_error * 2 + 1;
208  right_max = right_edge + pitch - pitch_error - 1;
209  segpts = new FPSEGPT_LIST; //list of points
210  segpt_it.set_to_list (segpts);
211  for (x = min_x; x <= max_x; x++) {
212  segpt = new FPSEGPT (x); //make a new one
213  //put in list
214  segpt_it.add_after_then_move (segpt);
215  }
216  //first segment
217  lattice_it.add_before_then_move (segpts);
218  min_index = 0;
219  region_index = 1;
220  best_cost = FLT_MAX;
221  best_end = nullptr;
222  min_it = *blob_it;
223  min_box = box_next (&min_it); //first box
224  do {
225  left_best_x = -1;
226  right_best_x = -1;
227  segpts = new FPSEGPT_LIST; //list of points
228  segpt_it.set_to_list (segpts);
229  min_x += pitch - pitch_error;//next limits
230  max_x += pitch + pitch_error;
231  while (min_box.right () < min_x && min_index < blob_count) {
232  min_index++;
233  min_box = box_next (&min_it);
234  }
235  max_it = min_it;
236  max_index = min_index;
237  max_box = min_box;
238  next_box = box_next (&max_it);
239  for (x = min_x; x <= max_x && x <= right_max; x++) {
240  while (x < right_edge && max_index < blob_count
241  && x > max_box.right ()) {
242  max_index++;
243  max_box = next_box;
244  next_box = box_next (&max_it);
245  }
246  if (x <= max_box.left () + pitch_error
247  || x >= max_box.right () - pitch_error || x >= right_edge
248  || (max_index < blob_count - 1 && x >= next_box.left ())
249  || (x - max_box.left () > pitch * pitsync_joined_edge
250  && max_box.right () - x > pitch * pitsync_joined_edge)) {
251  // || projection->local_min(x))
252  if (x - max_box.left () > 0
253  && x - max_box.left () <= pitch_error)
254  //dist to real break
255  offset = x - max_box.left ();
256  else if (max_box.right () - x > 0
257  && max_box.right () - x <= pitch_error
258  && (max_index >= blob_count - 1
259  || x < next_box.left ()))
260  offset = max_box.right () - x;
261  else
262  offset = 0;
263  // offset=pitsync_offset_freecut_fraction*projection->pile_count(x);
264  segpt = new FPSEGPT (x, false, offset, region_index,
265  pitch, pitch_error, lattice_it.data ());
266  }
267  else {
268  offset = projection->pile_count (x);
269  segpt = new FPSEGPT (x, true, offset, region_index,
270  pitch, pitch_error, lattice_it.data ());
271  }
272  if (segpt->previous () != nullptr) {
273  segpt_it.add_after_then_move (segpt);
274  if (x >= right_edge - pitch_error) {
275  segpt->terminal = true;//no more wanted
276  if (segpt->cost_function () < best_cost) {
277  best_cost = segpt->cost_function ();
278  //find least
279  best_end = segpt;
280  best_region_index = region_index;
281  left_best_x = x;
282  right_best_x = x;
283  }
284  else if (segpt->cost_function () == best_cost
285  && right_best_x == x - 1)
286  right_best_x = x;
287  }
288  }
289  else {
290  delete segpt; //no good
291  }
292  }
293  if (segpts->empty ()) {
294  if (best_end != nullptr)
295  break; //already found one
296  make_illegal_segment (lattice_it.data (), min_box, min_it,
297  region_index, pitch, pitch_error, segpts);
298  }
299  else {
300  if (right_best_x > left_best_x + 1) {
301  left_best_x = (left_best_x + right_best_x + 1) / 2;
302  for (segpt_it.mark_cycle_pt (); !segpt_it.cycled_list ()
303  && segpt_it.data ()->position () != left_best_x;
304  segpt_it.forward ());
305  if (segpt_it.data ()->position () == left_best_x)
306  //middle of region
307  best_end = segpt_it.data ();
308  }
309  }
310  //new segment
311  lattice_it.add_before_then_move (segpts);
312  region_index++;
313  }
314  while (min_x < right_edge);
315  ASSERT_HOST (best_end != nullptr);//must always find some
316 
317  for (lattice_it.mark_cycle_pt (); !lattice_it.cycled_list ();
318  lattice_it.forward ()) {
319  segpts = lattice_it.data ();
320  segpt_it.set_to_list (segpts);
321  // if (blob_count==8 && pitch==27)
322  // {
323  // for (segpt_it.mark_cycle_pt();!segpt_it.cycled_list();segpt_it.forward())
324  // {
325  // segpt=segpt_it.data();
326  // tprintf("At %d, (%x) cost=%g, m=%g, sq=%g, pred=%x\n",
327  // segpt->position(),segpt,segpt->cost_function(),
328  // segpt->sum(),segpt->squares(),segpt->previous());
329  // }
330  // tprintf("\n");
331  // }
332  for (segpt_it.mark_cycle_pt (); !segpt_it.cycled_list ()
333  && segpt_it.data () != best_end; segpt_it.forward ());
334  if (segpt_it.data () == best_end) {
335  //save good one
336  segpt = segpt_it.extract ();
337  outseg_it.add_before_then_move (segpt);
338  best_end = segpt->previous ();
339  }
340  }
341  ASSERT_HOST (best_end == nullptr);
342  ASSERT_HOST (!outseg_it.empty ());
343  outseg_it.move_to_last ();
344  mean_sum = outseg_it.data ()->sum ();
345  mean_sum = mean_sum * mean_sum / best_region_index;
346  if (outseg_it.data ()->squares () - mean_sum < 0)
347  tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
348  outseg_it.data ()->squares (), outseg_it.data ()->sum (),
349  best_region_index);
350  lattice.deep_clear (); //shift the lot
351  return outseg_it.data ()->squares () - mean_sum;
352 }
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:35
FPSEGPT * previous()
Definition: pitsync1.h:60
int16_t left() const
Definition: rect.h:72
TBOX box_next(BLOBNBOX_IT *it)
Definition: blobbox.cpp:636
double pitsync_joined_edge
Definition: pitsync1.cpp:26
void make_illegal_segment(FPSEGPT_LIST *prev_list, TBOX blob_box, BLOBNBOX_IT blob_it, int16_t region_index, int16_t pitch, int16_t pitch_error, FPSEGPT_LIST *seg_list)
Definition: pitsync1.cpp:361
bool terminal
Definition: pitsync1.h:68
int32_t pile_count(int32_t value) const
Definition: statistc.h:76
Definition: rect.h:34
double cost_function()
Definition: pitsync1.h:51
int16_t right() const
Definition: rect.h:79
#define ASSERT_HOST(x)
Definition: errcode.h:88

◆ ELISTIZEH()

ELISTIZEH ( FPSEGPT  )
pure virtual

"Use new fast algorithm"

◆ make_illegal_segment()

void make_illegal_segment ( FPSEGPT_LIST *  prev_list,
TBOX  blob_box,
BLOBNBOX_IT  blob_it,
int16_t  region_index,
int16_t  pitch,
int16_t  pitch_error,
FPSEGPT_LIST *  seg_list 
)

Definition at line 361 of file pitsync1.cpp.

369  {
370  int16_t x; //current coord
371  int16_t min_x = 0; //in this region
372  int16_t max_x = 0;
373  int16_t offset; //dist to edge
374  FPSEGPT *segpt; //segment point
375  FPSEGPT *prevpt; //previous point
376  float best_cost; //best path
377  FPSEGPT_IT segpt_it = seg_list;//iterator
378  //previous points
379  FPSEGPT_IT prevpt_it = prev_list;
380 
381  best_cost = FLT_MAX;
382  for (prevpt_it.mark_cycle_pt (); !prevpt_it.cycled_list ();
383  prevpt_it.forward ()) {
384  prevpt = prevpt_it.data ();
385  if (prevpt->cost_function () < best_cost) {
386  //find least
387  best_cost = prevpt->cost_function ();
388  min_x = prevpt->position ();
389  max_x = min_x; //limits on coords
390  }
391  else if (prevpt->cost_function () == best_cost) {
392  max_x = prevpt->position ();
393  }
394  }
395  min_x += pitch - pitch_error;
396  max_x += pitch + pitch_error;
397  for (x = min_x; x <= max_x; x++) {
398  while (x > blob_box.right ()) {
399  blob_box = box_next (&blob_it);
400  }
401  offset = x - blob_box.left ();
402  if (blob_box.right () - x < offset)
403  offset = blob_box.right () - x;
404  segpt = new FPSEGPT (x, false, offset,
405  region_index, pitch, pitch_error, prev_list);
406  if (segpt->previous () != nullptr) {
407  ASSERT_HOST (offset >= 0);
408  fprintf (stderr, "made fake at %d\n", x);
409  //make one up
410  segpt_it.add_after_then_move (segpt);
411  segpt->faked = true;
412  segpt->fake_count++;
413  }
414  else
415  delete segpt;
416  }
417 }
FPSEGPT * previous()
Definition: pitsync1.h:60
int32_t position()
Definition: pitsync1.h:48
int16_t left() const
Definition: rect.h:72
int16_t fake_count
Definition: pitsync1.h:69
TBOX box_next(BLOBNBOX_IT *it)
Definition: blobbox.cpp:636
double cost_function()
Definition: pitsync1.h:51
int16_t right() const
Definition: rect.h:79
#define ASSERT_HOST(x)
Definition: errcode.h:88
bool faked
Definition: pitsync1.h:67

◆ vertical_cblob_projection()

void vertical_cblob_projection ( C_BLOB blob,
STATS stats 
)

Definition at line 868 of file blobbox.cpp.

871  {
872  //outlines of blob
873  C_OUTLINE_IT out_it = blob->out_list ();
874 
875  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
876  vertical_coutline_projection (out_it.data (), stats);
877  }
878 }
C_OUTLINE_LIST * out_list()
Definition: stepblob.h:70
void vertical_coutline_projection(C_OUTLINE *outline, STATS *stats)
Definition: blobbox.cpp:888

◆ vertical_coutline_projection()

void vertical_coutline_projection ( C_OUTLINE outline,
STATS stats 
)

Definition at line 888 of file blobbox.cpp.

891  {
892  ICOORD pos; //current point
893  ICOORD step; //edge step
894  int32_t length; //of outline
895  int16_t stepindex; //current step
896  C_OUTLINE_IT out_it = outline->child ();
897 
898  pos = outline->start_pos ();
899  length = outline->pathlength ();
900  for (stepindex = 0; stepindex < length; stepindex++) {
901  step = outline->step (stepindex);
902  if (step.x () > 0) {
903  stats->add (pos.x (), -pos.y ());
904  } else if (step.x () < 0) {
905  stats->add (pos.x () - 1, pos.y ());
906  }
907  pos += step;
908  }
909 
910  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
911  vertical_coutline_projection (out_it.data (), stats);
912  }
913 }
integer coordinate
Definition: points.h:31
C_OUTLINE_LIST * child()
Definition: coutln.h:108
void add(int32_t value, int32_t count)
Definition: statistc.cpp:93
int32_t pathlength() const
Definition: coutln.h:135
int16_t x() const
access function
Definition: points.h:52
const ICOORD & start_pos() const
Definition: coutln.h:148
ICOORD step(int index) const
Definition: coutln.h:144
int16_t y() const
access_function
Definition: points.h:56
void vertical_coutline_projection(C_OUTLINE *outline, STATS *stats)
Definition: blobbox.cpp:888

◆ vertical_torow_projection()

int16_t vertical_torow_projection ( TO_ROW row,
STATS projection 
)

Variable Documentation

◆ pitsync_fake_depth

int pitsync_fake_depth = 1

"Max advance fake generation"

Definition at line 29 of file pitsync1.cpp.

◆ pitsync_joined_edge

double pitsync_joined_edge = 0.75

"Dist inside big blob for chopping"

Definition at line 26 of file pitsync1.cpp.

◆ pitsync_offset_freecut_fraction

double pitsync_offset_freecut_fraction = 0.25

"Fraction of cut for free cuts"

Definition at line 28 of file pitsync1.cpp.