SRL Archive - Research & Development Lounge

Is Tesseract broken?


Sin

2014-09-02 21:27:48

I have a fairly functional Merchanter script which works really other than errors from Tesseract.
When trying to read the GE buy price (where it says 'You bought X of ITEM for a total price of X*ITEM gp.'), X*ITEM is almost ALWAYS wrong! Usually it returns -1, but if i'm lucky it'll return something like 109, where the buy price was 3159.

Are the fonts out dated? Im using the FILTER_SMALL_CHARS preset.

Olly

2014-09-02 21:30:58

From: Sin
I have a fairly functional Merchanter script which works really other than errors from Tesseract.
When trying to read the GE buy price (where it says 'You bought X of ITEM for a total price of X*ITEM gp.'), X*ITEM is almost ALWAYS wrong! Usually it returns -1, but if i'm lucky it'll return something like 109, where the buy price was 3159.

Are the fonts out dated? Im using the FILTER_SMALL_CHARS preset.


Tesseract doesn't require any fonts… :p

Post a picture of when it fails, il see if i can get you a better result.

Sin

2014-09-02 21:46:58

[ATTACH=CONFIG]23950[/ATTACH]

Olly

2014-09-02 22:05:27

From: Sin
[ATTACH=CONFIG]23950[/ATTACH]


Well, For a start you need to use new SRL & Simba (if you aren't) It's alot better with that. Find that here.

{$DEFINE TESSERACT_DEBUG} // Remove this if you dont want the debug
{$DEFINE SMART}
{$i srl-6/srl.simba}

var
BMP := BitmapFromString(33, 14, 'meJxNVEtrU1EQPo/7fuTmnZDQatKFRVAQQSpCYmi14LIBKwgiCqIiKCql6kJQkhRsig8QBItL10l3yQ9w44/yO/nqITAczp0z881887jNStT8L2erUTnVjaKzvpq0Gwk0/MSlWnB5x1kthDihXK2n59slWEKDJ5xQ4hOCzzRUaysFukDqOXNCCSgaEJ9o1EBwASxdKASEWA1g6YsTgLwQkGLT5lMlFxD8QjsGNeBDY9GYoQ0Be5CyaMSnAS/kCAQ9mrgHU0YBJitWazXS+/tqPEu3d2ncqpgzvPsa9vpoDheira63sgdvnaN5cqMPzUqjVM5O6TO0/+ij9+ZYDCaOlpYXzlLnJp7k4Ux2dpJA2azi/uPQk1pJufdT7r4ElLVUC0s2kc0yZbl02Xn/O9y6LQcTrURzaRIguVDJ4QQhSqnHxjFK5Ju2Rk8G6uEHhDN9z3wgIEQ+9cCC7hwGkM1d7enrfTU0IYiANMgRn+7BieoaRzbdFrO+dgY1DM5djAKHxs5oSr52Mlmi+OkQlOMthJhaFnaicKLsqttHCE44iSA9d/84vrenpAAjKvVoCstiLgAL2wX5/Y9hh/zHc4H7s8/AxITYQKDjGEfDgoWi3n/3C5PguQpVQjjoIRo43X4578MLyUAQCK9SCHQZNUS7cQdrk/l4btthQnR2AlcSH9sUvfoG7q6WSehwJnGiNQyRjxU/qeeSIqv8rTvg4jrmNbfREz/+ogLhlR68wFR8mrnPv7BuGB68mhkYYM5Par1tuGfXNmEpFpbei6/LW7+8eogOOrirw1m0sSmEgDJLNBokpUC/Au90j4qJFgvuULpa1ctmy0qZbyzFwtI11bO7yU1hhqgeZ0kpWSsG1gZKOyH8TVHDTbSrDVgiLyfPE9sNJeytsd2y5Z/MctmZEv8edkQpnK5/5JOlKA==');
W, H: Integer;
myFilter: TTesseractFilter;
begin
GetBitmapSize(BMP, W, H);
SetTargetBitmap(BMP);

// All you need this below...
myFilter := TTesseractFilter([4, 4, [False, 20, TM_Mean]]);
Tesseract_GetText(0, 0, W -1, H -1, myFilter); // Dont forget to change the area!
end;

Grabs it fine. Output:

-- Tesseract_GetText(): Filtering took: 0 ms, Tesseract Took: 47 ms, Total Time: 47 ms.
-- Tesseract_GetText(): Text found: 4,121

Sin

2014-09-02 22:07:12

From: Olly
Well, For a start you need to use new SRL & Simba (if you aren't) It's alot better with that. Find that here.

{$DEFINE TESSERACT_DEBUG} // Remove this if you dont want the debug
{$DEFINE SMART}
{$i srl-6/srl.simba}

var
BMP := BitmapFromString(33, 14, 'meJxNVEtrU1EQPo/7fuTmnZDQatKFRVAQQSpCYmi14LIBKwgiCqIiKCql6kJQkhRsig8QBItL10l3yQ9w44/yO/nqITAczp0z881887jNStT8L2erUTnVjaKzvpq0Gwk0/MSlWnB5x1kthDihXK2n59slWEKDJ5xQ4hOCzzRUaysFukDqOXNCCSgaEJ9o1EBwASxdKASEWA1g6YsTgLwQkGLT5lMlFxD8QjsGNeBDY9GYoQ0Be5CyaMSnAS/kCAQ9mrgHU0YBJitWazXS+/tqPEu3d2ncqpgzvPsa9vpoDheira63sgdvnaN5cqMPzUqjVM5O6TO0/+ij9+ZYDCaOlpYXzlLnJp7k4Ux2dpJA2azi/uPQk1pJufdT7r4ElLVUC0s2kc0yZbl02Xn/O9y6LQcTrURzaRIguVDJ4QQhSqnHxjFK5Ju2Rk8G6uEHhDN9z3wgIEQ+9cCC7hwGkM1d7enrfTU0IYiANMgRn+7BieoaRzbdFrO+dgY1DM5djAKHxs5oSr52Mlmi+OkQlOMthJhaFnaicKLsqttHCE44iSA9d/84vrenpAAjKvVoCstiLgAL2wX5/Y9hh/zHc4H7s8/AxITYQKDjGEfDgoWi3n/3C5PguQpVQjjoIRo43X4578MLyUAQCK9SCHQZNUS7cQdrk/l4btthQnR2AlcSH9sUvfoG7q6WSehwJnGiNQyRjxU/qeeSIqv8rTvg4jrmNbfREz/+ogLhlR68wFR8mrnPv7BuGB68mhkYYM5Par1tuGfXNmEpFpbei6/LW7+8eogOOrirw1m0sSmEgDJLNBokpUC/Au90j4qJFgvuULpa1ctmy0qZbyzFwtI11bO7yU1hhqgeZ0kpWSsG1gZKOyH8TVHDTbSrDVgiLyfPE9sNJeytsd2y5Z/MctmZEv8edkQpnK5/5JOlKA==');
W, H: Integer;
myFilter: TTesseractFilter;
begin
GetBitmapSize(BMP, W, H);
SetTargetBitmap(BMP);

// All you need this below...
myFilter := TTesseractFilter([4, 4, [False, 20, TM_Mean]]);
Tesseract_GetText(0, 0, W -1, H -1, myFilter); // Dont forget to change the area!
end;

Grabs it fine. Output:

-- Tesseract_GetText(): Filtering took: 0 ms, Tesseract Took: 47 ms, Total Time: 47 ms.
-- Tesseract_GetText(): Text found: 4,121


I'll try it out in the morning, awesome, thanks :)

Brandon

2014-09-02 22:18:52

From: Sin
I'll try it out in the morning, awesome, thanks :)


Oh man.. You have no idea how much of a heart-attack that thread title gave me -_-
Thought the plugin was broken for a sec.. That thing is literally the worst thing to compile of all time (for windows at least)..

Olly to the rescue!

Olly

2014-09-02 23:43:35

You can't really 'break' mr. Tesseract. You just have to feed it a nice image :D

I have 90% of a tool made for it, so you can work out the best settings and such.

e: I would post the unfinished version but its but its broken… wth :(

e2: Woo I made it run (apperantly i can't have a TMufasaBitmap as a const…?) It's attached below. If you have the new simba + srl-6 it should run fine for you, you can draw a box on the screen and crop by pressing space, control+v to load from clipboard too.

It's 100% Lape too.. Pretty impressed with myself heh. Only thing left to do is undo/redo.


Brandon

2014-09-03 01:07:54

From: Olly
apparently i can't have a TMufasaBitmap as a const…?



Wouldn't that be true of all classes/records/objects? It makes sense.. If it's const, you can't modify the internal state of the object (because it's supposed to be constant/immutable). If that's true for primitives and arrays, it has to be true for everything else too because everything else uses primitives and arrays and alike..

A const class/record/object would have to guarantee that you don't call any setter functions (functions that maybe setPixel, setWidth, setHeight, etc) as it'd "change" the state of the class/record/object.. yeah?


Anyway, what does the above tool actually do? I'm too lazy to download it and test it :l

Olly

2014-09-03 13:47:29

From: Brandon
…


:s wth..

var
BMP: TMufasaBitmap;

procedure Foo(const Bitmap: TMufasaBitmap);
begin
Writeln(Bitmap.getWidth());
end;

begin
BMP.Init();
Foo(BMP);
end.

Gives:
Error: Access violation at line 6

@nielsie95

Brandon

2014-09-03 14:02:03

From: Olly
:s wth..

Gives:
Error: Access violation at line 6

@nielsie95


Works:


procedure Foo(const Bmp: TMufasaBitmap);
begin
Writeln(Bmp.getWidth());
end;

var
BMP: TMufasaBitmap;
begin
BMP.Init(getTClient().getMBitmaps());
BMP.SetSize(100, 100);
Foo(BMP);

writeln(Bmp);

Bmp.Free();
end.


Also works:


procedure Foo(const Bmp: TMufasaBitmap);
begin
Writeln(Bmp.getWidth());
end;

var
BMP: TMufasaBitmap;
begin
BMP.Init();
Foo(BMP);

writeln(Bmp);

Bmp.Free();
end.


EDIT: I used the Simba on the post by Wizzup (announcement post).. It access violated.. I compiled Simba myself, it works.. I redownload his Simba, it works.. I cannot replicate this anymore.. I was only able to replicate it the very first time. I restarted Simba many times, it works..

Olly

2014-09-03 14:11:27

From: Brandon
Works:


Huh? Both dont work for me. :s

Brandon

2014-09-03 14:12:08

From: Olly
Huh? Both dont work for me. :s


See my edit..


For me:


Compiled successfully in 219 ms.
100
0xA14AE38
Successfully executed.


Compiled successfully in 203 ms.
0
0xA0D2EB0
Successfully executed.


EDIT:
@Olly; Uhh compile it yourself.. it'll work. The 52k kb (un-stripped.. I know) one works.

The one in Wizzup's release post (build-bot build-646) is broken.. Let him know that it needs recompiling.


Olly

2014-09-03 14:14:54

From: Brandon
See my edit..


For me:


Compiled successfully in 219 ms.
100
0xA14AE38
Successfully executed.


Compiled successfully in 203 ms.
0
0xA0D2EB0
Successfully executed.


I just got the newest master build, and it failed maybe you can try?

http://l0.lt/builders/master/builds/653

Brandon

2014-09-03 14:23:08

From: Olly
I just got the newest master build, and it failed maybe you can try?

http://l0.lt/builders/master/builds/653



Access-violation.. Both 646 and 653. Not sure what is wrong with those builds, but building it myself works fine.. I can even send you a copy of the executable or github folder and you'll see it works :l


For now just stay away from those builds and do it yourself.. Works for me. Build-bot releases keeps giving me access-violation. See the pic in the last post.

Olly

2014-09-03 14:32:05

From: Brandon
Access-violation.. Both 646 and 653. Not sure what is wrong with those builds, but building it myself works fine.. I can even send you a copy of the executable or github folder and you'll see it works :l


For now just stay away from those builds and do it yourself.. Works for me. Build-bot releases keeps giving me access-violation. See the pic in the last post.


Just cloned Simba, and built and it fails… :s Something is wrong..

Brandon

2014-09-03 14:38:21

From: Olly
Just cloned Simba, and built and it fails… :s Something is wrong..


I guess it's not build-bot then..

EDIT: I was tempted.. updated my clone.. access-violation even after compiling it myself.. ={

Olly

2014-09-03 14:45:45

From: Brandon
I guess it's not build-bot then..

In that case I'll make sure not to pull the very latest Simba.. something has to be wrong.

I uploaded a copy of my git clone here: http://www.mediafire.com/download/jtuiltql3hw3ycp/Simba.zip

It already contains a compiled executable which I forgot to remove. You can compile that yourself if you like. Let me know if it works for you.
It doesn't seem to have constref :S I was pretty sure it had it..


EDIT: I was tempted.. updated my clone.. access-violation even after compiling it myself.. ={


Yea if your old clone didn't have constref it obviously didnt have the lape update, which means of course it would work!

Brandon

2014-09-03 14:47:32

From: Olly
Yea if your old clone didn't have constref it obviously didnt have the lape update, which means of course it would work!


Yeah.. It doesn't work anymore -_- It's weird. I had constref the same day when I saw slacky's post on it.. Same day I explained what it does..

Well.. I guess const is just broken now.. I updated my clones :l

Olly

2014-09-03 14:53:50

From: Brandon
Yeah.. It doesn't work anymore -_- It's weird. I had constref the same day when I saw slacky's post on it.. Same day I explained what it does..

Well.. I guess const is just broken now.. I updated my clones :l


It seems to be when something is typed as 'type something' eg: This will crash too.

type
TFoo = type TClient;

var
Foo: TFoo;

procedure Test(const F: TFoo);
begin
Writeln(F.getMBitmaps());
end;

begin
Foo.Init();
Test(Foo);
end;

Not much more else we can do, either wait for niels or @Dgby714 to figure out what's up.

nielsie95

2014-09-03 15:17:21

Yes, this is expected behaviour because you're using a constant. Before, you could actually change the value of constants/literals with type methods.


{$assertions on} //Turn off to see that Self is actually not passed.

procedure NativeInt.TestMe;
begin
WriteLn(@Self);
Self := 123;
end;

begin
1.TestMe;
end.

Olly

2014-09-03 15:21:44

From: nielsie95
Yes, this is expected behaviour because you're using a constant. Before, you could actually change the value of constants/literals with type methods.


{$assertions on} //Turn off to see that Self is actually not passed.

procedure NativeInt.TestMe;
begin
WriteLn(@Self);
Self := 123;
end;

begin
1.TestMe;
end.


Maybe put a better error message on your to-do list? I could see other people getting confused with this.

nielsie95

2014-09-03 15:48:07

Good point :p

Brandon

2014-09-03 15:52:24

Well.. I'm completely lost now..


I don't see why the code Olly posted shouldn't work.. It should work even if it is constant because it is an Object..

This:


procedure NativeInt.TestMe;
begin
WriteLn(@Self);
Self := 123;
end;


shouldn't be valid syntax if it has no self pointer. What would be the point of it if you cannot even access the value pointed to by "this/self"?


It's like this:


Procedure TMufasaBitmap.something;
begin
//self is nil/null..
//cannot access self.getWidth() cannot access "self" so you cannot access "self.anything".
end;

In that case, it makes no sense allowing the scripter to override or overload or even compose such a function if self isn't accessible regardless of whether it is const.


procedure Test(const F: TFoo);
begin
Writeln(F.getMBitmaps());
end;

should be valid syntax since TFoo is an object and should have a self pointer (address of itself even though you can't take the address of a const).. It would be equivalent to:


Function getMBitmaps(const self: ^TFoo): SomeMBitmaps;
begin
Result := self^.bmps;
end;

And that's perfectly valid..


It now makes me confused as to why one is allowed and the other isn't. They are equivalent functions and should generate the same assembly.

nielsie95

2014-09-03 16:02:57

It depends on how you call it whether self will be nil. If you call it with a constant, it will be nil. I agree that it is not ideal, though. It would be better if the compiler gave an error when trying to call the method, instead of implicitly passing nil.

The difference between your examples is that in the second example, the actual object is not a constant, only the pointer to it is. A referenced pointer is always writable.

Brandon

2014-09-03 16:16:39

From: nielsie95
The difference between your examples is that in the second example, the actual object is not a constant, only the pointer to it is. A referenced pointer is always writable.



Ohh.. I see.

So is this the thinking behind it:


procedure test(const F: TFoo); //F itself is constant? as in a copy is made?
begin
F.set(X); //F is immutable and cannot be changed?
F := nil; //valid or not valid.. makes no diff.
end;

OR is it:


procedure test(const F: TFoo); //F is a constant reference to a mutable object?
begin
F.set(X); //perfectly valid because F is mutable?
F := nil; //not valid.
end;

Because in both cases, I don't understand why a "F.get()" wouldn't work since it doesn't modify anything and only "gets" data.

nielsie95

2014-09-03 16:34:00

Yes, the reasoning is as in your first example. Perhaps this explains it a bit further:


procedure setVal(var Self: Int32; NewVal: Int32);
begin
WriteLn('Regular proc: ', @Self);
end;

procedure Int32.setVal(NewVal: Int32);
begin
WriteLn('Type proc: ', @Self);
end;

procedure test(const a: Int32); overload;
begin
//setVal(a, 123); <-- Will not compile: "Variable expected"
a.setVal(456); // <-- Will pass "nil" for self, because a is constant/immutable
end;

procedure test(const a: ^Int32); overload;
begin
setVal(a^, 123); // <-- Dereference is always writable, so can pass as variable
a^.setVal(456); // <-- Dereference is always writable, so can pass as variable
end;

var
i: Int32 = 1;
begin
test(i);
test(@i);
end;

I would like to make "a.setVal(456)" give a compiler error too, but currently that would interfere with code like "WriteLn(@Int32.setVal)" if executed in the above example.

slacky

2014-09-18 06:19:11

I really preferred how we where able to pass constants before, this changes to constant is only limiting what we can do, we can no longer write as expressive code..

the fact that "1.HelloWorld" passes nil is something I really really do not like. I would much rather see a copy passed, or heck.. be able to change the constant. It was useful to me to be able to do shit like { ' '.join(['hello', 'world', '=)']); } .. So, I am a bit angry @nielsie95 for that change, it's not welcomed by me.

nielsie95

2014-09-19 11:47:12

I agree that it is not a good solution currently. What I want to do is have "variable" and "constant" type methods, similar to regular parameters. Then, instead of passing nil for "mismatches", the compiler could give an error. Constant type methods would not be able to modify Self, while variable type methods (the default) would behave as type methods do currently (with a mutable Self variable).

slacky

2014-09-20 01:27:12

From: nielsie95
I agree that it is not a good solution currently. What I want to do is have "variable" and "constant" type methods, similar to regular parameters. Then, instead of passing nil for "mismatches", the compiler could give an error. Constant type methods would not be able to modify Self, while variable type methods (the default) would behave as type methods do currently (with a mutable Self variable).

That does sound like a usable concept; it does require us to repeat our code twice every time we need both var and const-versions. But I see that it might just be what's needed to achieve it without a bunch of hacks.

How would you go about the syntax for such a thing? :P
>> function const TIntArray.Append(..);
>> function TIntArray[const].Append(..);
I assume the former as it most accurately follows the current syntax for declaring constant.. (Tho I find the later prettier =p)

Also, have you seen the lape-issues site lately?
http://code.google.com/p/la-pe/issues/list

We have added two new issues for you to solve. First one (33) is simple enough, second one (34) I have no idea how to fix, so I hope you can take a look at em! :smile:

Brandon

2014-09-20 12:32:34

From: slacky
How would you go about the syntax for such a thing? :P

>> function const TIntArray.Append(..);
>> function TIntArray[const].Append(..);
I assume the former as it most accurately follows the current syntax for declaring constant.. (Tho I find the later prettier =p)


That seems weird.. If it's const.. why would it be appended to? It can't change. But meh. Just a typo I guess.. What about adding it to the end instead?

Something like:


function TIntArray.indexOf(I: int): const int; const;

where the const modifier promises not to modify self or self's member. Basically const for result and const for function.

slacky

2014-09-21 01:45:19

From: Brandon
That seems weird.. If it's const.. why would it be appended to? It can't change. But meh. Just a typo I guess..

Haha! Yeah that's true, I did not think about what I called the function! :-P
From: Brandon

What about adding it to the end instead?

Something like:


function TIntArray.indexOf(I: int): const int; const;

where the const modifier promises not to modify self or self's member. Basically const for result and const for function.

I guess, adding it to the end is an option, and it might be the clearest way to go about it.

N1234

2014-11-17 15:48:15

very interesting, nicely done