textord/pithsync.cpp File Reference

#include "mfcpch.h"
#include <math.h>
#include "memry.h"
#include "makerow.h"
#include "pitsync1.h"
#include "topitch.h"
#include "pithsync.h"
#include "tprintf.h"

Go to the source code of this file.

Defines

Functions


Define Documentation

#define EXTERN

Definition at line 38 of file pithsync.cpp.

#define PROJECTION_MARGIN   10

Arbitrary.

Note:
File: pithsync.cpp (Formerly pitsync2.c)
Code to find the optimum fixed pitch segmentation of some blobs.
Author:
Ray Smith
Date:
Nov 19 11:48:05 GMT 1992
 * (C) Copyright 1992, Hewlett-Packard Ltd.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.

Definition at line 36 of file pithsync.cpp.


Function Documentation

double check_pitch_sync2 ( BLOBNBOX_IT *  blob_it,
INT16  blob_count,
INT16  pitch,
INT16  pitch_error,
STATS projection,
INT16  projection_left,
INT16  projection_right,
float  projection_scale,
INT16 occupation_count,
FPSEGPT_LIST *  seg_list,
INT16  start,
INT16  end 
)

Find segmentation.

Parameters:
blob_it Pointer to blobs to do
blob_count Number of blobs
pitch Pitch estimate
pitch_error Tolerance
projection Vertical
projection_left Left edge
projection_right Right edge
projection_scale Scale factor
occupation_count Number of occupied cells
seg_list LIST of segments (modified)
start Start of good range
end End of good range
Returns:
Measure of goodness of the sync; of optimal path only.
Construct the lattice of possible segmentation points and choose the optimal path. Return the optimal path only.

Definition at line 307 of file pithsync.cpp.

References alloc_mem(), ASSERT_HOST, box_next(), check_pitch_sync3(), cprintf(), FALSE, free_mem(), BOX::left(), MAX_FLOAT32, MAX_INT16, MAX_INT32, NULL, STATS::pile_count(), FPCUTPT::position(), FPCUTPT::previous(), projection, BOX::right(), FPCUTPT::sum(), BOX::top(), tprintf(), and TRUE.

Referenced by compute_pitch_sd(), compute_pitch_sd2(), plot_fp_cells(), and print_pitch_sd().

00320                           {
00321   BOOL8 faking;                  //illegal cut pt
00322   BOOL8 mid_cut;                 //cheap cut pt.
00323   INT16 x;                       //current coord
00324   INT16 blob_index;              //blob number
00325   INT16 left_edge;               //of word
00326   INT16 right_edge;              //of word
00327   INT16 array_origin;            //x coord of array
00328   INT16 offset;                  //dist to legal area
00329   INT16 zero_count;              //projection zero
00330   INT16 best_left_x = 0;         //for equals
00331   INT16 best_right_x = 0;        //right edge
00332   BOX this_box;                  //bounding box
00333   BOX next_box;                  //box of next blob
00334   FPSEGPT *segpt;                //segment point
00335   FPCUTPT *cutpts;               //array of points
00336   double best_cost;              //best path
00337   double mean_sum;               //computes result
00338   FPCUTPT *best_end;             //end of best path
00339   INT16 best_fake;               //best fake level
00340   INT16 best_count;              //no of cuts
00341   BLOBNBOX_IT this_it;           //copy iterator
00342   FPSEGPT_IT seg_it = seg_list;  //output iterator
00343 
00344 #ifdef TEXT_VERBOSE
00345   // gets a 't', see ccmain/tesseractmain.dox
00346   cprintf("t");
00347 #endif
00348   //      tprintf("Computing sync on word of %d blobs with pitch %d\n",
00349   //              blob_count, pitch);
00350   //      if (blob_count==8 && pitch==27)
00351   //              projection->print(stdout,TRUE);
00352   zero_count = 0;
00353   if (pitch < 3)
00354     pitch = 3;                   //nothing ludicrous
00355   if ((pitch - 3) / 2 < pitch_error)
00356     pitch_error = (pitch - 3) / 2;
00357   this_it = *blob_it;
00358   this_box = box_next (&this_it);//get box
00359   //      left_edge=this_box.left();     //left of word
00360   //      right_edge=this_box.right();
00361   //      for (blob_index=1;blob_index<blob_count;blob_index++)
00362   //      {
00363   //              this_box=box_next(&this_it);
00364   //              if (this_box.right()>right_edge)
00365   //                      right_edge=this_box.right();
00366   //      }
00367   for (left_edge = projection_left; projection->pile_count (left_edge) == 0
00368     && left_edge < projection_right; left_edge++);
00369   for (right_edge = projection_right; projection->pile_count (right_edge) == 0
00370     && right_edge > left_edge; right_edge--);
00371   ASSERT_HOST (right_edge >= left_edge);
00372   if (pitsync_linear_version >= 4)
00373     return check_pitch_sync3 (projection_left, projection_right, zero_count,
00374       pitch, pitch_error, projection,
00375       projection_scale, occupation_count, seg_list,
00376       start, end);
00377   array_origin = left_edge - pitch;
00378   cutpts = (FPCUTPT *) alloc_mem ((right_edge - left_edge + pitch * 2 + 1)
00379     * sizeof (FPCUTPT));
00380   for (x = array_origin; x < left_edge; x++)
00381                                  //free cuts
00382     cutpts[x - array_origin].setup (cutpts, array_origin, projection,
00383     zero_count, pitch, x, 0);
00384   for (offset = 0; offset <= pitch_error; offset++, x++)
00385                                  //not quite free
00386     cutpts[x - array_origin].setup (cutpts, array_origin, projection,
00387     zero_count, pitch, x, offset);
00388 
00389   this_it = *blob_it;
00390   best_cost = MAX_FLOAT32;
00391   best_end = NULL;
00392   this_box = box_next (&this_it);//first box
00393   next_box = box_next (&this_it);//second box
00394   blob_index = 1;
00395   while (x < right_edge - pitch_error) {
00396     if (x > this_box.right () + pitch_error && blob_index < blob_count) {
00397       this_box = next_box;
00398       next_box = box_next (&this_it);
00399       blob_index++;
00400     }
00401     faking = FALSE;
00402     mid_cut = FALSE;
00403     if (x <= this_box.left ())
00404       offset = 0;
00405     else if (x <= this_box.left () + pitch_error)
00406       offset = x - this_box.left ();
00407     else if (x >= this_box.right ())
00408       offset = 0;
00409     else if (x >= next_box.left () && blob_index < blob_count) {
00410       offset = x - next_box.left ();
00411       if (this_box.right () - x < offset)
00412         offset = this_box.right () - x;
00413     }
00414     else if (x >= this_box.right () - pitch_error)
00415       offset = this_box.right () - x;
00416     else if (x - this_box.left () > pitch * pitsync_joined_edge
00417     && this_box.right () - x > pitch * pitsync_joined_edge) {
00418       mid_cut = TRUE;
00419       offset = 0;
00420     }
00421     else {
00422       faking = TRUE;
00423       offset = projection->pile_count (x);
00424     }
00425     cutpts[x - array_origin].assign (cutpts, array_origin, x,
00426       faking, mid_cut, offset, projection,
00427       projection_scale, zero_count, pitch,
00428       pitch_error);
00429     x++;
00430   }
00431 
00432   best_fake = MAX_INT16;
00433   best_cost = MAX_INT32;
00434   best_count = MAX_INT16;
00435   while (x < right_edge + pitch) {
00436     offset = x < right_edge ? right_edge - x : 0;
00437     cutpts[x - array_origin].assign (cutpts, array_origin, x,
00438       FALSE, FALSE, offset, projection,
00439       projection_scale, zero_count, pitch,
00440       pitch_error);
00441     cutpts[x - array_origin].terminal = TRUE;
00442     if (cutpts[x - array_origin].index () +
00443     cutpts[x - array_origin].fake_count <= best_count + best_fake) {
00444       if (cutpts[x - array_origin].fake_count < best_fake
00445         || cutpts[x - array_origin].fake_count == best_fake
00446       && cutpts[x - array_origin].cost_function () < best_cost) {
00447         best_fake = cutpts[x - array_origin].fake_count;
00448         best_cost = cutpts[x - array_origin].cost_function ();
00449         best_left_x = x;
00450         best_right_x = x;
00451         best_count = cutpts[x - array_origin].index ();
00452       }
00453       else if (cutpts[x - array_origin].fake_count == best_fake
00454         && x == best_right_x + 1
00455       && cutpts[x - array_origin].cost_function () == best_cost) {
00456       //exactly equal
00457         best_right_x = x;
00458       }
00459     }
00460     x++;
00461   }
00462   ASSERT_HOST (best_fake < MAX_INT16);
00463 
00464   best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
00465   if (this_box.right () == textord_test_x
00466   && this_box.top () == textord_test_y) {
00467     for (x = left_edge - pitch; x < right_edge + pitch; x++) {
00468       tprintf ("x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
00469         x, cutpts[x - array_origin].cost_function (),
00470         cutpts[x - array_origin].sum (),
00471         cutpts[x - array_origin].squares (),
00472         cutpts[x - array_origin].previous ()->position ());
00473     }
00474   }
00475   occupation_count = -1;
00476   do {
00477     for (x = best_end->position () - pitch + pitch_error;
00478       x < best_end->position () - pitch_error
00479       && projection->pile_count (x) == 0; x++);
00480     if (x < best_end->position () - pitch_error)
00481       occupation_count++;
00482                                  //copy it
00483     segpt = new FPSEGPT (best_end);
00484     seg_it.add_before_then_move (segpt);
00485     best_end = best_end->previous ();
00486   }
00487   while (best_end != NULL);
00488   seg_it.move_to_last ();
00489   mean_sum = seg_it.data ()->sum ();
00490   mean_sum = mean_sum * mean_sum / best_count;
00491   if (seg_it.data ()->squares () - mean_sum < 0)
00492     tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
00493       seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
00494   free_mem(cutpts); 
00495   //      tprintf("blob_count=%d, pitch=%d, sync=%g, occ=%d\n",
00496   //              blob_count,pitch,seg_it.data()->squares()-mean_sum,
00497   //              occupation_count);
00498   return seg_it.data ()->squares () - mean_sum;
00499 }

double check_pitch_sync3 ( INT16  projection_left,
INT16  projection_right,
INT16  zero_count,
INT16  pitch,
INT16  pitch_error,
STATS projection,
float  projection_scale,
INT16 occupation_count,
FPSEGPT_LIST *  seg_list,
INT16  start,
INT16  end 
)

Find segmentation.

Returns:
Measure of goodness of the sync; optimal path only.
Construct the lattice of possible segmentation points and choose the optimal path. Return the optimal path only.

Definition at line 510 of file pithsync.cpp.

References alloc_mem(), ASSERT_HOST, FALSE, free_mem(), STATS::local_min(), MAX_FLOAT32, MAX_INT16, MAX_INT32, NULL, STATS::pile_count(), FPCUTPT::position(), FPCUTPT::previous(), projection, FPCUTPT::sum(), tprintf(), and TRUE.

Referenced by check_pitch_sync2().

00522                           {
00523   BOOL8 faking;                  //illegal cut pt
00524   BOOL8 mid_cut;                 //cheap cut pt.
00525   INT16 left_edge;               //of word
00526   INT16 right_edge;              //of word
00527   INT16 x;                       //current coord
00528   INT16 array_origin;            //x coord of array
00529   INT16 offset;                  //dist to legal area
00530   INT16 projection_offset;       //from scaled projection
00531   INT16 prev_zero;               //previous zero dist
00532   INT16 next_zero;               //next zero dist
00533   INT16 zero_offset;             //scan window
00534   INT16 best_left_x = 0;         //for equals
00535   INT16 best_right_x = 0;        //right edge
00536   FPSEGPT *segpt;                //segment point
00537   FPCUTPT *cutpts;               //array of points
00538   BOOL8 *mins;                   //local min results
00539   int minindex;                  //next input position
00540   int test_index;                //index to mins
00541   double best_cost;              //best path
00542   double mean_sum;               //computes result
00543   FPCUTPT *best_end;             //end of best path
00544   INT16 best_fake;               //best fake level
00545   INT16 best_count;              //no of cuts
00546   FPSEGPT_IT seg_it = seg_list;  //output iterator
00547 
00548   end = (end - start) % pitch;
00549   if (pitch < 3)
00550     pitch = 3;                   //nothing ludicrous
00551   if ((pitch - 3) / 2 < pitch_error)
00552     pitch_error = (pitch - 3) / 2;
00553                                  //min dist of zero
00554   zero_offset = (INT16) (pitch * pitsync_joined_edge);
00555   for (left_edge = projection_left; projection->pile_count (left_edge) == 0
00556     && left_edge < projection_right; left_edge++);
00557   for (right_edge = projection_right; projection->pile_count (right_edge) == 0
00558     && right_edge > left_edge; right_edge--);
00559   array_origin = left_edge - pitch;
00560   cutpts = (FPCUTPT *) alloc_mem ((right_edge - left_edge + pitch * 2 + 1)
00561     * sizeof (FPCUTPT));
00562   mins = (BOOL8 *) alloc_mem ((pitch_error * 2 + 1) * sizeof (BOOL8));
00563   for (x = array_origin; x < left_edge; x++)
00564                                  //free cuts
00565     cutpts[x - array_origin].setup (cutpts, array_origin, projection,
00566     zero_count, pitch, x, 0);
00567   prev_zero = left_edge - 1;
00568   for (offset = 0; offset <= pitch_error; offset++, x++)
00569                                  //not quite free
00570     cutpts[x - array_origin].setup (cutpts, array_origin, projection,
00571     zero_count, pitch, x, offset);
00572 
00573   best_cost = MAX_FLOAT32;
00574   best_end = NULL;
00575   for (offset = -pitch_error, minindex = 0; offset < pitch_error;
00576     offset++, minindex++)
00577   mins[minindex] = projection->local_min (x + offset);
00578   next_zero = x + zero_offset + 1;
00579   for (offset = next_zero - 1; offset >= x; offset--) {
00580     if (projection->pile_count (offset) <= zero_count) {
00581       next_zero = offset;
00582       break;
00583     }
00584   }
00585   while (x < right_edge - pitch_error) {
00586     mins[minindex] = projection->local_min (x + pitch_error);
00587     minindex++;
00588     if (minindex > pitch_error * 2)
00589       minindex = 0;
00590     faking = FALSE;
00591     mid_cut = FALSE;
00592     offset = 0;
00593     if (projection->pile_count (x) <= zero_count) {
00594       prev_zero = x;
00595     }
00596     else {
00597       for (offset = 1; offset <= pitch_error; offset++)
00598         if (projection->pile_count (x + offset) <= zero_count
00599         || projection->pile_count (x - offset) <= zero_count)
00600           break;
00601     }
00602     if (offset > pitch_error) {
00603       if (x - prev_zero > zero_offset && next_zero - x > zero_offset) {
00604         for (offset = 0; offset <= pitch_error; offset++) {
00605           test_index = minindex + pitch_error + offset;
00606           if (test_index > pitch_error * 2)
00607             test_index -= pitch_error * 2 + 1;
00608           if (mins[test_index])
00609             break;
00610           test_index = minindex + pitch_error - offset;
00611           if (test_index > pitch_error * 2)
00612             test_index -= pitch_error * 2 + 1;
00613           if (mins[test_index])
00614             break;
00615         }
00616       }
00617       if (offset > pitch_error) {
00618         offset = projection->pile_count (x);
00619         faking = TRUE;
00620       }
00621       else {
00622         projection_offset =
00623           (INT16) (projection->pile_count (x) / projection_scale);
00624         if (projection_offset > offset)
00625           offset = projection_offset;
00626         mid_cut = TRUE;
00627       }
00628     }
00629     if (start == 0 && end == 0
00630       || !textord_fast_pitch_test
00631       || (x - projection_left - start) % pitch <= end)
00632       cutpts[x - array_origin].assign (cutpts, array_origin, x,
00633         faking, mid_cut, offset, projection,
00634         projection_scale, zero_count, pitch,
00635         pitch_error);
00636     else
00637       cutpts[x - array_origin].assign_cheap (cutpts, array_origin, x,
00638         faking, mid_cut, offset,
00639         projection, projection_scale,
00640         zero_count, pitch,
00641         pitch_error);
00642     x++;
00643     if (next_zero < x || next_zero == x + zero_offset)
00644       next_zero = x + zero_offset + 1;
00645     if (projection->pile_count (x + zero_offset) <= zero_count)
00646       next_zero = x + zero_offset;
00647   }
00648 
00649   best_fake = MAX_INT16;
00650   best_cost = MAX_INT32;
00651   best_count = MAX_INT16;
00652   while (x < right_edge + pitch) {
00653     offset = x < right_edge ? right_edge - x : 0;
00654     cutpts[x - array_origin].assign (cutpts, array_origin, x,
00655       FALSE, FALSE, offset, projection,
00656       projection_scale, zero_count, pitch,
00657       pitch_error);
00658     cutpts[x - array_origin].terminal = TRUE;
00659     if (cutpts[x - array_origin].index () +
00660     cutpts[x - array_origin].fake_count <= best_count + best_fake) {
00661       if (cutpts[x - array_origin].fake_count < best_fake
00662         || cutpts[x - array_origin].fake_count == best_fake
00663       && cutpts[x - array_origin].cost_function () < best_cost) {
00664         best_fake = cutpts[x - array_origin].fake_count;
00665         best_cost = cutpts[x - array_origin].cost_function ();
00666         best_left_x = x;
00667         best_right_x = x;
00668         best_count = cutpts[x - array_origin].index ();
00669       }
00670       else if (cutpts[x - array_origin].fake_count == best_fake
00671         && x == best_right_x + 1
00672       && cutpts[x - array_origin].cost_function () == best_cost) {
00673       //exactly equal
00674         best_right_x = x;
00675       }
00676     }
00677     x++;
00678   }
00679   ASSERT_HOST (best_fake < MAX_INT16);
00680 
00681   best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
00682   //      for (x=left_edge-pitch;x<right_edge+pitch;x++)
00683   //      {
00684   //              tprintf("x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
00685   //                      x,cutpts[x-array_origin].cost_function(),
00686   //                      cutpts[x-array_origin].sum(),
00687   //                      cutpts[x-array_origin].squares(),
00688   //                      cutpts[x-array_origin].previous()->position());
00689   //      }
00690   occupation_count = -1;
00691   do {
00692     for (x = best_end->position () - pitch + pitch_error;
00693       x < best_end->position () - pitch_error
00694       && projection->pile_count (x) == 0; x++);
00695     if (x < best_end->position () - pitch_error)
00696       occupation_count++;
00697                                  //copy it
00698     segpt = new FPSEGPT (best_end);
00699     seg_it.add_before_then_move (segpt);
00700     best_end = best_end->previous ();
00701   }
00702   while (best_end != NULL);
00703   seg_it.move_to_last ();
00704   mean_sum = seg_it.data ()->sum ();
00705   mean_sum = mean_sum * mean_sum / best_count;
00706   if (seg_it.data ()->squares () - mean_sum < 0)
00707     tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
00708       seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
00709   free_mem(mins); 
00710   free_mem(cutpts); 
00711   return seg_it.data ()->squares () - mean_sum;
00712 }


Generated on Wed Feb 28 19:49:25 2007 for Tesseract by  doxygen 1.5.1