SRL Archive - OSR Help

Colors and distance


Flight

2011-11-17 02:41:15

This is a bit hard to explain but I'll give it my best shot. Let's say I wanted to find an object that has, atleast, 2 separate colors on it, and I was to find this object based on how close together those colors were? I imagine it has something to do with finding a TPA of both of those colors and merging them, but what about the distance?

Here's an example, more or less:

Getting the TPA of the brown, no problem. Same with the black. But as you can see those colors eventually change to the other there at the tree trunk. So… How would I find the distance, from the closest point of brown to the closest point of black? Would there be a way of telling if those two TPA's come within X amount of distance from one another? And if they're very close to each other, how would I get a point or TPA of where they become the closest?

If someone has an example of how this might be done that'd be wonderful, as I'm the kind of person who learns best from looking at given samples. Thanks in advance!

BraK

2011-11-17 04:02:31

function Distance(xs, ys, xe, ye:LongInt):LongInt

built into Simba under Math :)

KingKong

2011-11-17 04:36:54

I think this best suits what you're looking for(i havent tested it):
http://docs.villavu.com/simba/scriptref/tpa.html#getsamepointsatpa

first get the two diff colors/combine into atpa, then do GetSamePointsATPA

or do this:

FindTPAEges of one color TPA(get the boundary TPA of one color)
then do TPAinTPA(find the boundary TPA from before and check if its in the boudary of the second color)

Flight

2011-11-17 05:07:51

I appreciate the suggestions. Thanks BraK but I already knew how to find distance, and that's kinda close to what I was looking for, KingKong, but not so much finding over-lapping TPAs.

How about this…How would I find a box of, let's say, 20x20 containing those two colors within it? Also, if that box is found containing both colors, how would I find the bounds of it as long as every point within it?

BraK

2011-11-17 05:13:51

From: Flight
how would I find the bounds of it as long as every point within it?


GetTPABounds

I might be reading that wrong it has bad wording.

From: Flight
I appreciate the suggestions. Thanks BraK but I already knew how to find distance


I misread your first post/skimmed through it.

Combine the two TPAs then break it down into 20x20 boxes and search each box for the colors if you find the box with both colors then you have your box. if you want them to have a certain amount of each just use countcolor instead to get the amount in each and compare.

mormonman

2011-11-17 05:20:51

From: Flight
I appreciate the suggestions. Thanks BraK but I already knew how to find distance, and that's kinda close to what I was looking for, KingKong, but not so much finding over-lapping TPAs.

How about this…How would I find a box of, let's say, 20x20 containing those two colors within it? Also, if that box is found containing both colors, how would I find the bounds of it as long as every point within it?


Combine the two tpas and then use the distance function of your choice to change the tpa into an atpa. Sort through the new atpa by the amount of points you want using length(atpa). I suggest debugging your object from different camera angles and finding the range of lengths the tpas have. I use this method for finding roaches. It is VERY accurate.

function FindRoach(var P: TPoint): Boolean;
var
CTS, I, Len, C: Integer;
TPA, TPA2, Temp, BTPA: TPointArray;
ATPA, NATPA: Array of TPointArray;
B, Mid: TBox;
TP: TPoint;
begin
Result := False;
ClearScreen;
if not LoggedIn then Exit;
CTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.41, 0.83);//find wings
FindColorsSpiralTolerance(MSCX, MSCY, TPA, 2387585, MSX1, MSY1, MSX2, MSY2, 12);
SetColorspeed2Modifiers(0.06, 0.27);//find body
FindColorsSpiralTolerance(MSCX, MSCY, TPA2, 1650514, MSX1, MSY1, MSX2, MSY2, 6);
ColorToleranceSpeed(CTS);
SetColorSpeed2Modifiers(0.2, 0.2);
if (Length(TPA) < 1) or (Length(TPA2) < 1) then
begin
m_Debug('Roach - Found no colors', True);
Exit;
end;
BTPA := CombineTPA(TPA, TPA2);//add them together
ClearDoubleTPA(BTPA);
ATPA := SplitTPA(BTPA, 7);//split into different

SetLength(NATPA, Length(ATPA));
C := 0;
for i := 0 to High(ATPA) do
begin
Len := Length(ATPA[i]);
if (Len < 300) then Continue;
TP := MiddleTPA(ATPA[i]);
if FindDeath(TP) then Continue;
SortTPAFrom(ATPA[i], Point(MSCY, MSCY));
NATPA[C] := ATPA[i];
Inc(C);
if Debug then
begin
B := GetTPABounds(ATPA[i]);
SMART_DrawBoxEx(False, B, clWhite);
end;
end;
SetLength(NATPA, C);

SortATPAFromFirstPoint(ATPA, Point(MSCX, MSCY));
//if Debug then DrawDotsMulti(False, NATPA);
For i := High(NATPA) downto 0 do
begin
B := GetTPABounds(NATPA[i]);
TP := MiddleTPA(NATPA[i]);
if FindDeath(TP) then Continue;
MMouse(TP.x, TP.y, 12, 12);
If(WaitUpTextMulti(['ttack', 'ockroach', 'roach sol', 'soldier'], 550)) then
begin
Result := True;
GetMousePos(P.x, P.y);
if Debug then SMART_DrawBoxEx(False, B, clGreen);
m_Debug('Roach - ', False);
m_Debug(' Length: ' +ToStr(Length(NATPA[i])), False);
m_Debug(' Bounds: ' +ToStr(GetTPABounds(NATPA[i])), False);
Exit;
end else
begin
if Debug then Smart_DrawBoxEx(False, B, clRed);
m_Debug('Not Roach - ', False);
m_Debug(' Length: ' +ToStr(Length(NATPA[i])), False);
m_Debug(' Bounds: ' +ToStr(GetTPABounds(NATPA[i])), False);
end;
end;
end;

weequ

2011-11-17 05:32:25

mormonman I think he wants to make sure both colors exist. Comibing would not be solution to that.

Flight

2011-11-17 05:45:59

From: BraK

Combine the two TPAs then break it down into 20x20 boxes and search each box for the colors if you find the box with both colors then you have your box. if you want them to have a certain amount of each just use countcolor instead to get the amount in each and compare.


Now that sounds more like it! I've made a TPA for each color, combined them, and put that final TPA into a 2DPA (with a 20x20 bounds each). So with that being done I don't think checking those boxes for the existence of both colors will be necessary, because to make even one box it must find both colors.

I'll play around with it for a while, do some debugging and let ya know what I come up with. If it's successful then that opens up many doors for me. Thank you very much for the help, Brak. Have some Repz. :p

Edit:
I'll come back to it after I spread some rep around… :(

Edit2:
Nevermind I was wrong. I will have to check each box for the existence of both colors. Any idea how to go about that?

Narcle

2011-11-17 05:51:13

From: weequ
mormonman I think he wants to make sure both colors exist. Comibing would not be solution to that.


That's what the Length() check is for for both TPAs. If only one was found it would exit (its there in code). I use the same method to find the Furnace in Edgeville. You can also do a Length check as well with the combined TPA.

What I do is look for the rarer color first, turn it into a ATPA with set parameters then get the bounds of the best ATPA (or get bounds of all) and search around those area(s) particularly for the next color. Then do a length check (you could do a length check on both before hand etc). Hasn't failed me yet.

Flight

2011-11-17 05:57:07

How is this looking for a start? If I'm doing something wrong then by all means tell me what should be changed:


CTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, ColorA, MSX1, MSY1, MSX2, MSY2, Tol);
FindColorsSpiralTolerance(MSCX, MSCY, TPA2, ColorB, MSX1, MSY1, MSX2, MSY2, Tol);
ColorToleranceSpeed(CTS);
TPAF := CombineTPA(TPA, TPA2);
TPAA := TPAToATPAEx(TPAF, Bounds, Bounds);
SortATPASize(TPAA, True);
for I := 0 To High(TPAA) do
begin
for H := 0 To High(TPA) do
begin
for J := 0 To High(TPA2) do
begin
if (PointInTPA(TPA[H], TPAA[i]) and PointInTPA(TPA[J], TPAA[i])) then
Writeln('Success!');

Edit:
Here's a better version. Since I've already combined TPA and TPA2 into TPAF I can just check if a point from TPAF exists within the TPAA. If so, I go to the middle of that and presto, I have the box where the two colors meet within an amount of H/W bounds I define. Check it out: (Searching for the 'relations box' in which Color A/B exists within a 10x10 box)

To:


FindColorsSpiralTolerance(MSCX, MSCY, TPA, ColorA, MSX1, MSY1, MSX2, MSY2, Tol);
FindColorsSpiralTolerance(MSCX, MSCY, TPA2, ColorB, MSX1, MSY1, MSX2, MSY2, Tol);
ColorToleranceSpeed(CTS);
TPAF := CombineTPA(TPA, TPA2);
TPAA := TPAToATPAEx(TPAF, Bounds, Bounds);
SortATPASize(TPAA, True);
for I := 0 To High(TPAA) do
begin
for K := 0 To High(TPAF) do
begin
if PointInTPA(TPAF[K], TPAA[i]) then
begin
MiddleTPAEx(TPAA[i], X, Y);

Another question, what's the function for adding a Point to a TPA?

Wanted

2011-11-17 12:28:07

You're over complicating the situation.

Find the first color, split it into boxes or whatever. Then expand the boundaries of that box to do a 2nd search for the 2nd color in that new area.

Narcle

2011-11-17 13:43:10

Something like this. This gives you all the areas its found this way.

  FindColorsTolerance(TPA, ColorA, x1, y1, x2, y2, tol);
if Length(TPA) < 1 then
Exit;
ATPA := TPAtoATPAEx(TPA, W, H);
L := High(ATPA);
SetArrayLength(ATPA2, L+1);
for i := 0 to L do
begin
B := GetTPABounds(ATPA[i]);
with B do
FindColorsTolerance(ATPA2[i], ColorB, x1-10, y1-10, x2+10, y2+10, tol);//<- customize the boundaries
end;

Flight

2011-11-17 19:55:57

From: Narcle
Something like this. This gives you all the areas its found this way.

  FindColorsTolerance(TPA, ColorA, x1, y1, x2, y2, tol);
if Length(TPA) < 1 then
Exit;
ATPA := TPAtoATPAEx(TPA, W, H);
L := High(ATPA);
SetArrayLength(ATPA2, L+1);
for i := 0 to L do
begin
B := GetTPABounds(ATPA[i]);
with B do
FindColorsTolerance(ATPA2[i], ColorB, x1-10, y1-10, x2+10, y2+10, tol);//<- customize the boundaries
end;


Ah ha, that makes sense. This is pretty much what you were suggesting Wanted, yes? Thank you Narcle, I've a couple theories to try out today and this will definitely be on the list.