Skip to content

Commit f90f23f

Browse files
committed
Improve RecognizeLines & add more tests.
1 parent 4802442 commit f90f23f

File tree

8 files changed

+119
-18
lines changed

8 files changed

+119
-18
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- uses: actions/[email protected]
5050

5151
- name: Install Lazarus
52-
uses: ollydev/setup-lazarus-fpcup@v3.2
52+
uses: ollydev/setup-lazarus-fpcup@v3.3
5353
with:
5454
laz: ${{ env.LAZ_VER }}
5555
fpc: ${{ env.FPC_VER }}
@@ -71,7 +71,7 @@ jobs:
7171
- uses: actions/[email protected]
7272

7373
- name: Install Lazarus
74-
uses: ollydev/setup-lazarus-fpcup@v3.2
74+
uses: ollydev/setup-lazarus-fpcup@v3.3
7575
with:
7676
laz: ${{ env.LAZ_VER }}
7777
fpc: ${{ env.FPC_VER }}

images/anycolor.png

593 Bytes
Loading

simpleocr.engine.pas

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ interface
7676
function _RecognizeX(Bounds: TBox; const MinCharacterCount, MaxWalk: Integer; out TextHits: Integer; out TextBounds: TBox): String;
7777
function _RecognizeXY(Bounds: TBox; const MinCharacterCount, MaxWalk: Integer; out TextHits: Integer; out TextBounds: TBox): String;
7878
public
79+
property Client: TIntegerMatrix read FClient;
80+
7981
function TextToMatrix(Text: String; constref FontSet: TFontSet): TIntegerMatrix;
8082
function TextToTPA(Text: String; constref FontSet: TFontSet): TPointArray;
8183

@@ -653,7 +655,7 @@ function TSimpleOCR.RecognizeStatic(Matrix: TIntegerMatrix; Filter: TOCRFilter;
653655

654656
function TSimpleOCR.RecognizeLines(Matrix: TIntegerMatrix; Filter: TOCRFilter; constref FontSet: TFontSet; out TextBounds: TBoxArray): TStringArray;
655657
var
656-
Bounds: TBox;
658+
SearchBox, Bounds, LastBounds: TBox;
657659
Text: String;
658660
Hits: Integer;
659661
MinCharacterPoints: Integer;
@@ -663,25 +665,31 @@ function TSimpleOCR.RecognizeLines(Matrix: TIntegerMatrix; Filter: TOCRFilter; c
663665

664666
if Self.Init(Matrix, FontSet, Filter, False) then
665667
begin
666-
MinCharacterPoints := FontSet.CharacterPoints[','];
668+
MinCharacterPoints := FontSet.CharacterPoints[','] + 1;
667669

668-
while (FSearchArea.Y1 + (FFontSet.MaxHeight div 3) < FSearchArea.Y2) do
670+
LastBounds := Box(-1, -1, -1, -1);
671+
SearchBox := FSearchArea;
672+
while (SearchBox.Y1 + (FFontSet.MaxHeight div 2) < FSearchArea.Y2) do
669673
begin
670-
Self._RecognizeX(FSearchArea, MinCharacterPoints, $FFFFFF, Hits, Bounds);
674+
// Find something on a row that is larger than `,`
675+
Self._RecognizeX(SearchBox, MinCharacterPoints, $FFFFFF, Hits, Bounds);
671676

672677
if (Hits > 0) then
673678
begin
674-
Text := Self._RecognizeXY(Box(FSearchArea.X1, FSearchArea.Y1, FSearchArea.X2, FSearchArea.Y1 + FFontSet.MaxHeight), MinCharacterPoints, $FFFFFF, Hits, Bounds);
675-
if (Text = '') then
679+
// OCR the row and some extra columns
680+
Text := Self._RecognizeXY(Box(SearchBox.X1, SearchBox.Y1, SearchBox.X2, SearchBox.Y1 + (FFontSet.MaxHeight div 2)), FontSet.CharacterPoints[Filter.MinCharacterMatch], $FFFFFF, Hits, Bounds);
681+
if (Text = '') or (Bounds.Y1 = LastBounds.Y1) then
676682
Exit;
677683

684+
LastBounds := Bounds;
678685
Result := Result + [Text];
679686
TextBounds := TextBounds + [Bounds];
680687

681-
FSearchArea.Y1 := Bounds.Y2 - (FFontSet.MaxHeight div 2);
688+
// Move down to the found text Bounds.Y2 (minus a little) so we don't recognize this again
689+
SearchBox.Y1 := Bounds.Y2 - (FFontSet.MaxHeight div 4);
682690
end;
683691

684-
FSearchArea.Y1 += 1;
692+
SearchBox.Y1 += 1;
685693
end;
686694
end;
687695
end;

tester/images/multiline3.png

18.6 KB
Loading

tester/images/multiline4.png

877 Bytes
Loading

tester/images/multiline5.png

7.2 KB
Loading

tester/test.bmp

-3.24 KB
Binary file not shown.

tester/tester.lpr

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ procedure Test_MultiLine1;
7878

7979
Assert(Length(Lines) = 5);
8080
Assert(Lines[0] = 'Select an Option');
81-
Assert(Lines[1] = 'Id like to access my bank account, please.');
82-
Assert(Lines[2] = 'Id like to check my PIN settings.');
83-
Assert(Lines[3] = 'Id like to collect items.');
81+
Assert(Lines[1] = 'I''d like to access my bank account, please.');
82+
Assert(Lines[2] = 'I''d like to check my PIN settings.');
83+
Assert(Lines[3] = 'I''d like to collect items.');
8484
Assert(Lines[4] = 'What is this place?');
8585
end;
8686

@@ -104,6 +104,96 @@ procedure Test_MultiLine2;
104104
Assert(Lines[1] = 'restore(4)');
105105
end;
106106

107+
procedure Test_MultiLine3;
108+
const
109+
Filter1: TOCRFilter = (
110+
FilterType: EOCRFilterType.COLOR;
111+
AnyColorFilter: ();
112+
ColorRule: (Colors: ((Color: $009933; Tolerance: 0)); Invert: False);
113+
ThresholdRule: ();
114+
ShadowRule: ();
115+
MinCharacterMatch: #0;
116+
);
117+
Filter2: TOCRFilter = (
118+
FilterType: EOCRFilterType.COLOR;
119+
AnyColorFilter: ();
120+
ColorRule: (Colors: ((Color: $00CC33; Tolerance: 0)); Invert: False);
121+
ThresholdRule: ();
122+
ShadowRule: ();
123+
MinCharacterMatch: #0;
124+
);
125+
var
126+
Lines: TStringArray;
127+
I: Integer;
128+
begin
129+
Lines := SimpleOCR.RecognizeLines(LoadMatrix('images/multiline3.png'), Filter1, FONT_PLAIN_11);
130+
for I := 0 to High(Lines) do
131+
Lines[I] := StringReplace(Lines[I], 'I', 'l', [rfReplaceAll]);
132+
133+
Assert(Length(Lines) = 5);
134+
Assert(Lines[0] = 'Leather Boots:');
135+
Assert(Lines[1] = 'Adamant Kiteshield:');
136+
Assert(Lines[2] = 'Adamant Helm:');
137+
Assert(Lines[3] = 'Emerald:');
138+
Assert(Lines[4] = 'Rune Longsword:');
139+
140+
Lines := SimpleOCR.RecognizeLines(LoadMatrix('images/multiline3.png'), Filter2, FONT_PLAIN_11);
141+
142+
Assert(Length(Lines) = 6);
143+
Assert(Lines[0] = '0');
144+
Assert(Lines[1] = '5');
145+
Assert(Lines[2] = '1');
146+
Assert(Lines[3] = '30');
147+
Assert(Lines[4] = '15');
148+
Assert(Lines[5] = '8');
149+
end;
150+
151+
procedure Test_MultiLine4;
152+
const
153+
Filter: TOCRFilter = (
154+
FilterType: EOCRFilterType.COLOR;
155+
AnyColorFilter: ();
156+
ColorRule: (Colors: ((Color: $000000; Tolerance: 0)); Invert: False);
157+
ThresholdRule: ();
158+
ShadowRule: ();
159+
MinCharacterMatch: #0;
160+
);
161+
var
162+
Lines: TStringArray;
163+
begin
164+
Lines := SimpleOCR.RecognizeLines(LoadMatrix('images/multiline4.png'), Filter, FONT_PLAIN_12);
165+
166+
Assert(Length(Lines) = 3);
167+
Assert(Lines[0] = 'Fishing XP: 20');
168+
Assert(Lines[1] = 'Next level at: 83');
169+
Assert(Lines[2] = 'Remaining XP: 63');
170+
end;
171+
172+
procedure Test_MultiLine5;
173+
const
174+
Filter: TOCRFilter = (
175+
FilterType: EOCRFilterType.COLOR;
176+
AnyColorFilter: ();
177+
ColorRule: (Colors: ((Color: 3099981; Tolerance: 0)); Invert: False);
178+
ThresholdRule: ();
179+
ShadowRule: ();
180+
MinCharacterMatch: #0;
181+
);
182+
var
183+
Lines: TStringArray;
184+
begin
185+
Lines := SimpleOCR.RecognizeLines(LoadMatrix('images/multiline5.png'), Filter, FONT_PLAIN_12);
186+
187+
Assert(Length(Lines) = 7);
188+
Assert(Lines[0] = 'Ahrim');
189+
Assert(Lines[1] = 'Dharok');
190+
Assert(Lines[2] = 'Guthan');
191+
Assert(Lines[3] = 'Karil');
192+
Assert(Lines[4] = 'Torag');
193+
Assert(Lines[5] = 'Verac');
194+
Assert(Lines[6] = 'Rewards potential: 0%');
195+
end;
196+
107197
procedure Test_UpText1;
108198
const
109199
Filter: TOCRFilter = (
@@ -231,14 +321,14 @@ procedure Test_Locate2;
231321
Fail, Pass: Integer;
232322
StartTime: UInt64;
233323

234-
function Test(Proc: TProcedure; Name: String): Boolean;
324+
procedure Test(Proc: TProcedure; Name: String);
235325
begin
236-
Result := True;
237-
238326
try
239327
WriteLn('Testing: ' + Name);
240328
Proc();
241329
WriteLn('Passed');
330+
331+
Inc(Pass);
242332
except
243333
on E: Exception do
244334
begin
@@ -247,7 +337,7 @@ function Test(Proc: TProcedure; Name: String): Boolean;
247337
else
248338
WriteLn('Failed: ', E.Message);
249339

250-
Result := False;
340+
Inc(Fail);
251341
end;
252342
end;
253343
end;
@@ -272,6 +362,9 @@ function Test(Proc: TProcedure; Name: String): Boolean;
272362
Test(@Test_Threshold2, 'Threshold2');
273363
Test(@Test_MultiLine1, 'MultiLine1');
274364
Test(@Test_MultiLine2, 'MultiLine2');
365+
Test(@Test_MultiLine3, 'MultiLine3');
366+
Test(@Test_MultiLine4, 'MultiLine4');
367+
Test(@Test_MultiLine5, 'MultiLine5');
275368
Test(@Test_UpText1, 'UpText1');
276369
Test(@Test_UpText2, 'UpText2');
277370
Test(@Test_Shadow, 'Shadow');
@@ -288,6 +381,6 @@ function Test(Proc: TProcedure; Name: String): Boolean;
288381
if (Fail > 0) then
289382
ExitCode := 1;
290383

291-
ReadLn;
384+
//ReadLn;
292385
end.
293386

0 commit comments

Comments
 (0)