tesseract  4.0.0-1-g2a2b
pitsync1.cpp File Reference
#include <cfloat>
#include <cmath>
#include "pitsync1.h"

Go to the source code of this file.

Functions

 ELISTIZE (FPSEGPT) CLISTIZE(FPSEGPT_LIST) int pitsync_linear_version
 
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)
 

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 144 of file pitsync1.cpp.

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

◆ ELISTIZE()

ELISTIZE ( FPSEGPT  )

"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 362 of file pitsync1.cpp.

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

Variable Documentation

◆ pitsync_fake_depth

int pitsync_fake_depth = 1

"Max advance fake generation"

Definition at line 30 of file pitsync1.cpp.

◆ pitsync_joined_edge

double pitsync_joined_edge = 0.75

"Dist inside big blob for chopping"

Definition at line 27 of file pitsync1.cpp.

◆ pitsync_offset_freecut_fraction

double pitsync_offset_freecut_fraction = 0.25

"Fraction of cut for free cuts"

Definition at line 29 of file pitsync1.cpp.