tesseract  5.0.0-alpha-619-ge9db
pithsync.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: pithsync.cpp (Formerly pitsync2.c)
3  * Description: Code to find the optimum fixed pitch segmentation of some blobs.
4  * Author: Ray Smith
5  *
6  * (C) Copyright 1992, Hewlett-Packard Ltd.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  *
17  **********************************************************************/
18 
19 #include <cmath>
20 #include <cfloat> // for FLT_MAX
21 #include <vector> // for std::vector
22 #include "makerow.h"
23 #include "pitsync1.h"
24 #include "topitch.h"
25 #include "pithsync.h"
26 #include "tprintf.h"
27 
28 /**********************************************************************
29  * FPCUTPT::setup
30  *
31  * Constructor to make a new FPCUTPT.
32  **********************************************************************/
33 
34 void FPCUTPT::setup( //constructor
35  FPCUTPT *cutpts, //predecessors
36  int16_t array_origin, //start coord
37  STATS *projection, //vertical occupation
38  int16_t zero_count, //official zero
39  int16_t pitch, //proposed pitch
40  int16_t x, //position
41  int16_t offset //dist to gap
42  ) {
43  //half of pitch
44  int16_t half_pitch = pitch / 2 - 1;
45  uint32_t lead_flag; //new flag
46  int32_t ind; //current position
47 
48  if (half_pitch > 31)
49  half_pitch = 31;
50  else if (half_pitch < 0)
51  half_pitch = 0;
52  lead_flag = 1 << half_pitch;
53 
54  pred = nullptr;
55  mean_sum = 0;
56  sq_sum = offset * offset;
57  cost = sq_sum;
58  faked = false;
59  terminal = false;
60  fake_count = 0;
61  xpos = x;
62  region_index = 0;
63  mid_cuts = 0;
64  if (x == array_origin) {
65  back_balance = 0;
66  fwd_balance = 0;
67  for (ind = 0; ind <= half_pitch; ind++) {
68  fwd_balance >>= 1;
69  if (projection->pile_count (ind) > zero_count)
70  fwd_balance |= lead_flag;
71  }
72  }
73  else {
74  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
75  back_balance &= lead_flag + lead_flag - 1;
76  if (projection->pile_count (x) > zero_count)
77  back_balance |= 1;
78  fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
79  if (projection->pile_count (x + half_pitch) > zero_count)
80  fwd_balance |= lead_flag;
81  }
82 }
83 
84 
85 /**********************************************************************
86  * FPCUTPT::assign
87  *
88  * Constructor to make a new FPCUTPT.
89  **********************************************************************/
90 
91 void FPCUTPT::assign( //constructor
92  FPCUTPT* cutpts, //predecessors
93  int16_t array_origin, //start coord
94  int16_t x, //position
95  bool faking, //faking this one
96  bool mid_cut, //cheap cut.
97  int16_t offset, //dist to gap
98  STATS* projection, //vertical occupation
99  float projection_scale, //scaling
100  int16_t zero_count, //official zero
101  int16_t pitch, //proposed pitch
102  int16_t pitch_error //allowed tolerance
103 ) {
104  int index; //test index
105  int balance_index; //for balance factor
106  int16_t balance_count; //ding factor
107  int16_t r_index; //test cut number
108  FPCUTPT *segpt; //segment point
109  int32_t dist; //from prev segment
110  double sq_dist; //squared distance
111  double mean; //mean pitch
112  double total; //total dists
113  double factor; //cost function
114  //half of pitch
115  int16_t half_pitch = pitch / 2 - 1;
116  uint32_t lead_flag; //new flag
117 
118  if (half_pitch > 31)
119  half_pitch = 31;
120  else if (half_pitch < 0)
121  half_pitch = 0;
122  lead_flag = 1 << half_pitch;
123 
124  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
125  back_balance &= lead_flag + lead_flag - 1;
126  if (projection->pile_count (x) > zero_count)
127  back_balance |= 1;
128  fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
129  if (projection->pile_count (x + half_pitch) > zero_count)
130  fwd_balance |= lead_flag;
131 
132  xpos = x;
133  cost = FLT_MAX;
134  pred = nullptr;
135  faked = faking;
136  terminal = false;
137  region_index = 0;
138  fake_count = INT16_MAX;
139  for (index = x - pitch - pitch_error; index <= x - pitch + pitch_error;
140  index++) {
141  if (index >= array_origin) {
142  segpt = &cutpts[index - array_origin];
143  dist = x - segpt->xpos;
144  if (!segpt->terminal && segpt->fake_count < INT16_MAX) {
145  balance_count = 0;
146  if (textord_balance_factor > 0) {
148  lead_flag = back_balance ^ segpt->fwd_balance;
149  balance_count = 0;
150  while (lead_flag != 0) {
151  balance_count++;
152  lead_flag &= lead_flag - 1;
153  }
154  }
155  else {
156  for (balance_index = 0;
157  index + balance_index < x - balance_index;
158  balance_index++)
159  balance_count +=
160  (projection->pile_count (index + balance_index) <=
161  zero_count) ^ (projection->pile_count (x -
162  balance_index)
163  <= zero_count);
164  }
165  balance_count =
166  static_cast<int16_t>(balance_count * textord_balance_factor /
167  projection_scale);
168  }
169  r_index = segpt->region_index + 1;
170  total = segpt->mean_sum + dist;
171  balance_count += offset;
172  sq_dist =
173  dist * dist + segpt->sq_sum + balance_count * balance_count;
174  mean = total / r_index;
175  factor = mean - pitch;
176  factor *= factor;
177  factor += sq_dist / (r_index) - mean * mean;
178  if (factor < cost && segpt->fake_count + faked <= fake_count) {
179  cost = factor; //find least cost
180  pred = segpt; //save path
181  mean_sum = total;
182  sq_sum = sq_dist;
183  fake_count = segpt->fake_count + faked;
184  mid_cuts = segpt->mid_cuts + mid_cut;
185  region_index = r_index;
186  }
187  }
188  }
189  }
190 }
191 
192 
193 /**********************************************************************
194  * FPCUTPT::assign_cheap
195  *
196  * Constructor to make a new FPCUTPT on the cheap.
197  **********************************************************************/
198 
199 void FPCUTPT::assign_cheap( //constructor
200  FPCUTPT *cutpts, //predecessors
201  int16_t array_origin, //start coord
202  int16_t x, //position
203  bool faking, //faking this one
204  bool mid_cut, //cheap cut.
205  int16_t offset, //dist to gap
206  STATS *projection, //vertical occupation
207  float projection_scale, //scaling
208  int16_t zero_count, //official zero
209  int16_t pitch, //proposed pitch
210  int16_t pitch_error //allowed tolerance
211  ) {
212  int index; //test index
213  int16_t balance_count; //ding factor
214  int16_t r_index; //test cut number
215  FPCUTPT *segpt; //segment point
216  int32_t dist; //from prev segment
217  double sq_dist; //squared distance
218  double mean; //mean pitch
219  double total; //total dists
220  double factor; //cost function
221  //half of pitch
222  int16_t half_pitch = pitch / 2 - 1;
223  uint32_t lead_flag; //new flag
224 
225  if (half_pitch > 31)
226  half_pitch = 31;
227  else if (half_pitch < 0)
228  half_pitch = 0;
229  lead_flag = 1 << half_pitch;
230 
231  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
232  back_balance &= lead_flag + lead_flag - 1;
233  if (projection->pile_count (x) > zero_count)
234  back_balance |= 1;
235  fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
236  if (projection->pile_count (x + half_pitch) > zero_count)
237  fwd_balance |= lead_flag;
238 
239  xpos = x;
240  cost = FLT_MAX;
241  pred = nullptr;
242  faked = faking;
243  terminal = false;
244  region_index = 0;
245  fake_count = INT16_MAX;
246  index = x - pitch;
247  if (index >= array_origin) {
248  segpt = &cutpts[index - array_origin];
249  dist = x - segpt->xpos;
250  if (!segpt->terminal && segpt->fake_count < INT16_MAX) {
251  balance_count = 0;
252  if (textord_balance_factor > 0) {
253  lead_flag = back_balance ^ segpt->fwd_balance;
254  balance_count = 0;
255  while (lead_flag != 0) {
256  balance_count++;
257  lead_flag &= lead_flag - 1;
258  }
259  balance_count = static_cast<int16_t>(balance_count * textord_balance_factor
260  / projection_scale);
261  }
262  r_index = segpt->region_index + 1;
263  total = segpt->mean_sum + dist;
264  balance_count += offset;
265  sq_dist =
266  dist * dist + segpt->sq_sum + balance_count * balance_count;
267  mean = total / r_index;
268  factor = mean - pitch;
269  factor *= factor;
270  factor += sq_dist / (r_index) - mean * mean;
271  cost = factor; //find least cost
272  pred = segpt; //save path
273  mean_sum = total;
274  sq_sum = sq_dist;
275  fake_count = segpt->fake_count + faked;
276  mid_cuts = segpt->mid_cuts + mid_cut;
277  region_index = r_index;
278  }
279  }
280 }
281 
282 
283 /**********************************************************************
284  * check_pitch_sync
285  *
286  * Construct the lattice of possible segmentation points and choose the
287  * optimal path. Return the optimal path only.
288  * The return value is a measure of goodness of the sync.
289  **********************************************************************/
290 
291 double check_pitch_sync2( //find segmentation
292  BLOBNBOX_IT *blob_it, //blobs to do
293  int16_t blob_count, //no of blobs
294  int16_t pitch, //pitch estimate
295  int16_t pitch_error, //tolerance
296  STATS *projection, //vertical
297  int16_t projection_left, //edges //scale factor
298  int16_t projection_right,
299  float projection_scale,
300  int16_t &occupation_count, //no of occupied cells
301  FPSEGPT_LIST *seg_list, //output list
302  int16_t start, //start of good range
303  int16_t end //end of good range
304  ) {
305  bool faking; //illegal cut pt
306  bool mid_cut; //cheap cut pt.
307  int16_t x; //current coord
308  int16_t blob_index; //blob number
309  int16_t left_edge; //of word
310  int16_t right_edge; //of word
311  int16_t array_origin; //x coord of array
312  int16_t offset; //dist to legal area
313  int16_t zero_count; //projection zero
314  int16_t best_left_x = 0; //for equals
315  int16_t best_right_x = 0; //right edge
316  TBOX this_box; //bounding box
317  TBOX next_box; //box of next blob
318  FPSEGPT *segpt; //segment point
319  double best_cost; //best path
320  double mean_sum; //computes result
321  FPCUTPT *best_end; //end of best path
322  int16_t best_fake; //best fake level
323  int16_t best_count; //no of cuts
324  BLOBNBOX_IT this_it; //copy iterator
325  FPSEGPT_IT seg_it = seg_list; //output iterator
326 
327  // tprintf("Computing sync on word of %d blobs with pitch %d\n",
328  // blob_count, pitch);
329  // if (blob_count==8 && pitch==27)
330  // projection->print(stdout,true);
331  zero_count = 0;
332  if (pitch < 3)
333  pitch = 3; //nothing ludicrous
334  if ((pitch - 3) / 2 < pitch_error)
335  pitch_error = (pitch - 3) / 2;
336  this_it = *blob_it;
337  this_box = box_next (&this_it);//get box
338  // left_edge=this_box.left(); //left of word
339  // right_edge=this_box.right();
340  // for (blob_index=1;blob_index<blob_count;blob_index++)
341  // {
342  // this_box=box_next(&this_it);
343  // if (this_box.right()>right_edge)
344  // right_edge=this_box.right();
345  // }
346  for (left_edge = projection_left; projection->pile_count (left_edge) == 0
347  && left_edge < projection_right; left_edge++);
348  for (right_edge = projection_right; projection->pile_count (right_edge) == 0
349  && right_edge > left_edge; right_edge--);
350  ASSERT_HOST (right_edge >= left_edge);
351  if (pitsync_linear_version >= 4)
352  return check_pitch_sync3 (projection_left, projection_right, zero_count,
353  pitch, pitch_error, projection,
354  projection_scale, occupation_count, seg_list,
355  start, end);
356  array_origin = left_edge - pitch;
357  // array of points
358  std::vector<FPCUTPT> cutpts(right_edge - left_edge + pitch * 2 + 1);
359  for (x = array_origin; x < left_edge; x++)
360  //free cuts
361  cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
362  zero_count, pitch, x, 0);
363  for (offset = 0; offset <= pitch_error; offset++, x++)
364  //not quite free
365  cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
366  zero_count, pitch, x, offset);
367 
368  this_it = *blob_it;
369  best_cost = FLT_MAX;
370  best_end = nullptr;
371  this_box = box_next (&this_it);//first box
372  next_box = box_next (&this_it);//second box
373  blob_index = 1;
374  while (x < right_edge - pitch_error) {
375  if (x > this_box.right () + pitch_error && blob_index < blob_count) {
376  this_box = next_box;
377  next_box = box_next (&this_it);
378  blob_index++;
379  }
380  faking = false;
381  mid_cut = false;
382  if (x <= this_box.left ())
383  offset = 0;
384  else if (x <= this_box.left () + pitch_error)
385  offset = x - this_box.left ();
386  else if (x >= this_box.right ())
387  offset = 0;
388  else if (x >= next_box.left () && blob_index < blob_count) {
389  offset = x - next_box.left ();
390  if (this_box.right () - x < offset)
391  offset = this_box.right () - x;
392  }
393  else if (x >= this_box.right () - pitch_error)
394  offset = this_box.right () - x;
395  else if (x - this_box.left () > pitch * pitsync_joined_edge
396  && this_box.right () - x > pitch * pitsync_joined_edge) {
397  mid_cut = true;
398  offset = 0;
399  }
400  else {
401  faking = true;
402  offset = projection->pile_count (x);
403  }
404  cutpts[x - array_origin].assign (&cutpts[0], array_origin, x,
405  faking, mid_cut, offset, projection,
406  projection_scale, zero_count, pitch,
407  pitch_error);
408  x++;
409  }
410 
411  best_fake = INT16_MAX;
412  best_cost = INT32_MAX;
413  best_count = INT16_MAX;
414  while (x < right_edge + pitch) {
415  offset = x < right_edge ? right_edge - x : 0;
416  cutpts[x - array_origin].assign (&cutpts[0], array_origin, x,
417  false, false, offset, projection,
418  projection_scale, zero_count, pitch,
419  pitch_error);
420  cutpts[x - array_origin].terminal = true;
421  if (cutpts[x - array_origin].index () +
422  cutpts[x - array_origin].fake_count <= best_count + best_fake) {
423  if (cutpts[x - array_origin].fake_count < best_fake
424  || (cutpts[x - array_origin].fake_count == best_fake
425  && cutpts[x - array_origin].cost_function () < best_cost)) {
426  best_fake = cutpts[x - array_origin].fake_count;
427  best_cost = cutpts[x - array_origin].cost_function ();
428  best_left_x = x;
429  best_right_x = x;
430  best_count = cutpts[x - array_origin].index ();
431  }
432  else if (cutpts[x - array_origin].fake_count == best_fake
433  && x == best_right_x + 1
434  && cutpts[x - array_origin].cost_function () == best_cost) {
435  //exactly equal
436  best_right_x = x;
437  }
438  }
439  x++;
440  }
441  ASSERT_HOST (best_fake < INT16_MAX);
442 
443  best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
444  if (this_box.right () == textord_test_x
445  && this_box.top () == textord_test_y) {
446  for (x = left_edge - pitch; x < right_edge + pitch; x++) {
447  tprintf ("x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
448  x, cutpts[x - array_origin].cost_function (),
449  cutpts[x - array_origin].sum (),
450  cutpts[x - array_origin].squares (),
451  cutpts[x - array_origin].previous ()->position ());
452  }
453  }
454  occupation_count = -1;
455  do {
456  for (x = best_end->position () - pitch + pitch_error;
457  x < best_end->position () - pitch_error
458  && projection->pile_count (x) == 0; x++);
459  if (x < best_end->position () - pitch_error)
460  occupation_count++;
461  //copy it
462  segpt = new FPSEGPT (best_end);
463  seg_it.add_before_then_move (segpt);
464  best_end = best_end->previous ();
465  }
466  while (best_end != nullptr);
467  seg_it.move_to_last ();
468  mean_sum = seg_it.data ()->sum ();
469  mean_sum = mean_sum * mean_sum / best_count;
470  if (seg_it.data ()->squares () - mean_sum < 0)
471  tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
472  seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
473  // tprintf("blob_count=%d, pitch=%d, sync=%g, occ=%d\n",
474  // blob_count,pitch,seg_it.data()->squares()-mean_sum,
475  // occupation_count);
476  return seg_it.data ()->squares () - mean_sum;
477 }
478 
479 
480 /**********************************************************************
481  * check_pitch_sync
482  *
483  * Construct the lattice of possible segmentation points and choose the
484  * optimal path. Return the optimal path only.
485  * The return value is a measure of goodness of the sync.
486  **********************************************************************/
487 
488 double check_pitch_sync3( //find segmentation
489  int16_t projection_left, //edges //to be considered 0
490  int16_t projection_right,
491  int16_t zero_count,
492  int16_t pitch, //pitch estimate
493  int16_t pitch_error, //tolerance
494  STATS *projection, //vertical
495  float projection_scale, //scale factor
496  int16_t &occupation_count, //no of occupied cells
497  FPSEGPT_LIST *seg_list, //output list
498  int16_t start, //start of good range
499  int16_t end //end of good range
500  ) {
501  bool faking; //illegal cut pt
502  bool mid_cut; //cheap cut pt.
503  int16_t left_edge; //of word
504  int16_t right_edge; //of word
505  int16_t x; //current coord
506  int16_t array_origin; //x coord of array
507  int16_t offset; //dist to legal area
508  int16_t projection_offset; //from scaled projection
509  int16_t prev_zero; //previous zero dist
510  int16_t next_zero; //next zero dist
511  int16_t zero_offset; //scan window
512  int16_t best_left_x = 0; //for equals
513  int16_t best_right_x = 0; //right edge
514  FPSEGPT *segpt; //segment point
515  int minindex; //next input position
516  int test_index; //index to mins
517  double best_cost; //best path
518  double mean_sum; //computes result
519  FPCUTPT *best_end; //end of best path
520  int16_t best_fake; //best fake level
521  int16_t best_count; //no of cuts
522  FPSEGPT_IT seg_it = seg_list; //output iterator
523 
524  end = (end - start) % pitch;
525  if (pitch < 3)
526  pitch = 3; //nothing ludicrous
527  if ((pitch - 3) / 2 < pitch_error)
528  pitch_error = (pitch - 3) / 2;
529  //min dist of zero
530  zero_offset = static_cast<int16_t>(pitch * pitsync_joined_edge);
531  for (left_edge = projection_left; projection->pile_count (left_edge) == 0
532  && left_edge < projection_right; left_edge++);
533  for (right_edge = projection_right; projection->pile_count (right_edge) == 0
534  && right_edge > left_edge; right_edge--);
535  array_origin = left_edge - pitch;
536  // array of points
537  std::vector<FPCUTPT> cutpts(right_edge - left_edge + pitch * 2 + 1);
538  // local min results
539  std::vector<bool> mins(pitch_error * 2 + 1);
540  for (x = array_origin; x < left_edge; x++)
541  //free cuts
542  cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
543  zero_count, pitch, x, 0);
544  prev_zero = left_edge - 1;
545  for (offset = 0; offset <= pitch_error; offset++, x++)
546  //not quite free
547  cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
548  zero_count, pitch, x, offset);
549 
550  best_cost = FLT_MAX;
551  best_end = nullptr;
552  for (offset = -pitch_error, minindex = 0; offset < pitch_error;
553  offset++, minindex++)
554  mins[minindex] = projection->local_min (x + offset);
555  next_zero = x + zero_offset + 1;
556  for (offset = next_zero - 1; offset >= x; offset--) {
557  if (projection->pile_count (offset) <= zero_count) {
558  next_zero = offset;
559  break;
560  }
561  }
562  while (x < right_edge - pitch_error) {
563  mins[minindex] = projection->local_min (x + pitch_error);
564  minindex++;
565  if (minindex > pitch_error * 2)
566  minindex = 0;
567  faking = false;
568  mid_cut = false;
569  offset = 0;
570  if (projection->pile_count (x) <= zero_count) {
571  prev_zero = x;
572  }
573  else {
574  for (offset = 1; offset <= pitch_error; offset++)
575  if (projection->pile_count (x + offset) <= zero_count
576  || projection->pile_count (x - offset) <= zero_count)
577  break;
578  }
579  if (offset > pitch_error) {
580  if (x - prev_zero > zero_offset && next_zero - x > zero_offset) {
581  for (offset = 0; offset <= pitch_error; offset++) {
582  test_index = minindex + pitch_error + offset;
583  if (test_index > pitch_error * 2)
584  test_index -= pitch_error * 2 + 1;
585  if (mins[test_index])
586  break;
587  test_index = minindex + pitch_error - offset;
588  if (test_index > pitch_error * 2)
589  test_index -= pitch_error * 2 + 1;
590  if (mins[test_index])
591  break;
592  }
593  }
594  if (offset > pitch_error) {
595  offset = projection->pile_count (x);
596  faking = true;
597  }
598  else {
599  projection_offset =
600  static_cast<int16_t>(projection->pile_count (x) / projection_scale);
601  if (projection_offset > offset)
602  offset = projection_offset;
603  mid_cut = true;
604  }
605  }
606  if ((start == 0 && end == 0)
608  || (x - projection_left - start) % pitch <= end)
609  cutpts[x - array_origin].assign(&cutpts[0], array_origin, x,
610  faking, mid_cut, offset, projection,
611  projection_scale, zero_count, pitch,
612  pitch_error);
613  else
614  cutpts[x - array_origin].assign_cheap(&cutpts[0], array_origin, x,
615  faking, mid_cut, offset,
616  projection, projection_scale,
617  zero_count, pitch,
618  pitch_error);
619  x++;
620  if (next_zero < x || next_zero == x + zero_offset)
621  next_zero = x + zero_offset + 1;
622  if (projection->pile_count (x + zero_offset) <= zero_count)
623  next_zero = x + zero_offset;
624  }
625 
626  best_fake = INT16_MAX;
627  best_cost = INT32_MAX;
628  best_count = INT16_MAX;
629  while (x < right_edge + pitch) {
630  offset = x < right_edge ? right_edge - x : 0;
631  cutpts[x - array_origin].assign(&cutpts[0], array_origin, x,
632  false, false, offset, projection,
633  projection_scale, zero_count, pitch,
634  pitch_error);
635  cutpts[x - array_origin].terminal = true;
636  if (cutpts[x - array_origin].index () +
637  cutpts[x - array_origin].fake_count <= best_count + best_fake) {
638  if (cutpts[x - array_origin].fake_count < best_fake
639  || (cutpts[x - array_origin].fake_count == best_fake
640  && cutpts[x - array_origin].cost_function () < best_cost)) {
641  best_fake = cutpts[x - array_origin].fake_count;
642  best_cost = cutpts[x - array_origin].cost_function ();
643  best_left_x = x;
644  best_right_x = x;
645  best_count = cutpts[x - array_origin].index ();
646  }
647  else if (cutpts[x - array_origin].fake_count == best_fake
648  && x == best_right_x + 1
649  && cutpts[x - array_origin].cost_function () == best_cost) {
650  //exactly equal
651  best_right_x = x;
652  }
653  }
654  x++;
655  }
656  ASSERT_HOST (best_fake < INT16_MAX);
657 
658  best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
659  // for (x=left_edge-pitch;x<right_edge+pitch;x++)
660  // {
661  // tprintf("x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
662  // x,cutpts[x-array_origin].cost_function(),
663  // cutpts[x-array_origin].sum(),
664  // cutpts[x-array_origin].squares(),
665  // cutpts[x-array_origin].previous()->position());
666  // }
667  occupation_count = -1;
668  do {
669  for (x = best_end->position () - pitch + pitch_error;
670  x < best_end->position () - pitch_error
671  && projection->pile_count (x) == 0; x++);
672  if (x < best_end->position () - pitch_error)
673  occupation_count++;
674  //copy it
675  segpt = new FPSEGPT (best_end);
676  seg_it.add_before_then_move (segpt);
677  best_end = best_end->previous ();
678  }
679  while (best_end != nullptr);
680  seg_it.move_to_last ();
681  mean_sum = seg_it.data ()->sum ();
682  mean_sum = mean_sum * mean_sum / best_count;
683  if (seg_it.data ()->squares () - mean_sum < 0)
684  tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
685  seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
686  return seg_it.data ()->squares () - mean_sum;
687 }
pitsync_joined_edge
double pitsync_joined_edge
Definition: pitsync1.cpp:25
check_pitch_sync3
double check_pitch_sync3(int16_t projection_left, int16_t projection_right, int16_t zero_count, int16_t pitch, int16_t pitch_error, STATS *projection, float projection_scale, int16_t &occupation_count, FPSEGPT_LIST *seg_list, int16_t start, int16_t end)
Definition: pithsync.cpp:482
check_pitch_sync2
double check_pitch_sync2(BLOBNBOX_IT *blob_it, int16_t blob_count, int16_t pitch, int16_t pitch_error, STATS *projection, int16_t projection_left, int16_t projection_right, float projection_scale, int16_t &occupation_count, FPSEGPT_LIST *seg_list, int16_t start, int16_t end)
Definition: pithsync.cpp:286
pithsync.h
textord_balance_factor
double textord_balance_factor
Definition: topitch.cpp:53
FPCUTPT::fake_count
int16_t fake_count
Definition: pithsync.h:90
ASSERT_HOST
#define ASSERT_HOST(x)
Definition: errcode.h:87
TBOX::top
int16_t top() const
Definition: rect.h:57
STATS::pile_count
int32_t pile_count(int32_t value) const
Definition: statistc.h:75
FPCUTPT::setup
void setup(FPCUTPT cutpts[], int16_t array_origin, STATS *projection, int16_t zero_count, int16_t pitch, int16_t x, int16_t offset)
Definition: pithsync.cpp:32
FPCUTPT::assign_cheap
void assign_cheap(FPCUTPT cutpts[], int16_t array_origin, int16_t x, bool faking, bool mid_cut, int16_t offset, STATS *projection, float projection_scale, int16_t zero_count, int16_t pitch, int16_t pitch_error)
Definition: pithsync.cpp:195
FPCUTPT::previous
FPCUTPT * previous()
Definition: pithsync.h:78
FPCUTPT::assign
void assign(FPCUTPT cutpts[], int16_t array_origin, int16_t x, bool faking, bool mid_cut, int16_t offset, STATS *projection, float projection_scale, int16_t zero_count, int16_t pitch, int16_t pitch_error)
Definition: pithsync.cpp:88
topitch.h
textord_fast_pitch_test
bool textord_fast_pitch_test
Definition: topitch.cpp:42
makerow.h
textord_test_y
int textord_test_y
Definition: makerow.cpp:61
FPCUTPT
Definition: pithsync.h:27
FPCUTPT::position
int32_t position()
Definition: pithsync.h:66
STATS
Definition: statistc.h:30
tprintf.h
STATS::local_min
bool local_min(int32_t x) const
Definition: statistc.cpp:240
FPCUTPT::sum
double sum()
Definition: pithsync.h:75
box_next
TBOX box_next(BLOBNBOX_IT *it)
Definition: blobbox.cpp:629
TBOX::left
int16_t left() const
Definition: rect.h:71
TBOX::right
int16_t right() const
Definition: rect.h:78
tprintf
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:34
FPSEGPT
Definition: pitsync1.h:31
FPCUTPT::terminal
bool terminal
Definition: pithsync.h:89
textord_test_x
int textord_test_x
Definition: makerow.cpp:60
pitsync1.h
FPCUTPT::faked
bool faked
Definition: pithsync.h:88
TBOX
Definition: rect.h:33
FPCUTPT::index
int16_t index() const
Definition: pithsync.h:84