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:
Simba Code:
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):
pascal Code:
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:
pascal Code:
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:
log Code:
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