29 #define PROJECTION_MARGIN 10 //arbitrary 47 int16_t half_pitch = pitch / 2 - 1;
53 else if (half_pitch < 0)
55 lead_flag = 1 << half_pitch;
59 sq_sum = offset * offset;
67 if (x == array_origin) {
70 for (ind = 0; ind <= half_pitch; ind++) {
73 fwd_balance |= lead_flag;
77 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
78 back_balance &= lead_flag + lead_flag - 1;
81 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
82 if (projection->
pile_count (x + half_pitch) > zero_count)
83 fwd_balance |= lead_flag;
102 float projection_scale,
109 int16_t balance_count;
118 int16_t half_pitch = pitch / 2 - 1;
123 else if (half_pitch < 0)
125 lead_flag = 1 << half_pitch;
127 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
128 back_balance &= lead_flag + lead_flag - 1;
131 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
132 if (projection->
pile_count (x + half_pitch) > zero_count)
133 fwd_balance |= lead_flag;
142 for (
index = x - pitch - pitch_error;
index <= x - pitch + pitch_error;
144 if (
index >= array_origin) {
145 segpt = &cutpts[
index - array_origin];
146 dist = x - segpt->xpos;
151 lead_flag = back_balance ^ segpt->fwd_balance;
153 while (lead_flag != 0) {
155 lead_flag &= lead_flag - 1;
159 for (balance_index = 0;
160 index + balance_index < x - balance_index;
172 r_index = segpt->region_index + 1;
173 total = segpt->mean_sum + dist;
174 balance_count += offset;
176 dist * dist + segpt->sq_sum + balance_count * balance_count;
177 mean = total / r_index;
178 factor = mean - pitch;
180 factor += sq_dist / (r_index) - mean * mean;
187 mid_cuts = segpt->mid_cuts + mid_cut;
188 region_index = r_index;
204 int16_t array_origin,
210 float projection_scale,
216 int16_t balance_count;
225 int16_t half_pitch = pitch / 2 - 1;
230 else if (half_pitch < 0)
232 lead_flag = 1 << half_pitch;
234 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
235 back_balance &= lead_flag + lead_flag - 1;
238 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
239 if (projection->
pile_count (x + half_pitch) > zero_count)
240 fwd_balance |= lead_flag;
250 if (
index >= array_origin) {
251 segpt = &cutpts[
index - array_origin];
252 dist = x - segpt->xpos;
256 lead_flag = back_balance ^ segpt->fwd_balance;
258 while (lead_flag != 0) {
260 lead_flag &= lead_flag - 1;
265 r_index = segpt->region_index + 1;
266 total = segpt->mean_sum + dist;
267 balance_count += offset;
269 dist * dist + segpt->sq_sum + balance_count * balance_count;
270 mean = total / r_index;
271 factor = mean - pitch;
273 factor += sq_dist / (r_index) - mean * mean;
279 mid_cuts = segpt->mid_cuts + mid_cut;
280 region_index = r_index;
295 BLOBNBOX_IT *blob_it,
300 int16_t projection_left,
301 int16_t projection_right,
302 float projection_scale,
303 int16_t &occupation_count,
304 FPSEGPT_LIST *seg_list,
314 int16_t array_origin;
317 int16_t best_left_x = 0;
318 int16_t best_right_x = 0;
328 FPSEGPT_IT seg_it = seg_list;
337 if ((pitch - 3) / 2 < pitch_error)
338 pitch_error = (pitch - 3) / 2;
349 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
350 && left_edge < projection_right; left_edge++);
351 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
352 && right_edge > left_edge; right_edge--);
354 if (pitsync_linear_version >= 4)
356 pitch, pitch_error, projection,
357 projection_scale, occupation_count, seg_list,
359 array_origin = left_edge - pitch;
361 std::vector<FPCUTPT> cutpts(right_edge - left_edge + pitch * 2 + 1);
362 for (x = array_origin; x < left_edge; x++)
364 cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
365 zero_count, pitch, x, 0);
366 for (offset = 0; offset <= pitch_error; offset++, x++)
368 cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
369 zero_count, pitch, x, offset);
377 while (x < right_edge - pitch_error) {
378 if (x > this_box.
right () + pitch_error && blob_index < blob_count) {
385 if (x <= this_box.
left ())
387 else if (x <= this_box.
left () + pitch_error)
388 offset = x - this_box.
left ();
389 else if (x >= this_box.
right ())
391 else if (x >= next_box.
left () && blob_index < blob_count) {
392 offset = x - next_box.
left ();
393 if (this_box.
right () - x < offset)
394 offset = this_box.
right () - x;
396 else if (x >= this_box.
right () - pitch_error)
397 offset = this_box.
right () - x;
407 cutpts[x - array_origin].assign (&cutpts[0], array_origin, x,
408 faking, mid_cut, offset, projection,
409 projection_scale, zero_count, pitch,
414 best_fake = INT16_MAX;
415 best_cost = INT32_MAX;
416 best_count = INT16_MAX;
417 while (x < right_edge + pitch) {
418 offset = x < right_edge ? right_edge - x : 0;
419 cutpts[x - array_origin].assign (&cutpts[0], array_origin, x,
420 false,
false, offset, projection,
421 projection_scale, zero_count, pitch,
423 cutpts[x - array_origin].terminal =
true;
424 if (cutpts[x - array_origin].index () +
425 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
426 if (cutpts[x - array_origin].fake_count < best_fake
427 || (cutpts[x - array_origin].fake_count == best_fake
428 && cutpts[x - array_origin].cost_function () < best_cost)) {
429 best_fake = cutpts[x - array_origin].fake_count;
430 best_cost = cutpts[x - array_origin].cost_function ();
433 best_count = cutpts[x - array_origin].index ();
435 else if (cutpts[x - array_origin].fake_count == best_fake
436 && x == best_right_x + 1
437 && cutpts[x - array_origin].cost_function () == best_cost) {
446 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
449 for (x = left_edge - pitch; x < right_edge + pitch; x++) {
450 tprintf (
"x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
451 x, cutpts[x - array_origin].cost_function (),
452 cutpts[x - array_origin].sum (),
453 cutpts[x - array_origin].squares (),
454 cutpts[x - array_origin].previous ()->position ());
457 occupation_count = -1;
459 for (x = best_end->
position () - pitch + pitch_error;
460 x < best_end->
position () - pitch_error
462 if (x < best_end->position () - pitch_error)
465 segpt =
new FPSEGPT (best_end);
466 seg_it.add_before_then_move (segpt);
469 while (best_end !=
nullptr);
470 seg_it.move_to_last ();
471 mean_sum = seg_it.data ()->
sum ();
472 mean_sum = mean_sum * mean_sum / best_count;
473 if (seg_it.data ()->squares () - mean_sum < 0)
474 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
475 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
479 return seg_it.data ()->squares () - mean_sum;
492 int16_t projection_left,
493 int16_t projection_right,
498 float projection_scale,
499 int16_t &occupation_count,
500 FPSEGPT_LIST *seg_list,
509 int16_t array_origin;
511 int16_t projection_offset;
515 int16_t best_left_x = 0;
516 int16_t best_right_x = 0;
525 FPSEGPT_IT seg_it = seg_list;
527 end = (end - start) % pitch;
530 if ((pitch - 3) / 2 < pitch_error)
531 pitch_error = (pitch - 3) / 2;
534 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
535 && left_edge < projection_right; left_edge++);
536 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
537 && right_edge > left_edge; right_edge--);
538 array_origin = left_edge - pitch;
540 std::vector<FPCUTPT> cutpts(right_edge - left_edge + pitch * 2 + 1);
542 std::vector<BOOL8> mins(pitch_error * 2 + 1);
543 for (x = array_origin; x < left_edge; x++)
545 cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
546 zero_count, pitch, x, 0);
547 prev_zero = left_edge - 1;
548 for (offset = 0; offset <= pitch_error; offset++, x++)
550 cutpts[x - array_origin].setup(&cutpts[0], array_origin, projection,
551 zero_count, pitch, x, offset);
555 for (offset = -pitch_error, minindex = 0; offset < pitch_error;
556 offset++, minindex++)
557 mins[minindex] = projection->
local_min (x + offset);
558 next_zero = x + zero_offset + 1;
559 for (offset = next_zero - 1; offset >= x; offset--) {
560 if (projection->
pile_count (offset) <= zero_count) {
565 while (x < right_edge - pitch_error) {
566 mins[minindex] = projection->
local_min (x + pitch_error);
568 if (minindex > pitch_error * 2)
573 if (projection->
pile_count (x) <= zero_count) {
577 for (offset = 1; offset <= pitch_error; offset++)
578 if (projection->
pile_count (x + offset) <= zero_count
579 || projection->
pile_count (x - offset) <= zero_count)
582 if (offset > pitch_error) {
583 if (x - prev_zero > zero_offset && next_zero - x > zero_offset) {
584 for (offset = 0; offset <= pitch_error; offset++) {
585 test_index = minindex + pitch_error + offset;
586 if (test_index > pitch_error * 2)
587 test_index -= pitch_error * 2 + 1;
588 if (mins[test_index])
590 test_index = minindex + pitch_error - offset;
591 if (test_index > pitch_error * 2)
592 test_index -= pitch_error * 2 + 1;
593 if (mins[test_index])
597 if (offset > pitch_error) {
603 (int16_t) (projection->
pile_count (x) / projection_scale);
604 if (projection_offset > offset)
605 offset = projection_offset;
609 if ((start == 0 && end == 0)
611 || (x - projection_left - start) % pitch <= end)
612 cutpts[x - array_origin].assign(&cutpts[0], array_origin, x,
613 faking, mid_cut, offset, projection,
614 projection_scale, zero_count, pitch,
617 cutpts[x - array_origin].assign_cheap(&cutpts[0], array_origin, x,
618 faking, mid_cut, offset,
619 projection, projection_scale,
623 if (next_zero < x || next_zero == x + zero_offset)
624 next_zero = x + zero_offset + 1;
625 if (projection->
pile_count (x + zero_offset) <= zero_count)
626 next_zero = x + zero_offset;
629 best_fake = INT16_MAX;
630 best_cost = INT32_MAX;
631 best_count = INT16_MAX;
632 while (x < right_edge + pitch) {
633 offset = x < right_edge ? right_edge - x : 0;
634 cutpts[x - array_origin].assign(&cutpts[0], array_origin, x,
635 false,
false, offset, projection,
636 projection_scale, zero_count, pitch,
638 cutpts[x - array_origin].terminal =
true;
639 if (cutpts[x - array_origin].index () +
640 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
641 if (cutpts[x - array_origin].fake_count < best_fake
642 || (cutpts[x - array_origin].fake_count == best_fake
643 && cutpts[x - array_origin].cost_function () < best_cost)) {
644 best_fake = cutpts[x - array_origin].fake_count;
645 best_cost = cutpts[x - array_origin].cost_function ();
648 best_count = cutpts[x - array_origin].index ();
650 else if (cutpts[x - array_origin].fake_count == best_fake
651 && x == best_right_x + 1
652 && cutpts[x - array_origin].cost_function () == best_cost) {
661 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
670 occupation_count = -1;
672 for (x = best_end->
position () - pitch + pitch_error;
673 x < best_end->
position () - pitch_error
675 if (x < best_end->position () - pitch_error)
678 segpt =
new FPSEGPT (best_end);
679 seg_it.add_before_then_move (segpt);
682 while (best_end !=
nullptr);
683 seg_it.move_to_last ();
684 mean_sum = seg_it.data ()->
sum ();
685 mean_sum = mean_sum * mean_sum / best_count;
686 if (seg_it.data ()->squares () - mean_sum < 0)
687 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
688 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
689 return seg_it.data ()->squares () - mean_sum;
EXTERN bool textord_fast_pitch_test
int32_t pile_count(int32_t value) const
void setup(FPCUTPT cutpts[], int16_t array_origin, STATS *projection, int16_t zero_count, int16_t pitch, int16_t x, int16_t offset)
double pitsync_joined_edge
bool local_min(int32_t x) const
void assign_cheap(FPCUTPT cutpts[], int16_t array_origin, int16_t x, BOOL8 faking, BOOL8 mid_cut, int16_t offset, STATS *projection, float projection_scale, int16_t zero_count, int16_t pitch, int16_t pitch_error)
EXTERN double textord_balance_factor
TBOX box_next(BLOBNBOX_IT *it)
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)
DLLSYM void tprintf(const char *format,...)
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)
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)