SRL Archive - SRL Suggestions

New PixelShift, which works perfectly even with high lag


m34tcode

2012-04-07 14:26:37

Wrote a new verison of poxel shift. This one will, over a duration of time, watch for all the pixels that never changed.

When finished, it counts the pixels that did change color, beyond a specified tolerance.

While it is similar to the standard PixelShift, It is far more effective through lag. Tested and it works perfectly now.

Also, as the function rules out pixels, it will get faster. So in a real application, and without DEBUG defined, it runs in less than a third of a second per iteration, on my old and slow pc. Newer computers should be even better.

Code:

{$DEFINE DEBUG}
{$DEFINE SMART}
{$i srl/srl.simba}
{$i srl/srl/misc/paintsmart.simba}

function GetColArr (Box : TBox) : T2DIntegerArray;
var
x,y : Integer;
begin
SetArrayLength(Result,box.X2-box.X1);
for x := 0 to box.X2-box.X1-1 do
begin
SetArrayLength(Result[x],box.Y2-box.Y1);
for y := 0 to box.Y2-box.Y1-1 do
begin
Result[x][y] := GetColor(x+box.X1,y+box.Y1);
end;
end;
end;

procedure ValidatePixels(Box : TBox; OrigCols : T2DIntegerArray; BoolArr : array of TBoolArray; Tolerance : Integer);
var
X,Y : Integer;
NewCols : T2DIntegerArray;
begin
NewCols := GetColArr(Box);
for X := 0 to Box.X2 - Box.X1-1 do
for Y := 0 to Box.Y2 - Box.Y1-1 do
begin
if not BoolArr[x][y] then
continue;
boolArr[x][y] := SimilarColors(origCols[x][y],NewCols[x][y],Tolerance);
end;
end;

function InitBoolArr(Width,Height : Integer) : array of TBoolArray;
var x,y : Integer;
begin
SetArrayLength(Result,Width);
for x := 0 to Width-1 do
begin
SetArrayLength(Result[x],Height);
for Y := 0 to Height-1 do
begin
Result[x][y] := True;
end;
end;
end;

function countBools(BoolArr : Array of TBoolArray; CountTrues : Boolean) : Integer;
var
X,Y,W,H,C : Integer;
begin
W := GetArrayLength(BoolArr);
H := GetArrayLength(BoolArr[0]);
For X := 0 to W-1 do
for Y := 0 to H-2 do
if BoolArr[X][Y] = CountTrues then
Inc(C);
Result := C;
end;

function CalcNonStaticPixelCount(Box : TBox; ShiftInterval, Repetitions, Tolerance : Integer) : Integer;
var
I,X,Y : Integer;
T,TT : LongInt;
OrigColArr : T2DIntegerArray;
BoolArr : array of TBoolArray;
begin
OrigColArr := GetColArr(Box);
BoolArr := initBoolArr(Box.X2-Box.X1,Box.Y2-Box.Y1);
MarkTime(T);
MarkTime(TT);
for I := 0 to Repetitions-1 do
begin
if (TimeFromMark(T) > (Repetitions*ShiftInterval)) then
begin
srl_Warn('CalcNonStaticPixelCount','Completed only ' + IntToStr(I) + ' of '
+ IntToStr(Repetitions) + '. Try increasing the interval',1);
break;
end;
{$IFDEF DEBUG}
if (I > 0) then
writeln('CalcNonStaticPixelCount: Iteration ' + IntToStr(I) + ' took '
+ FloatToStr(TimeFromMark(TT)/1000.0) + ' seconds to complete.');
{$ENDIF}
MarkTime(TT);
wait(Max(0,ShiftInterval-TimeFromMark(TT)));
validatePixels(Box,OrigColArr,BoolArr,Tolerance);
{$IFDEF DEBUG}
SMART_ClearCanvas;
for x := 0 to box.x2-box.x1-1 do
for y := 0 to box.y2-box.y1-1 do
if boolArr[x][y] then
SMART_DrawDot(false,Point(x+box.x1,box.y1+y),clRed);
{$ENDIF}
end;
Result := countBools(BoolArr,False);
end;

var
T : Longint;
Box : TBox;
begin
{$ifdef SMART}
Smart_Members := True;
Smart_Server := 100;
Smart_Signed := False;
Smart_SuperDetail := False;
{$endif}
SetupSRL;
SMART_ClearCanvas;
MarkTime(T);
box := IntToBox(236,97,271,175);
writeln('Found ' + IntToStr(CalcNonStaticPixelCount(box,100,90,10)) + ' nonstatic pixels.');
writeln('Executed in ' + FloatToStr(TimeFromMark(T)/1000.0));
end.

nickrules

2012-04-07 15:10:23

Neat. Pretty accurate too. Going to test this out in my autofighter to see how it holds up, because the current pixelshift isn't working too hot for me.

m34tcode

2012-04-08 02:03:57

I submitted a pull request for this as a new include. It works amazingly

Coh3n

2012-04-08 22:21:42

Why did you make another thread? You already have one for this exact thing.

m34tcode

2012-04-08 22:28:41

It was the previous one, that was inefficient and died. I felt I had it in the wrong forum, so I took advantage of that and moved it here.

Coh3n

2012-04-08 22:29:59

This is where you posted the other one. I moved it to snippets. In the future, just asked for it to be moved again.

Thanks for sending a pull request, that should help us.

m34tcode

2012-04-08 22:33:12

Oh ok failed then >.> lol. Thanks =]

And ill just ask next time. That works =]

Coh3n

2012-04-08 22:38:15

Doesn't this just return the pixels that never changed? So the completely opposite of PixelShift? If that's the case, you can just do:

function StaticPixels(b: TBox; time: integer): integer;
var
tpaBox: TPointArray;
shift: integer;
begin
tpaBox := TPAFromBox(b);
shift := pixelShift(b, time);
result := abs(length(tpaBox) - shift); // returns the number of pixels that didn't shift
end;
I'm not trying to be negative, just trying to understand it correctly.

m34tcode

2012-04-08 22:41:03

It does the same thing, but it keeps a record for those static pixels through multiple iterations

Pixel shift returns a number, and not the actual pixels that staid the same. So basically, I have the validate pixels function, which goes through the array of pixels that have remained static. When it finds a pixel that has changed, it sets that pixels value accordingly. It is very similar to pixel shift, but that small difference has a great impact.

Hard to explain

If you run the script, with debug painting defined,you will see as it eliminates pixels. Should hopefully make more sense =]

Coh3n

2012-04-08 22:43:01

From: m34tcode
It does the same thing, but it keeps a record for those static pixels through multiple iterations

Pixel shift returns a number, and not the actual pixels that staid the same. So basically, I have the validate pixels function, which goes through the array of pixels that have remained static. When it finds a pixel that has changed, it sets that pixels value accordingly. It is very similar to pixel shift, but that small difference has a great impact.

Hard to explain

If you run the script, with debug painting defined,you will see as it eliminates pixels. Should hopefully make more sense =]
Ah, yes I understand it now. Not exactly what I had in mind. :p

I can see how it would be useful. I'll take a closer look at your code when I can. Just out of curiosity, how are you using this in your script?

m34tcode

2012-04-08 22:49:30

I havent written another script that uses pixelshift yet, but while i was testing, it worked amazingly. very accurate.

Iv been contemplating whether expanding on this, to create 'Animation Masks' would be usefull. It would be even more accurate, but they would need to be dynamically created.

By masks, i mean the 'image' that is painted on smart should be unique to each animation. If you are chopping a tree, vs mining a rock.

It would need to be dynamic because if you are wearing different clothes, or using a different kind of tool than who made the mask, it will mess it up.

Rezozo

2012-04-08 22:53:11

From: m34tcode
I havent written another script that uses pixelshift yet, but while i was testing, it worked amazingly. very accurate.

Iv been contemplating whether expanding on this, to create 'Animation Masks' would be usefull. It would be even more accurate, but they would need to be dynamically created.

By masks, i mean the 'image' that is painted on smart should be unique to each animation. If you are chopping a tree, vs mining a rock.

It would need to be dynamic because if you are wearing different clothes, or using a different kind of tool than who made the mask, it will mess it up.


I like the Idea, like to see it in action :)

Coh3n

2012-04-08 23:05:40

From: m34tcode
I havent written another script that uses pixelshift yet, but while i was testing, it worked amazingly. very accurate.

Iv been contemplating whether expanding on this, to create 'Animation Masks' would be usefull. It would be even more accurate, but they would need to be dynamically created.

By masks, i mean the 'image' that is painted on smart should be unique to each animation. If you are chopping a tree, vs mining a rock.

It would need to be dynamic because if you are wearing different clothes, or using a different kind of tool than who made the mask, it will mess it up.
Could have a tolerance variable.

m34tcode

2012-04-08 23:13:48

With a mask it would be needed, since you would probably never get the exact same mask, due to slight differences in camera angle

Gu3st...

2012-04-09 19:34:23

This is lovely, m34tcode!
I love these kind of stuff. The animation-idea is neat, too!

+rep for good work :)

Bam Bam

2012-04-09 22:44:53

Awesomely cool. I like what you've done here and that you've done it :D rep+

-Bam Bam

m34tcode

2012-04-09 23:45:02

;] I had time where others didnt. Im happy =]

Jakkle

2012-04-16 00:25:09

Great work, I will be trying this out in my scripts :)

m34tcode

2012-04-16 00:26:28

Pkease. Id like to get it pulled into srl. No progress for a few days though. Think cohen is busy

Coh3n

2012-04-16 17:21:58

From: m34tcode
Pkease. Id like to get it pulled into srl. No progress for a few days though. Think cohen is busy
Yeah, sorry. Very busy, and I'm going to be gone for a week or two, unfortunately. My buddy and I are driving home (British Columbia to New York), so I'll be MIA for a while.

I have a whole list of suggestions to add to SRL when I get home, though. :)

masterBB

2012-04-16 17:54:19

Wait, I want to improve it. Ten minutes ;).

edit:
Ten minutes was a bit optimistic. Will be fast.

masterBB

2012-04-16 18:18:15

I haven't tested it yet, but I hope it works. Do no have access to internet with a ping above the 500 so I will not try to start runescape ;)

What I did:
  1. Replaced all 2D arrays with 1D arrays
  2. Used getColors instead of GetColor to reduce the 'new buffer' calls
  3. Boolean array now starts all negative, if a pixel changes it will become positive
  4. reversed some for loops
  5. Removed some debug, could be added again.

function GetColArr (Box : TBox) : TIntegerArray;
begin
Result := GetColors(TPAFromBox(Box));
end;

procedure ValidatePixels(Box : TBox; OrigCols : TIntegerArray; BoolArr : TBoolArray; Tolerance : Integer);
var
i : Integer;
newColors : TIntegerArray;
begin
newColors := GetColArr(Box);
for i := High(NewColors) to 0 do
begin
if BoolArr[i] then
continue;
boolArr[i] := not(SimilarColors(origCols[i],newColors[i],Tolerance));
end;
end;

function countBools(BoolArr :TBoolArray; CountTrues : Boolean) : Integer;
var
i:Integer;
begin
for i := High(BoolArr) downto 0 do
if BoolArr[i] = CountTrues then
Inc(Result);
end;

function CalcNonStaticPixelCount(Box : TBox; ShiftInterval, Repetitions, Tolerance : Integer) : Integer;
var
I,X,Y : Integer;
T,TT : LongInt;
OrigColArr : TIntegerArray;
BoolArr : TBoolArray;
begin
OrigColArr := GetColArr(Box);
SetLength(BoolArr,High(OrigColArr));
MarkTime(T);
MarkTime(TT);
for I := 0 to Repetitions-1 do
begin
if (TimeFromMark(T) > (Repetitions*ShiftInterval)) then
begin
srl_Warn('CalcNonStaticPixelCount','Completed only ' + IntToStr(I) + ' of '
+ IntToStr(Repetitions) + '. Try increasing the interval',1);
break;
end;
{$IFDEF DEBUG}
if (I > 0) then
writeln('CalcNonStaticPixelCount: Iteration ' + IntToStr(I) + ' took '
+ FloatToStr(TimeFromMark(TT)/1000.0) + ' seconds to complete.');
{$ENDIF}
MarkTime(TT);
wait(Max(0,ShiftInterval-TimeFromMark(TT)));
validatePixels(Box,OrigColArr,BoolArr,Tolerance);
end;
Result := countBools(BoolArr,False);
end;

m34tcode

2012-04-16 21:38:40

Ah, I like the changes. Ill modify the functions in the repo tomorrow, wicked tired right now.

Thanks