Advertisement
WarPie90

Simple OCR for numbers

Mar 16th, 2017
455
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 5.24 KB | None | 0 0
  1. program new;
  2.  
  3. const
  4.   STR_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  5.   STR_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';
  6.   STR_LETTERS   = STR_UPPERCASE + STR_LOWERCASE;
  7.   STR_NUMBERS   = '0123456789';
  8.   STR_SYMBOLS   = '.,-<>?+()/\*';
  9.   STR_EVERYTHING= STR_LETTERS + STR_NUMBERS + STR_SYMBOLS;
  10.   STR_FNUMBERS  = STR_NUMBERS + '.';
  11.  
  12.  
  13. function PrepareTPAForOCR(TPA: TPointArray; size:Int32=18): TPointArray;
  14. var
  15.   muf: TMufasaBitmap;
  16.   B: TBox;
  17. begin
  18.   Result := Copy(TPA);
  19.   B := GetTPABounds(Result);
  20.   OffsetTPA(Result, Point(-B.X1,-B.Y1));
  21.  
  22.   muf := GetMufasaBitmap(CreateBitmap(B.x2-B.x1+2, B.y2-B.y1+2));
  23.   muf.DrawTPA(Result, $FFFFFF);
  24.   //WriteLn(size / muf.GetHeight * muf.GetWidth);
  25.   muf.ResizeEx(RM_Bilinear, Ceil(size / muf.GetHeight * muf.GetWidth), size);
  26.   muf.ThresholdAdaptive(0,255, False, TM_Mean, 0);
  27.   muf.FindColors(Result, 255);
  28.   muf.Free();
  29. end;
  30.  
  31.  
  32. function LoadFontFeatures(fontName:String; style:TFontStyles=[]; Chars:String = STR_EVERYTHING): T2DPointArray;
  33. var
  34.   W,H,i,x,y: Int32;
  35.   bmp: TBitmap;
  36.   tmp: TPointArray;
  37.   f: TFont;
  38. begin
  39.   F.Init();
  40.   F.SetName(fontName);
  41.   F.SetSize(20);
  42.   F.setStyle(style);
  43.   F.setQuality(fqNonAntialiased);
  44.   F.setColor($FFFFFF);
  45.   bmp.Init();
  46.  
  47.   bmp.GetCanvas().GetBrush().SetStyle(bsClear);
  48.   bmp.GetCanvas().SetFont(F);
  49.  
  50.   for i:=1 to Length(Chars) do
  51.   begin
  52.     bmp.Clear();
  53.     W := bmp.GetCanvas().TextWidth(Chars[i]) + 1;
  54.     H := bmp.GetCanvas().TextHeight(Chars[i]) + 1;
  55.     bmp.SetWidth(W);
  56.     bmp.SetHeight(H);
  57.     bmp.GetCanvas().TextOut(0,0, Chars[i]);
  58.  
  59.     for y:=0 to H-1 do
  60.       for x:=0 to W-1 do
  61.         if bmp.GetCanvas.GetPixel(x,y) = $FFFFFF then
  62.           tmp += Point(x,y);
  63.  
  64.     Result += PrepareTPAForOCR(TMP);
  65.     SetLength(tmp, 0);
  66.   end;
  67.   F.Free();
  68.   bmp.Free();
  69. end;
  70.  
  71.  
  72. function TPointArray.DistToNearest(p:TPoint): Double;
  73. var
  74.   i:Int32;
  75.   d:Double;
  76. begin
  77.   Result := 9999999;
  78.   for i:=0 to High(self) do
  79.   begin
  80.     d := Hypot(self[i].x-p.x, self[i].y-p.y);
  81.     if d < Result then
  82.     begin
  83.       Result := d;
  84.       if Result = 0 then Exit;
  85.     end;
  86.   end;
  87. end;
  88.  
  89. function DirtyMatchTPA(A,B:TPointArray): Double;
  90. var
  91.   i:Int32;
  92. begin
  93.   for i:=0 to High(A) do
  94.     Result += B.DistToNearest(A[i]);
  95.   Result /= Length(A);
  96. end;
  97.  
  98. function DirtyOCR(TPA:TPointArray; chars: T2DPointArray): TIntegerArray;
  99. var
  100.   i, j, charId:Int32;
  101.   best,this:Double;
  102.   ATPA: T2DPointArray;
  103.   B: TBox;
  104. begin
  105.   ATPA := ClusterTPAEx(TPA, 1,2);
  106.   B := GetTPABounds(TPA);
  107.   SortATPAFromMidPoint(ATPA, Point(B.x1,B.y1));
  108.  
  109.   for i:=0 to High(ATPA) do
  110.     ATPA[i] := PrepareTPAForOCR(ATPA[i]);
  111.  
  112.   for i:=0 to High(ATPA) do
  113.   begin
  114.     best := $FFFFFF;
  115.  
  116.     for j:=0 to High(chars) do
  117.     begin
  118.       this := (DirtyMatchTPA(ATPA[i], chars[j]) + DirtyMatchTPA(chars[j], ATPA[i])) / 2;
  119.       if this < best then
  120.       begin
  121.         best := this;
  122.         charId := j;
  123.       end;
  124.     end;
  125.     //if best < 5 then
  126.       Result += charId;
  127.   end;
  128. end;
  129.  
  130. function IndicesToString(idx:TIntegerArray; Lookup:String): String;
  131. var i:Int32;
  132. begin
  133.   for i:=0 to High(idx) do
  134.     Result += Lookup[idx[i]+1];
  135. end;
  136.  
  137. function GrabTextArea(Area:TBox; thresh: Int32; Debug:Boolean=True): T2DPointArray;
  138. var
  139.   i:Int32;
  140.   bmp:TMufasaBitmap;
  141.   TPA:TPointArray;
  142.   ATPA:T2DPointArray;
  143. begin
  144.   bmp := GetMufasaBitmap(BitmapFromClient(Area.x1,Area.y1,Area.x2,Area.y2));
  145.   bmp.ThresholdAdaptive(0,255, True, TM_Mean, thresh);
  146.  
  147.   if debug then
  148.   begin
  149.     DisplayDebugImgWindow(bmp.getWidth, bmp.getHeight);
  150.     DrawBitmapDebugImg(bmp.getIndex);
  151.   end;
  152.  
  153.   bmp.FindColors(TPA, 255);
  154.   ATPA := ClusterTPAEx(TPA, 10,4);
  155.   for i:=0 to High(ATPA) do
  156.     if True{add some checks perhaps} then
  157.       Result += ATPA[i];
  158.  
  159.   bmp.Free();
  160. end;
  161.  
  162.  
  163. function GrabTextFromColumns(area:TBox; thresh: Int32; borderColor, borderTol:Int32; Debug:Boolean=True): T2DPointArray;
  164. var
  165.   i:Int32;
  166.   bmp:TMufasaBitmap;
  167.   TPA,cols:TPointArray;
  168.   ATPA:T2DPointArray;
  169. begin
  170.   bmp := GetMufasaBitmap(BitmapFromClient(Area.x1,Area.y1,Area.x2,Area.y2));
  171.   bmp.ThresholdAdaptive(0,255, True, TM_Mean, thresh);
  172.  
  173.   FindColorsTolerance(cols, borderColor, Area.x1,Area.y1,Area.x2,Area.y2, borderTol);
  174.   OffsetTPA(cols, Point(-area.x1, -area.y1));
  175.   bmp.DrawTPA(cols, $FF0000);
  176.  
  177.   if debug then
  178.   begin
  179.     DisplayDebugImgWindow(bmp.getWidth, bmp.getHeight);
  180.     DrawBitmapDebugImg(bmp.getIndex);
  181.   end;
  182.  
  183.   bmp.FindColors(TPA, 0);
  184.   ATPA := ClusterTPA(TPA, 1);
  185.   for i:=0 to High(ATPA) do
  186.     Result += ReturnPointsNotInTPA(ATPA[i], GetTPABounds(ATPA[i]));
  187.  
  188.   bmp.Free();
  189. end;
  190.  
  191.  
  192.  
  193. var
  194.   input, chars:T2DPointArray;
  195.   str: String;
  196.   i,j:Int32;
  197. begin                   {search area, should only inc the columns}
  198.   input := GrabTextFromColumns([140,211, 520,485], -80, $C0C0C0, 50);
  199.  
  200.   chars := LoadFontFeatures('Tahoma', [], STR_FNUMBERS);
  201.  
  202.   for i:=0 to High(input) with 3 do //steps of 3
  203.   begin
  204.     str := '';
  205.     for j:=0 to 2 do //proccess the columns
  206.     begin
  207.       if i+j > High(input) then
  208.       begin
  209.         WriteLn(str);
  210.         Break(2); //nothing more to proccess
  211.       end;
  212.  
  213.       str += IndicesToString(DirtyOCR(input[i+j], chars), STR_FNUMBERS);
  214.       if j <> 2 then
  215.         str += '  |  '
  216.       else
  217.         WriteLn(str);
  218.     end;
  219.   end;
  220. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement