SRL Archive - SRL-OSR Snippets

OCR-Engine for OSRS


slacky

2014-12-04 05:27:11

I know Simba does a good job already, and tesseract can be tweaked to work for most text, but there is room for yet another alternative, so here it goes:
I've just written a small OCR-engine for OSRS. I don't have the possibility to test it properly my self, but I assume it works like it should (mostly). This engine is pretty much an upgrade for my old one (OCR-engine for OSR (Uptext)), and it's still a early version, might have to add some updates at some point (time will tell).

Motivation:
  • Should read connected chars properly (biggest motivator, Simba can't do this (example))
  • Simpler to use then my old one (no script-side functions needed to have it working)
  • Should work for most fonts in OSRS, not just uptext (just load the correct font).
  • Tweak-able - You pass it a very simple "filter" (my old one had hard-coded tolerance and shit).
  • Can use thresholding instead of having to pass a specific color (so it can read textline that has many colors)

It has a small "issue": It is extremely good at adding noise-chars (".-,_") to the result (only when threshold is used), mostly just when it's run on some random image (where the text is not recognized). I could probably write "hack" to remove most of it, but i don't see why I should bother (yet).

Sidenote: The engine should work in other games. EG: RS3 as long as the font is NOT smooth, and you have a proper charset for it.


Methods exported:

procedure TFontSet.Load(Font:AnsiString; Space:Int32=4);
procedure TFontSet.Free();

procedure TSimpleOCR.Init(Font:TFontSet; Dbg:LongBool=False; AClient:TTarget_Exported=ExportImageTarget());
procedure TSimpleOCR.Init(Font:AnsiString; SpaceWidth:Int32=4; Dbg:LongBool=False; AClient:TTarget_Exported=ExportImageTarget()); overload;
procedure TSimpleOCR.SetFont(Font:TFontSet);
procedure TSimpleOCR.SetFont(Font:AnsiString; SpaceWidth:Int32=4); overload;
procedure TSimpleOCR.Free();
function TSimpleOCR.Recognize(B:TBox; Filter:TCompareRules; MaxWalk:Int32=40): AnsiString;
function TSimpleOCR.RecognizeEx(AClient:T2DIntArray; Filter:TCompareRules; MaxWalk:Int32=40): AnsiString; overload;
As you see there is no IsText(..), there is only Recognize(..), it does all that is needed, the rest can easily be done scriptside.
@`dbg` (debug) parameter is simple (in OCR.Init): if "True" the client matrix is not freed once the image has been read, so you can debug it (TSimpleOCR.Client) and write it to a bitmap, mostly just to check if threshold looks correct, or if the passed box (B) is correctly positioned.


Example usage (Coordinates might be off, and filters might be iffy):
Simple example (uptext):

program SimpleExample;
{$loadlib SimpleOCR.dll}
var
OCR: TSimpleOCR;
begin
OCR.Init('UpChars07_s'); //or preferable: OCR.Init('UpChars07_s',,,ExportImageTarget());
WriteLn(OCR.Recognize(TBox([7,7,465,25]), TCompareRules([-1,72,True,55]))); //filter = [AnyColor,72 tol, UseShadows!, 55 shadow tol]
end;

Extended example:

program FullExample;
{$loadlib SimpleOCR.dll}

const
(*
TCompareRules:
If color = -1 and useshadows=False then tolerance is ignored, it will use thresholding instead.
Both shadows, and threshold is never used at the same time:
- If HasShadow = True then shadows are used (specify shadow tolerance)
- Else threshold is used (specify threshold, and if you need to invert the threshold)

Example of using with some color:
WriteLn(OCR.Recognize([29,34,450,51], [myColor, myTolerance]));

// fields in the type is something like:
IN: (Color,Toleranse), (HasShadow,ShadowTolernace), (Threshold,InvertThreshold)
EG: [-1, 0, False, 0, 50, False]
*)
//Example "filters" (could need tweaking)
OCR_RULES_DEFAULT:TCompareRules = [-1,,,,50,False]; //Threshold
OCR_RULES_UPTEXT: TCompareRules = [-1,75,True,55]; //Shadow
OCR_RULES_CHATBOX:TCompareRules = [-1,,,,-80,True]; //Threshold
OCR_RULES_BLUE: TCompareRules = [16711680,10]; //navy-blue text (chatbox msg)
OCR_RULES_BLACK: TCompareRules = [0,10]; //black text (chatbox nick)



// Uses
var
SmallFont,UpFont:TFontSet;
OCR: TSimpleOCR;
i:Int32;
begin
UpFont.Load('UpChars07_s'); // fontloading (can be forced freed with UpFont.Free() for example)
SmallFont.Load('SmallChars07'); // tho memory should be automanaged.

OCR.Init(UpFont); // OCR initialization (font)

// Uptext
WriteLn('Example 1: '+OCR.Recognize(TBox([7,7,465,25]), OCR_RULES_UPTEXT));

// Duel Arena challenge (The header "Dueling with: ...")
OCR.SetFont(SmallFont);
WriteLn('Example 2: '+OCR.Recognize(TBox([29,34,450,51]), OCR_RULES_DEFAULT));

// Chatbox
for i:=0 to 6 do
WriteLn('Example 3: '+OCR.Recognize(TBox([8,359+(14*i),480,374+(14*i)+1]), OCR_RULES_CHATBOX));
end;



Plugin (just extract the dll to the plugin folder):
- https://github.com/slackydev/SimpleOCR/releases

Source:
- https://github.com/slackydev/SimpleOCR/


Note:
It only works in Lape. I do not plan on supporting PascalScript.


Changelog:

06/12/14: Fix: Issue with grabbing the client image when using SMART. Updated examples, and the Init-function to reflect this change.
06/12/14: Fix: Text could start with space.
19/12/14: Addition: function TSimpleOCR.Recognize(AClient:T2DIntArray; Filter:TCompareRules; MaxWalk:Int32=40): AnsiString; overload;
19/12/14: Update: Should compile on linux now.
19/12/14: Fix: Issue caused `?`-font (63.bmp) to not load
04/02/15: Fix: Removed 1 (maybe 2) bug(s), and added some more error-handling.
... For more changes check it out at github.

PS: For proper implementation, so that it works with SMART you will need to actively updte the client, so that it's in tune with simba, this can be done by overrideing exported methods. See:
> https://github.com/SRL/SRL/blob/master/osr/text.simba

Hoodz

2014-12-04 06:02:25

From: slacky
*snip*


very nice slacky!

Janilabo

2014-12-04 08:14:58

Source code looks pretty damn good - nice work, @slacky!

Also mate, I am really glad to see that you are back in action. :p

slacky

2014-12-04 09:43:33

From: hoodz
very nice slacky!

Thanks!

From: Janilabo
Source code looks pretty damn good - nice work, @slacky!

Also mate, I am really glad to see that you are back in action. :p

Thanks. Been a long time since I've heard from you buddy.

I hope that this engine will get some uses, and even replace my old ("hacky") one :)

slacky

2014-12-06 15:42:51

Added a fix: There was an issue when using SMART with this, the way I grabbed the target-image would have failed with SMART as it's not like other targets.
Thanks @Olly for noticing it.

rj

2014-12-06 15:49:53

This looks pretty bad a, always had trouble reading 'CharsNPC07'

slacky

2014-12-06 16:25:04

From: Robert
This looks pretty bad a, always had trouble reading 'CharsNPC07'

CharsNPC07 should work fine, I did a couple of tests on it which came back flawless.
And what looks bad?

Sjoe

2014-12-06 16:31:20

From: slacky
CharsNPC07 should work fine, I did a couple of tests on it which came back flawless.
And what looks bad?


he meant badass

slacky

2014-12-06 16:36:28

From: Sjoe
he meant badass

Aha, thank you for explaining! :)

riwu

2014-12-10 10:05:46

OCR has been pretty accurate except 1 minor detection error:
http://puu.sh/doVxz/8e2b72d6b1.png
http://puu.sh/doVvA/79c9b3631b.png

var
OCR: TSimpleOCR;
i: integer;
begin
OCR.LoadFont('SmallChars07');
for i:=0 to 10 do
writeln(OCR.Recognize(IntToBox(109, 60, 182, 70 + i), [2070753, 0]));
end.
It's detecting the underscore as dots: 'Darkace…….25'
Using Replace() as a temp fix now :)

slacky

2014-12-10 11:50:32

From: riwu
OCR has been pretty accurate except 1 minor detection error:
http://puu.sh/doVxz/8e2b72d6b1.png
http://puu.sh/doVvA/79c9b3631b.png

var
OCR: TSimpleOCR;
i: integer;
begin
OCR.LoadFont('SmallChars07');
for i:=0 to 10 do
writeln(OCR.Recognize(IntToBox(109, 60, 182, 70 + i), [2070753, 0]));
end.
It's detecting the underscore as dots: 'Darkace…….25'
Using Replace() as a temp fix now :)


It's not a bug/error. It's the fontset (SmallChars07) that is lacking the underscore (95.bmp) font.
The 95.bmp from SmallChars fits the SmallChars07, just copy that one.

PS: Seems like you are still using the prototype engine, since that one is pure lape its much slower, it also lack some small fixes ;P

riwu

2014-12-16 00:37:07

From: slacky
It's not a bug/error. It's the fontset (SmallChars07) that is lacking the underscore (95.bmp) font.
The 95.bmp from SmallChars fits the SmallChars07, just copy that one.

PS: Seems like you are still using the prototype engine, since that one is pure lape its much slower, it also lack some small fixes ;P

Ahh I see didn't thought of that.

The script still has to wait for opponent's offer after reading the text so speed isnt an issue, easier for me to do minor adjustments using the pure lape version.
Also the plugin version is throwing 'Error: Don't know which overloaded method to call with params (AnsiString)', probably because of https://villavu.com/forum/showthread.php?t=110843 of which only ur simba has the fix ;)


procedure TSimpleOCR.Init(Font:TFontSet; Dbg:LongBool=False; AClient:TTarget_Exported=ExportImageTarget());
procedure TSimpleOCR.Init(Font:AnsiString; SpaceWidth:Int32=4; Dbg:LongBool=False; AClient:TTarget_Exported=ExportImageTarget()); overload;

slacky

2014-12-16 05:43:57

From: riwu
…
Also the plugin version is throwing 'Error: Don't know which overloaded method to call with params (AnsiString)'
…

Hmm. There shoudn't be any issue with overloads, just tried with older Simba versions, and it works fine for me. The "bug" you linked to is also unrelated to the issue you have.
Can anyone else verify the above issue? Where it fails to call overload method to init from string.

Flight

2014-12-16 06:17:17

This looks interesting and if you say it's an upgrade from your previous OCR engine, I'm all for it. Would you say it's worth replacing your old OCR engine in AeroLib with this new version, Slacky?

Also, whoever has tested this, how does it do speed-wise? Maybe this question is also best intended for you, Slacky. Would you say it's faster to recognize text as opposed to the older version?

slacky

2014-12-16 23:20:13

From: Flight
This looks interesting and if you say it's an upgrade from your previous OCR engine, I'm all for it. Would you say it's worth replacing your old OCR engine in AeroLib with this new version, Slacky?

Also, whoever has tested this, how does it do speed-wise? Maybe this question is also best intended for you, Slacky. Would you say it's faster to recognize text as opposed to the older version?

Idk. I guess it would be worth the update. Performance-wise the new one is a tad slower, but on the other hand it reads connected characters https://villavu.com/forum/showthread.php?t=111126.
It's slower because it doesn't have any shortcut "tricks", my old one could be passed a string like "more options" to make it quit once that text was read causing a significant boost in speed (in some cases), the new one doesn't have this feature, I'll consider adding it, and some other shit.
The new one can however work with most font-sets, which means you can read this: http://i.imgur.com/Rn49FlM.png :P

slacky

2014-12-21 15:45:29

I just got news from Olly that the OCR engine is added to Simbas updater (SRL-plugins), so you should now be able to use it without having to download it manually :)

Hoodz

2014-12-21 15:45:59

From: slacky
I just got news from Olly that the OCR engine is added to Simbas updater, so you should now be able to use it without having to download it manually :)


that's some great news!

Zhendos

2014-12-23 07:37:23

Thank you to share this with us!