reference/ocr-new/properties.doc
changeset 0 6b8091ca909a
equal deleted inserted replaced
-1:000000000000 0:6b8091ca909a
       
     1 #include "system.h"
       
     2 #include "Component.h"
       
     3 #include "BitMap.h"
       
     4 #include <assert.h>
       
     5 #include "list.h"
       
     6 #include "tcl_interface.h"
       
     7 
       
     8 /*** Component.cc
       
     9   Member functions for Components 
       
    10   Component functions defined in Component.h
       
    11   rev 12/9/95 KM
       
    12 ***/
       
    13 
       
    14 
       
    15 Components::Components()
       
    16 :List()
       
    17 {
       
    18 }
       
    19 
       
    20 
       
    21 Components::~Components()
       
    22 {
       
    23   for (ListElement *ptr = first; ptr != NULL && ptr->item!=NULL; 
       
    24        ptr = ptr->next) {
       
    25     if (ptr->item != NULL)
       
    26       delete (Component *) (ptr->item);
       
    27      }
       
    28   while(!IsEmpty())
       
    29     Remove();
       
    30 
       
    31 }
       
    32 
       
    33 
       
    34 int Component::AddToComponent(ListElement* intrvl, RLEMap* rlemap)
       
    35 //this needs to be fixed to trap page boundaries
       
    36 //or else pad the page with a blank line at top and bottom
       
    37 {
       
    38   assert(intrvl != NULL);
       
    39   List* list = new List();           //make a new queue
       
    40   ListElement* current;
       
    41   ListElement* nextelt;
       
    42   int counter = 0;
       
    43   int currentRow;
       
    44 
       
    45   if (intrvl->previous != NULL)
       
    46     intrvl->previous->next = intrvl->next;
       
    47   else rlemap->fMapData[((RLEPair *) intrvl->item)->row]->first = intrvl->next;
       
    48   if (intrvl->next != NULL)
       
    49     intrvl->next->previous = intrvl->previous;
       
    50   list->first = intrvl;              //put starting interval on queue
       
    51   list->last = intrvl;
       
    52   list->length = 1;
       
    53   intrvl->next = NULL;
       
    54   intrvl->previous = NULL;
       
    55   currentRow = 0;
       
    56   while ((intrvl = list->first) != NULL && 
       
    57 	 currentRow < rlemap->imageLength()) //Take an interval off queue
       
    58     {
       
    59       currentRow = ((RLEPair *) intrvl->item)->row;
       
    60       for (int i=-1; i < 2; i+=2) { 
       
    61 	current = rlemap->fMapData[currentRow+i]->first;
       
    62 	while ((current != NULL) 
       
    63 	       && (((RLEPair *) current->item)->start <= 
       
    64 		   ((RLEPair *) intrvl->item)->end+MinHorizSeparation)) {
       
    65 
       
    66 //	  printf("Looking at an interval on row %d that goes from %d to %d\n",
       
    67 //		 currentRow, ((RLEPair *) intrvl->item)->start,
       
    68 //		  ((RLEPair *) intrvl->item)->end);
       
    69 
       
    70 	  if ((((RLEPair *) current->item)->end 
       
    71 	       >= ((RLEPair *) intrvl->item)->start-1) 
       
    72 	      && (((RLEPair *) current->item)->start <= 
       
    73 		  ((RLEPair *) intrvl->item)->end+MinHorizSeparation)) {
       
    74 //	  printf("Adding connection for interval on row %d that goes from %d to %d\n", currentRow+i,
       
    75 //		 ((RLEPair *) current->item)->start,
       
    76 //		  ((RLEPair *) current->item)->end);
       
    77 	
       
    78 	    if (current->previous != NULL)
       
    79 	      current->previous->next = current->next;   //take off RLEMap
       
    80 	    else
       
    81 	      rlemap->fMapData[currentRow+i]->first = current->next;
       
    82 	    if (current->next != NULL)
       
    83 	      current->next->previous = current->previous;
       
    84 	    nextelt = current->next;
       
    85 	    list->last->next = current;                //add to queue
       
    86 	    current->previous = list->last;
       
    87 	    list->last = current;
       
    88 	    current->next = NULL;
       
    89 	    current = nextelt;
       
    90 	    list->length++;
       
    91 	  } else
       
    92 	    current = current->next;
       
    93 	}
       
    94       }
       
    95       
       
    96       if ((((RLEPair *) intrvl->item)->start < ful.x()) || (ful.x()==-1)) {
       
    97 	ful.x() = ((RLEPair *) intrvl->item)->start;
       
    98 //	printf("Changed ful.x to %d\n", ful.x());
       
    99       }
       
   100       if ((((RLEPair *) intrvl->item)->end > flr.x()) || (flr.x()==-1)) {
       
   101 	flr.x() = ((RLEPair *) intrvl->item)->end;
       
   102 //	printf("Changed flr.x to %d\n", flr.x());
       
   103       }
       
   104       if ((((RLEPair *) intrvl->item)->row < ful.y()) || (ful.y()==-1)) {
       
   105 	ful.y() = ((RLEPair *) intrvl->item)->row;
       
   106 //	printf("Changed ful.y to %d\n", ful.y());
       
   107       }
       
   108       if ((((RLEPair *) intrvl->item)->row > flr.y()) || (flr.y()==-1)) {
       
   109 	flr.y() = ((RLEPair *) intrvl->item)->row;
       
   110 //	printf("Changed flr.y to %d\n", flr.y());
       
   111       }      
       
   112       list->first = intrvl->next;
       
   113       if (intrvl->next != NULL)
       
   114 	intrvl->next->previous = NULL;
       
   115       delete ((RLEPair *) (intrvl->item));
       
   116       delete intrvl;               //so the letter O won't go forever
       
   117       counter++;
       
   118       list->length--;
       
   119     }
       
   120 
       
   121   delete list;
       
   122   return counter;
       
   123 
       
   124 }
       
   125 
       
   126 void Component::setProperties(BitMap * map)  // was BitMap
       
   127 /*--------------------------------------------------------------
       
   128 Primary Purpose: Set the property vector for this component
       
   129 Arguments:  The BitMap to which this component belongs
       
   130 Return Value:
       
   131 Effects: The component is divided into a 5 by 5 grid.  A gray
       
   132     scale (0 - 255) for each section is determined.  The gray scale
       
   133     is 0 for all white, 255 for all black, but normally will be somewhere
       
   134     between the two.  The gray scales are represented in properties
       
   135     0-24. 
       
   136     Property 25 is the grayscale accross the top.
       
   137     Property 26 is the grayscale accross the bottom.
       
   138     Property 27 is the width/height ratio again scaled to (0-255)
       
   139     Actually the formula for property 27 is
       
   140         width/ height * 255  if height > width
       
   141         1- height/width * 255 if width > height
       
   142     This way near 0 is very tall and thin
       
   143              near 128 height near width
       
   144 	     near 255 very wide
       
   145     Property 28 is  Indicator of a vertically disjoint character
       
   146      like i and j.
       
   147     Also the total number of black pixels is set in fnumBits.
       
   148     // This is not used at this time.    
       
   149 Constraints: The data fields ful and flr must already be set 
       
   150    before calling this function. These fields specify a bounding
       
   151    box for the character within the BitMap.
       
   152 Rev: 12/9 KM
       
   153 ---------------------------------------------------------------*/
       
   154 {
       
   155   if (ful > flr) 
       
   156     printf("Problem\n");
       
   157   assert (ful <= flr);
       
   158   short int hflag[NumHorizDiv + 1];  // flags horizontal section dividers
       
   159   short int vflag[NumVertDiv + 1];   // flags vertical section dividers
       
   160   float height, width;
       
   161   int propNum;
       
   162   float darkest = 0;
       
   163   float lightest; 
       
   164   int darkrow = 0;
       
   165   int lightrow = 0;
       
   166 
       
   167   Point sectionLr, sectionUl;
       
   168   // Set Number of bits
       
   169   fnumBits = map->pixelsInRegion(ful, flr);
       
   170 
       
   171   setSectionFlags(hflag, vflag);
       
   172   for (int r = 0; r < NumVertDiv; r++)
       
   173     for (int c = 0; c < NumHorizDiv; c++)
       
   174       {
       
   175 	propNum = (r * NumHorizDiv) + c;
       
   176 	sectionUl = Point(hflag[c], vflag[r]);
       
   177 	sectionLr = Point(hflag[c+1]-1, vflag[r+1]-1);
       
   178 	if (sectionUl <= sectionLr)
       
   179 	  fproperty[propNum] = map->grayScale(sectionUl, sectionLr); 
       
   180 	assert(fproperty[propNum] >= 0 && fproperty[propNum] < 256);
       
   181       }
       
   182 
       
   183   // set the height/width ratio
       
   184   // 0 is very thin 128 is even 256 is very wide.
       
   185   width = flr.x() - ful.x() + 1;
       
   186   height = flr.y() - ful.y() + 1;
       
   187  
       
   188   // Grayscale across the top - Indicator of top bar
       
   189   sectionUl = Point(ful.x(), ful.y());
       
   190   sectionLr = Point(flr.x(), ful.y() + (int)(height/(NumVertDiv*2)));
       
   191   fproperty[25] = map->grayScale(sectionUl, sectionLr);
       
   192 
       
   193    // Grayscale across bottom - Indicator of a foot for l opposed to 1
       
   194   sectionUl = Point(ful.x(),  flr.y() -  (int)(height/(NumVertDiv*2)));
       
   195   sectionLr = Point(flr.x(),  flr.y());
       
   196   fproperty[26] = map->grayScale(sectionUl, sectionLr);
       
   197 
       
   198   float hdivw = (float)height/width;
       
   199   float wdivh = (float) width/height;
       
   200   if (width > height)
       
   201        fproperty[27]= (short int) ((1- hdivw/2)*255);
       
   202   else
       
   203     fproperty[27] = (short int)((wdivh/2)* 255);
       
   204 
       
   205   // is this a disjoint character like i or j  255 = yes 0 = no
       
   206   fproperty[28]=0;
       
   207   lightest = width;
       
   208   for(int row = ful.y(); row < flr.y(); row++)
       
   209       {
       
   210 	int pixelsThisRow = pixelsBetween(map->row(row), ful.x(), flr.x());
       
   211 	if(!(pixelsThisRow))
       
   212 	      fproperty[28]=255;
       
   213       }
       
   214 
       
   215   fproperty[29]= 0;
       
   216     for(int p = 0; p < numProperties; p++)	
       
   217       assert(fproperty[p] >= 0 && fproperty[p] < 256);
       
   218 
       
   219 
       
   220 }
       
   221 
       
   222 void Component::setSectionFlags(short int hflag[], short int vflag[])
       
   223 /*--------------------------------------------------------------
       
   224 Primary Purpose: Breaks this component into a grid NumHorizDiv X NumVertDiv
       
   225     for determining grayscale property vectors.
       
   226 Arguments:  hflag[] is an empty array to be filled by this procedure with
       
   227     the starting columns of each horizontal subdivision.  vflag[] will
       
   228     be filled with the vertical subdivisions.
       
   229 Effects:  fills hflag[] with the starting column for each subdivision.
       
   230      The last element of the array is actually the pixel immediately 
       
   231      following the last  subdivision.  The last subdivision contains any 
       
   232      remaining pixels that did not divide evenly amongst the divisions.
       
   233      vflag[NumHorizDiv] is comparable for vertical supdivisions.
       
   234      Example ful = (0,25) flr = (52,46) NumHorizDiv = NumVertDiv = 5
       
   235          hflag[6] = { 0,10,20,30,40,53 }
       
   236 	 vflag[6] = {25.29.33.37.41.47 } 
       
   237 Constraints: ful and flr must be set to mark the bounding box before
       
   238    calling this procedure.
       
   239 Rev:  10/27 KM
       
   240 ---------------------------------------------------------------*/
       
   241 {
       
   242   int ulx = ful.x();  int uly = ful.y();
       
   243   int lrx = flr.x();  int lry = flr.y();
       
   244 
       
   245   int width =  lrx - ulx+1;
       
   246   int height = lry - uly+1;
       
   247 
       
   248   int horizDiv = width/NumHorizDiv;
       
   249   int vertDiv = height/NumVertDiv;
       
   250 
       
   251   int horizExtra = width - horizDiv*NumHorizDiv;
       
   252   int vertExtra = height - vertDiv*NumVertDiv;
       
   253 
       
   254   int i, add;
       
   255   for (i = 0; i < NumHorizDiv; i++)
       
   256     {
       
   257     if(horizExtra - i > 0) add = i; else add = horizExtra;
       
   258     hflag[i] = ulx + (i*horizDiv)+ add;
       
   259   }
       
   260   hflag[i] = lrx + 1;              // Closes off last division
       
   261 
       
   262   int j;
       
   263   for(j = 0; j < NumVertDiv; j ++)
       
   264       {
       
   265     if(vertExtra - j > 0) add = j; else add = vertExtra;
       
   266     vflag[j] = uly + (j*vertDiv)+ add;
       
   267   }
       
   268   vflag[j] = lry + 1;
       
   269 
       
   270     
       
   271 
       
   272 
       
   273 }
       
   274 
       
   275 
       
   276 Distance Component::distance(Component * comp) 
       
   277 /*--------------------------------------------------------------
       
   278 Primary Purpose: Determines heuristic distance between two components
       
   279 Arguments:  Another component to compare
       
   280 Return Value: integer value which represents the distance between two 
       
   281    components. Distance = sum over i of
       
   282                        weight *square (this->fproperty[i] - comp->fproperty[i])
       
   283 		       weight for i == 27, 28 is 3 weight is 1 for all other 
       
   284 		       properties
       
   285 Constraints: setProperties must have been run on both components
       
   286 
       
   287 Rev: 11/1 KM
       
   288 ---------------------------------------------------------------*/
       
   289 {
       
   290   Property * a = fproperty;
       
   291   Property * b = comp->properties();
       
   292   Distance dist=0;
       
   293   int dif=0;
       
   294   int worst = 0;
       
   295   int weight = 1;
       
   296 
       
   297   for(int i= 0; i < numProperties; i++)
       
   298     { 
       
   299 
       
   300 
       
   301      if (i == 27 || i == 28) weight = 3;
       
   302      else weight = 1;
       
   303      
       
   304        dif = (a[i] - b[i]);      
       
   305       dist += weight*dif*dif;
       
   306     }
       
   307 
       
   308   return dist;
       
   309 }
       
   310 
       
   311 
       
   312 
       
   313 
       
   314 
       
   315 
       
   316 
       
   317 
       
   318 
       
   319 void printVector(short int vector[], int size)
       
   320 {
       
   321   for (int i = 0; i < size; i++)
       
   322     cout << vector[i] << " " ;
       
   323   cout << endl;
       
   324 
       
   325 }
       
   326 
       
   327 
       
   328 void testProperties(Component* c, BitMap * map)
       
   329 {
       
   330   short int hflag[NumHorizDiv + 1];  // flags horizontal section dividers
       
   331   short int vflag[NumVertDiv + 1];   // flags vertical section dividers
       
   332 
       
   333   cout << "First test subDivisions  " << endl;
       
   334   c->setSectionFlags(hflag, vflag);
       
   335   cout << "Horizontal flags" <<endl;
       
   336   printVector(hflag, NumHorizDiv + 1);
       
   337   cout << "Vertical flags" <<endl;
       
   338   printVector(vflag, NumHorizDiv + 1);
       
   339 
       
   340   cout << "Now lets look at the properties " << endl;
       
   341   // setSectionFlags will actually get called again within setProperties
       
   342   c->setProperties(map);
       
   343   printVector(c->properties(), NumHorizDiv*NumVertDiv + 1);
       
   344   cout << endl << " The distance of this component from itself: " << " ";
       
   345   cout << c->distance(c) << endl;
       
   346 
       
   347 }
       
   348 
       
   349 void Component::display_bounding_box()
       
   350 {
       
   351   int ulx = (ul()).x();
       
   352   int uly = (ul()).y();
       
   353   int lrx = (lr()).x();
       
   354   int lry = (lr()).y();
       
   355   scale(ulx); scale(uly); scale(lrx); scale(lry);
       
   356   
       
   357   docommand(".main_window.display.work_space create rectangle %d %d %d %d -outline blue -tags IMAGE_TAG",  ulx, uly, lrx, lry);
       
   358 }  
       
   359 
       
   360 Distance Component::recognize(Component * learnedchars)
       
   361 // This is out of date. Current recognize is below
       
   362 {
       
   363   Distance d, nextd;
       
   364   char id;
       
   365 
       
   366 //  printf("Another call to recognize\n");
       
   367   d = (256*256)*numProperties;  // this is the biggest distance
       
   368                         
       
   369 
       
   370 	       
       
   371     for (int i = 0; i < 256; i++)
       
   372 	{
       
   373 	  if(learnedchars[i].confid() != 0)
       
   374 	      {
       
   375 		nextd = distance(&learnedchars[i]);
       
   376 //		printf("Distance = %d, character = %c\n", nextd, i);
       
   377 		if (nextd < d)
       
   378 		    {
       
   379 		      d = nextd;
       
   380 		      id = (char) i;
       
   381 		    }
       
   382 	      }
       
   383 	  
       
   384 	}
       
   385   
       
   386   fasciiId = id;
       
   387   /*  printf("Recognized a Component: %c\n", id); */
       
   388   return d;
       
   389 }
       
   390 
       
   391 
       
   392 Distance Component::recognize(Components * learnedgroups, bool allGroups)
       
   393 {
       
   394   Distance d, worstDistance,nextd;
       
   395   char id;
       
   396   short int fontid;
       
   397   float tempd;
       
   398   worstDistance = 150000;
       
   399 
       
   400 //  printf("Another call to new recognize\n");
       
   401   d = (65536)*numProperties;  // this is the biggest distance
       
   402   
       
   403                         
       
   404     fconfid = 0;
       
   405 
       
   406     for(int g = 0; g < NumCharGroups &&
       
   407  	((fconfid < ConfidenceThreshold) || allGroups); g++)
       
   408     {
       
   409       int offset = (charGroup+g) % NumCharGroups;
       
   410       if (offset == 4 && charGroup != 4) continue;
       
   411       for (ListElement* ptr = learnedgroups[offset].first; ptr != NULL;
       
   412 	 ptr = ptr->next)
       
   413 	{
       
   414 	  Component * item = (Component *) ptr->item;
       
   415 	  nextd = distance(item);
       
   416 //	  printf("Distance = %d, character = %c\n", nextd, i);
       
   417 	  if (nextd < d)
       
   418 	      {
       
   419 		d = nextd;
       
   420 		id = item->fasciiId;
       
   421 		fontid = item->ffontId;
       
   422 	      }
       
   423 
       
   424 	}
       
   425 
       
   426       if (d >= worstDistance) 
       
   427 	  tempd = worstDistance - 1;
       
   428       else tempd = d;
       
   429 	
       
   430 	fconfid = (unsigned short int)
       
   431 	  (255 - (tempd/worstDistance)*256);
       
   432       if(charGroup == 4) break;  // dont check other groups for floaters
       
   433     }
       
   434   
       
   435 
       
   436   fasciiId = id;
       
   437 
       
   438 
       
   439   ffontId = fontid;
       
   440 //  printf("Recognized a Component: %c in font#%d  %d %u\n", 
       
   441 //	 id, fontid, fconfid, d);
       
   442 
       
   443 
       
   444 
       
   445   return d;
       
   446 }
       
   447 
       
   448 
       
   449 
       
   450 int Component::vertShrink(BitMap * bitmap)
       
   451 {
       
   452   int r;
       
   453   int shrunk = 0;
       
   454 	for(r = ful.y(); r < flr.y(); r++)
       
   455 	      if (pixelsBetween(bitmap->row(r), ful.x(), flr.x()))
       
   456 		  {
       
   457 		    ful.y() = r;
       
   458 		    shrunk = 1;
       
   459 		    break;
       
   460 		  }
       
   461 	for(r = flr.y(); r > ful.y(); r--)
       
   462 	      if (pixelsBetween(bitmap->row(r), ful.x(), flr.x()))
       
   463 		  {
       
   464 		    flr.y() = r;
       
   465 		    shrunk = 1;
       
   466 		    break;		    
       
   467 		  }
       
   468 		
       
   469   return shrunk;
       
   470       }
       
   471 
       
   472 
       
   473 
       
   474