textord/pitsync1.cpp File Reference

#include "mfcpch.h"
#include <math.h>
#include "memry.h"
#include "pitsync1.h"
#include "notdll.h"

Go to the source code of this file.

Defines

Functions

Variables


Define Documentation

#define EXTERN


Function Documentation

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

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

References ASSERT_HOST, box_next(), FPSEGPT::cost_function(), FALSE, BOX::left(), make_illegal_segment(), MAX_FLOAT32, NULL, STATS::pile_count(), FPSEGPT::previous(), projection, BOX::right(), FPSEGPT::terminal, tprintf(), and TRUE.

Referenced by compute_pitch_sd(), and plot_fp_cells().

00146                          {
00147   INT16 x;                       //current coord
00148   INT16 min_index;               //blob number
00149   INT16 max_index;               //blob number
00150   INT16 left_edge;               //of word
00151   INT16 right_edge;              //of word
00152   INT16 right_max;               //max allowed x
00153   INT16 min_x;                   //in this region
00154   INT16 max_x;
00155   INT16 region_index;
00156   INT16 best_region_index = 0;   //for best result
00157   INT16 offset;                  //dist to legal area
00158   INT16 left_best_x;             //edge of good region
00159   INT16 right_best_x;            //right edge
00160   BOX min_box;                   //bounding box
00161   BOX max_box;                   //bounding box
00162   BOX next_box;                  //box of next blob
00163   FPSEGPT *segpt;                //segment point
00164   FPSEGPT_LIST *segpts;          //points in a segment
00165   double best_cost;              //best path
00166   double mean_sum;               //computes result
00167   FPSEGPT *best_end;             //end of best path
00168   BLOBNBOX_IT min_it;            //copy iterator
00169   BLOBNBOX_IT max_it;            //copy iterator
00170   FPSEGPT_IT segpt_it;           //iterator
00171                                  //output segments
00172   FPSEGPT_IT outseg_it = seg_list;
00173   FPSEGPT_LIST_CLIST lattice;    //list of lists
00174                                  //region iterator
00175   FPSEGPT_LIST_C_IT lattice_it = &lattice;
00176 
00177   //      tprintf("Computing sync on word of %d blobs with pitch %d\n",
00178   //              blob_count, pitch);
00179   //      if (blob_count==8 && pitch==27)
00180   //              projection->print(stdout,TRUE);
00181   if (pitch < 3)
00182     pitch = 3;                   //nothing ludicrous
00183   if ((pitch - 3) / 2 < pitch_error)
00184     pitch_error = (pitch - 3) / 2;
00185   min_it = *blob_it;
00186   min_box = box_next (&min_it);  //get box
00187   //      if (blob_count==8 && pitch==27)
00188   //              tprintf("1st box at (%d,%d)->(%d,%d)\n",
00189   //                      min_box.left(),min_box.bottom(),
00190   //                      min_box.right(),min_box.top());
00191                                  //left of word
00192   left_edge = min_box.left () + pitch_error;
00193   for (min_index = 1; min_index < blob_count; min_index++) {
00194     min_box = box_next (&min_it);
00195     //              if (blob_count==8 && pitch==27)
00196     //                      tprintf("Box at (%d,%d)->(%d,%d)\n",
00197     //                              min_box.left(),min_box.bottom(),
00198     //                              min_box.right(),min_box.top());
00199   }
00200   right_edge = min_box.right (); //end of word
00201   max_x = left_edge;
00202                                  //min permissible
00203   min_x = max_x - pitch + pitch_error * 2 + 1;
00204   right_max = right_edge + pitch - pitch_error - 1;
00205   segpts = new FPSEGPT_LIST;     //list of points
00206   segpt_it.set_to_list (segpts);
00207   for (x = min_x; x <= max_x; x++) {
00208     segpt = new FPSEGPT (x);     //make a new one
00209                                  //put in list
00210     segpt_it.add_after_then_move (segpt);
00211   }
00212                                  //first segment
00213   lattice_it.add_before_then_move (segpts);
00214   min_index = 0;
00215   region_index = 1;
00216   best_cost = MAX_FLOAT32;
00217   best_end = NULL;
00218   min_it = *blob_it;
00219   min_box = box_next (&min_it);  //first box
00220   do {
00221     left_best_x = -1;
00222     right_best_x = -1;
00223     segpts = new FPSEGPT_LIST;   //list of points
00224     segpt_it.set_to_list (segpts);
00225     min_x += pitch - pitch_error;//next limits
00226     max_x += pitch + pitch_error;
00227     while (min_box.right () < min_x && min_index < blob_count) {
00228       min_index++;
00229       min_box = box_next (&min_it);
00230     }
00231     max_it = min_it;
00232     max_index = min_index;
00233     max_box = min_box;
00234     next_box = box_next (&max_it);
00235     for (x = min_x; x <= max_x && x <= right_max; x++) {
00236       while (x < right_edge && max_index < blob_count
00237       && x > max_box.right ()) {
00238         max_index++;
00239         max_box = next_box;
00240         next_box = box_next (&max_it);
00241       }
00242       if (x <= max_box.left () + pitch_error
00243         || x >= max_box.right () - pitch_error || x >= right_edge
00244         || max_index < blob_count - 1 && x >= next_box.left ()
00245         || x - max_box.left () > pitch * pitsync_joined_edge
00246       && max_box.right () - x > pitch * pitsync_joined_edge) {
00247       //                      || projection->local_min(x))
00248         if (x - max_box.left () > 0
00249           && x - max_box.left () <= pitch_error)
00250                                  //dist to real break
00251           offset = x - max_box.left ();
00252         else if (max_box.right () - x > 0
00253           && max_box.right () - x <= pitch_error
00254           && (max_index >= blob_count - 1
00255           || x < next_box.left ()))
00256           offset = max_box.right () - x;
00257         else
00258           offset = 0;
00259         // offset=pitsync_offset_freecut_fraction*projection->pile_count(x);
00260         segpt = new FPSEGPT (x, FALSE, offset, region_index,
00261           pitch, pitch_error, lattice_it.data ());
00262       }
00263       else {
00264         offset = projection->pile_count (x);
00265         segpt = new FPSEGPT (x, TRUE, offset, region_index,
00266           pitch, pitch_error, lattice_it.data ());
00267       }
00268       if (segpt->previous () != NULL) {
00269         segpt_it.add_after_then_move (segpt);
00270         if (x >= right_edge - pitch_error) {
00271           segpt->terminal = TRUE;//no more wanted
00272           if (segpt->cost_function () < best_cost) {
00273             best_cost = segpt->cost_function ();
00274             //find least
00275             best_end = segpt;
00276             best_region_index = region_index;
00277             left_best_x = x;
00278             right_best_x = x;
00279           }
00280           else if (segpt->cost_function () == best_cost
00281             && right_best_x == x - 1)
00282             right_best_x = x;
00283         }
00284       }
00285       else {
00286         delete segpt;            //no good
00287       }
00288     }
00289     if (segpts->empty ()) {
00290       if (best_end != NULL)
00291         break;                   //already found one
00292       make_illegal_segment (lattice_it.data (), min_box, min_it,
00293         region_index, pitch, pitch_error, segpts);
00294     }
00295     else {
00296       if (right_best_x > left_best_x + 1) {
00297         left_best_x = (left_best_x + right_best_x + 1) / 2;
00298         for (segpt_it.mark_cycle_pt (); !segpt_it.cycled_list ()
00299           && segpt_it.data ()->position () != left_best_x;
00300           segpt_it.forward ());
00301         if (segpt_it.data ()->position () == left_best_x)
00302                                  //middle of region
00303           best_end = segpt_it.data ();
00304       }
00305     }
00306                                  //new segment
00307     lattice_it.add_before_then_move (segpts);
00308     region_index++;
00309   }
00310   while (min_x < right_edge);
00311   ASSERT_HOST (best_end != NULL);//must always find some
00312 
00313   for (lattice_it.mark_cycle_pt (); !lattice_it.cycled_list ();
00314   lattice_it.forward ()) {
00315     segpts = lattice_it.data ();
00316     segpt_it.set_to_list (segpts);
00317 // if (blob_count==8 && pitch==27)
00318 // {
00319 //   for (segpt_it.mark_cycle_pt();!segpt_it.cycled_list();segpt_it.forward())
00320 //   {
00321 //        segpt=segpt_it.data();
00322 //        tprintf("At %d, (%x) cost=%g, m=%g, sq=%g, pred=%x\n",
00323 //                segpt->position(),segpt,segpt->cost_function(),
00324 //                segpt->sum(),segpt->squares(),segpt->previous());
00325 //    }
00326 //    tprintf("\n");
00327 // }
00328     for (segpt_it.mark_cycle_pt (); !segpt_it.cycled_list ()
00329       && segpt_it.data () != best_end; segpt_it.forward ());
00330     if (segpt_it.data () == best_end) {
00331                                  //save good one
00332       segpt = segpt_it.extract ();
00333       outseg_it.add_before_then_move (segpt);
00334       best_end = segpt->previous ();
00335     }
00336   }
00337   ASSERT_HOST (best_end == NULL);
00338   ASSERT_HOST (!outseg_it.empty ());
00339   outseg_it.move_to_last ();
00340   mean_sum = outseg_it.data ()->sum ();
00341   mean_sum = mean_sum * mean_sum / best_region_index;
00342   if (outseg_it.data ()->squares () - mean_sum < 0)
00343     tprintf ("Impossible sqsum=%g, mean=%g, total=%d\n",
00344       outseg_it.data ()->squares (), outseg_it.data ()->sum (),
00345       best_region_index);
00346   lattice.deep_clear ();         //shift the lot
00347   return outseg_it.data ()->squares () - mean_sum;
00348 }

EXTERN double_VAR ( pitsync_offset_freecut_fraction  ,
0.  25,
"Fraction of cut for free cuts"   
)

EXTERN double_VAR ( pitsync_joined_edge  ,
0.  75,
"Dist inside big blob for chopping"   
)

ELISTIZE ( FPSEGPT   ) 

Note:
File: pitsync1.cpp (Formerly pitsync.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.

EXTERN INT_VAR ( pitsync_fake_depth  ,
,
"Max advance fake generation"   
)

void make_illegal_segment ( FPSEGPT_LIST *  prev_list,
BOX  blob_box,
BLOBNBOX_IT  blob_it,
INT16  region_index,
INT16  pitch,
INT16  pitch_error,
FPSEGPT_LIST *  seg_list 
)

Find segmentation

Make a fake set of chop points due to having no legal places.

Definition at line 356 of file pitsync1.cpp.

References ASSERT_HOST, box_next(), FPSEGPT::cost_function(), FPSEGPT::fake_count, FALSE, BOX::left(), MAX_FLOAT32, NULL, FPSEGPT::position(), FPSEGPT::previous(), BOX::right(), and TRUE.

Referenced by check_pitch_sync().

00364                            {
00365   INT16 x;                       //current coord
00366   INT16 min_x = 0;               //in this region
00367   INT16 max_x = 0;
00368   INT16 offset;                  //dist to edge
00369   FPSEGPT *segpt;                //segment point
00370   FPSEGPT *prevpt;               //previous point
00371   float best_cost;               //best path
00372   FPSEGPT_IT segpt_it = seg_list;//iterator
00373                                  //previous points
00374   FPSEGPT_IT prevpt_it = prev_list;
00375 
00376   best_cost = MAX_FLOAT32;
00377   for (prevpt_it.mark_cycle_pt (); !prevpt_it.cycled_list ();
00378   prevpt_it.forward ()) {
00379     prevpt = prevpt_it.data ();
00380     if (prevpt->cost_function () < best_cost) {
00381                                  //find least
00382       best_cost = prevpt->cost_function ();
00383       min_x = prevpt->position ();
00384       max_x = min_x;             //limits on coords
00385     }
00386     else if (prevpt->cost_function () == best_cost) {
00387       max_x = prevpt->position ();
00388     }
00389   }
00390   min_x += pitch - pitch_error;
00391   max_x += pitch + pitch_error;
00392   for (x = min_x; x <= max_x; x++) {
00393     while (x > blob_box.right ()) {
00394       blob_box = box_next (&blob_it);
00395     }
00396     offset = x - blob_box.left ();
00397     if (blob_box.right () - x < offset)
00398       offset = blob_box.right () - x;
00399     segpt = new FPSEGPT (x, FALSE, offset,
00400       region_index, pitch, pitch_error, prev_list);
00401     if (segpt->previous () != NULL) {
00402       ASSERT_HOST (offset >= 0);
00403       fprintf (stderr, "made fake at %d\n", x);
00404                                  //make one up
00405       segpt_it.add_after_then_move (segpt);
00406       segpt->faked = TRUE;
00407       segpt->fake_count++;
00408     }
00409     else
00410       delete segpt;
00411   }
00412 }


Variable Documentation

Use new fast algorithm

Definition at line 33 of file pitsync1.cpp.


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