From b2f5a9f77a43ce2a89fe6913a59e42e5df24387d Mon Sep 17 00:00:00 2001 From: Wizzup? Date: Mon, 4 Jan 2010 19:08:06 +0000 Subject: [PATCH] Added DTM NOT points, made DTM algorithm more dynamic. Added CTS support for DTM. (May remove later if it becomes slow) git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@371 3f818213-9676-44b0-a9b4-5e4c4e03d09d --- Projects/MufasaTests/project1.lpi | 342 ++++++++++++----------------- Projects/MufasaTests/project1.lpr | 138 +++++------- Units/MMLAddon/PSInc/pscompile.inc | 4 +- Units/MMLCore/dtm.pas | 18 -- Units/MMLCore/dtmutil.pas | 19 +- Units/MMLCore/finder.pas | 37 +++- Units/MMLCore/mufasatypes.pas | 2 + Units/MMLCore/window.pas | 1 + 8 files changed, 244 insertions(+), 317 deletions(-) diff --git a/Projects/MufasaTests/project1.lpi b/Projects/MufasaTests/project1.lpi index 5bbabb7..76bf1ae 100644 --- a/Projects/MufasaTests/project1.lpi +++ b/Projects/MufasaTests/project1.lpi @@ -11,7 +11,7 @@ - + @@ -30,15 +30,15 @@ - + - - + + - + @@ -46,15 +46,15 @@ - + - - - - + + + + @@ -62,370 +62,318 @@ - + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - - - - - + + + - - - + + + - - + + - + - + - + - + - + - - + + - - - - + + + + - - - - + + + + - - - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - + + diff --git a/Projects/MufasaTests/project1.lpr b/Projects/MufasaTests/project1.lpr index eecdf9c..27aba64 100644 --- a/Projects/MufasaTests/project1.lpr +++ b/Projects/MufasaTests/project1.lpr @@ -10,8 +10,7 @@ uses Forms,Interfaces, LCLIntf, Client, - bitmaps,{x ,}mufasatypes,dtm,dtmutil, ocrutil ,graphics ,colour_conv,math, - updater + bitmaps,x ,mufasatypes,dtm,dtmutil, ocrutil { you can add units after this }; @@ -47,51 +46,24 @@ begin result.t[i] := random(255); result.asz [i] := random(5); result.ash[i] := 0; - writeln(format('dtm: (%d, %d) c: %d, t: %d, asz: %d', [result.p[i].x, - result.p[i].y, result.c[i], result.t[i], result.asz[i]])); + {writeln(format('dtm: (%d, %d) c: %d, t: %d, asz: %d', [result.p[i].x, + result.p[i].y, result.c[i], result.t[i], result.asz[i]])); } + result.gp[i] := false;// random(10) = 1; end; result.c[0] := 255; -end; - -var - aTime: dword; - -function myChange: boolean; -begin - if gettickcount-atime > 1000 then - result := true - else - result := false; + PrintpDTM(result); end; procedure MufasaTests.DoRun; - -{const - ocr_Limit_High = 191; - ocr_Limit_Low = 65; - - ocr_White = 16777215; - ocr_Green = 65280; - ocr_Red = 255; - ocr_Yellow = 65535; - ocr_Blue = 16776960; - ocr_ItemC = 16744447; - - ocr_Purple = 8388736; } - var ErrorMsg: String; -{ Time: DWord; + Time: DWord; C: TClient; - I, w, h,x,y: Integer; + I: Integer; dtm: pdtm; p:tpointarray; - bmp, bmprs: TMufasaBitmap; - tbmp: TBitmap; - r,g,b:integer; - t:Dword; } - up: TMMLFileDownloader; + bmp: TMufasaBitmap; begin // quick check parameters @@ -109,59 +81,57 @@ begin Exit; end; - atime:=gettickcount; - - up := TMMLFileDownloader.Create; - up.FileURL:='http://www.villavu.com/pics/desktop.png'; - up.ReplacementFile:='test.png'; - up.OnBeat:=@myChange; - try - up.DownloadAndSave; - up.Replace; - finally - writeln(inttostr(gettickcount-atime)); - up.Free; - end; - - - - - { clOlive = false point } - { clSilver = false shadow } - { clLime = false shadow} - { add your program here } + C := TClient.Create; -{ tbmp:=TBitmap.Create; - tbmp.LoadFromFile('/home/merlijn/Programs/mufasa/pics/16.bmp'); - - bmprs := TMufasaBitmap.Create; - bmprs.SetSize(10,10); - - bmprs.LoadFromRawImage(tbmp.RawImage); - tbmp.Free; - tbmp := bmprs.ToTBitmap; - } - { for y := 0 to tbmp.Height -1 do - for x := 0 to tbmp.width -1 do - begin - writeln(format('(%d, %d) = %d , %d', [x,y,tbmp.Canvas.pixels[x,y],bmprs.FastGetPixel(x,y)])); - colortorgb(tbmp.Canvas.pixels[x,y],r,g,b); - writeln(format('%d,%d,%d', [r,g,b])); - colortorgb(bmprs.FastGetPixel(x,y),r,g,b); - writeln(format('%d,%d,%d', [r,g,b])); - end; } - //bmprs.LoadFromFile('/home/merlijn/Programs/mufasa/pics/16.bmp'); - {C := TClient.Create; - C.MWindow.SetTarget(bmprs); } + bmp := TMufasaBitmap.Create; + bmp.SetSize(CW,CH); + Writeln(Format('Client W/H: %d, %d', [CW, CH])); + FillChar(bmp.FData[0],sizeof(trgb32)*CW*CH, 0); + Randomize; + for i := 0 to 500 do + bmp.fastsetpixel(random(CW), random(CH), 255); + { bmp.FastSetPixel(8,8,255); + bmp.FastSetPixel(9,9,255); + bmp.FastSetPixel(7,7,255); + bmp.FastSetPixel(9,8,255); + bmp.FastSetPixel(8,9,255); } + C.MWindow.SetTarget(bmp); - { bmp.SaveToFile('/tmp/output.bmp'); - tbmp.SaveToFile('/tmp/output2.bmp'); - //bmp.OnDestroy:=nil; + { initdtm(dtm, 5); + dtm.p[0] := Point(2, 2); + dtm.p[1] := Point(-3, -3); + dtm.p[2] := Point(0, 0); + dtm.p[3] := Point(1, 1); + dtm.p[4] := Point(3, 3); + dtm.c[0] := 255; + dtm.t[0] := 0; + dtm.asz[1] := 1; + dtm.ash[1] := dtm_Rectangle; } + + dtm := randomdtm(10); + + // setlength(p, 1); + C.MFinder.SetToleranceSpeed(1); + + time := GetTickCount; + for i := 0 to 100 do + begin + setlength(p,0); + C.MFinder.FindDTMs(dtm, p, 0, 0,CW-1, CH-1, 0); + end; + writeln(inttostr(gettickcount - time) + 'ms'); + writeln(inttostr(length(p))+ ' points found'); + setlength(p,0); + + {for i := 0 to high(p) do + writeln(format('%d: (%d, %d)', [i, p[i].x, p[i].y])); } + + + //bmp.OnDestroy:=nil; bmp.Free; - tbmp.Free; } - // C.Free; + C.Free; // stop program loop Terminate; diff --git a/Units/MMLAddon/PSInc/pscompile.inc b/Units/MMLAddon/PSInc/pscompile.inc index 0b5516d..f8effb7 100644 --- a/Units/MMLAddon/PSInc/pscompile.inc +++ b/Units/MMLAddon/PSInc/pscompile.inc @@ -32,10 +32,10 @@ Sender.Comp.AddTypeS('TBmpMirrorStyle','(MirrorWidth,MirrorHeight,MirrorLine)'); Sender.Comp.AddTypeS('TMask','record White, Black : TPointArray; WhiteHi,BlackHi : integer; W,H : integer;end;'); -Sender.Comp.AddTypes('TDTMPointDef', 'record x, y, Color, Tolerance, AreaSize, AreaShape: integer; end;'); +Sender.Comp.AddTypes('TDTMPointDef', 'record x, y, Color, Tolerance, AreaSize, AreaShape: integer; Good: Boolean; end;'); Sender.Comp.AddTypes('TDTMPointDefArray', 'Array Of TDTMPointDef;'); Sender.Comp.AddTypes('TDTM','record MainPoint: TDTMPointDef; SubPoints: TDTMPointDefArray; end;'); -Sender.Comp.AddTypeS('pDTM','record l: Integer;p: TPointArray;c, t, asz, ash: TIntegerArray;n: String; end;'); +Sender.Comp.AddTypeS('pDTM','record l: Integer;p: TPointArray;c, t, asz, ash: TIntegerArray; gp: array of boolean; n: String; end;'); Sender.Comp.AddTypeS('T2DExtendedArray', 'array of array of extended;'); Sender.Comp.AddTypeS('TStringArray','Array of string;'); diff --git a/Units/MMLCore/dtm.pas b/Units/MMLCore/dtm.pas index 25744f7..ceb5be8 100644 --- a/Units/MMLCore/dtm.pas +++ b/Units/MMLCore/dtm.pas @@ -78,24 +78,6 @@ type FreeSpots: Array Of Integer; end; -{ - I am not sure wether I should simply copy and paste the old DTM implementation, - or rewrite it from scratch. - - The old DTM system problaby doesn't perform that well, but seems to be quite - stable and complete. - - If I would rewrite it from scratch, it would probably be faster, and - hopefully more efficient.That won't be too hard, especially since I have - direct data access now. (TClient FTW!) - - Rewrite from scratch it will be, I guess. - And AreaShape will be turned into a {$I }, inline simply doesn't cut it. - - ~Wizz -} - - implementation uses Client, dtmutil, paszlib, diff --git a/Units/MMLCore/dtmutil.pas b/Units/MMLCore/dtmutil.pas index 966d77b..71d4bc5 100644 --- a/Units/MMLCore/dtmutil.pas +++ b/Units/MMLCore/dtmutil.pas @@ -64,6 +64,8 @@ begin setlength(d.t, len); setlength(d.ash, len); setlength(d.asz, len); + setlength(d.gp, len); + FillChar(d.p[0], SizeOf(TPoint) * len, 0); FillChar(d.c[0], SizeOf(Integer) * len, 0); FillChar(d.t[0], SizeOf(Integer) * len, 0); @@ -71,8 +73,10 @@ begin // Better set it to 1, than fill with 0. FillChar(d.asz[0], SizeOf(Integer) * len, 0); - {for i := 0 to len - 1 do - d.asz[i] := 1; } + + //FillChar(d.gp[0], SizeOf(Boolean) * len, 0); + for i := 0 to len - 1 do + d.gp[i] := true; end; Procedure PrintpDTM(tDTM : pDTM); @@ -82,9 +86,9 @@ begin; i := 0; if tdtm.n <> '' then writeln('Name: ' + tdtm.n); - WriteLn('MainPoint ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i])); + WriteLn('MainPoint ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i])+ ', Good: ' + BoolToStr(tdtm.gp[i])); for I := 1 to High(tDTM.p) do - WriteLn('SubPoint['+IntToStr(I) + '] ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i])); + WriteLn('SubPoint['+IntToStr(I) + '] ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i]) + ', Good: ' + BoolToStr(tdtm.gp[i])); end; Function pDTMToTDTM(Const DTM: pDTM): TDTM; @@ -102,6 +106,7 @@ Begin Temp.AreaShape := DTM.ash[i]; Temp.Color := DTM.c[i]; Temp.Tolerance := DTM.t[i]; + Temp.Good:= DTM.gp[i]; End; Result.MainPoint := Temp; SetLength(Result.SubPoints, Length(DTM.p) - 1); @@ -115,6 +120,7 @@ Begin Temp.AreaShape := DTM.ash[i]; Temp.Color := DTM.c[i]; Temp.Tolerance := DTM.t[i]; + Temp.Good:= DTM.gp[i]; Result.SubPoints[I - 1] := Temp; End; End; @@ -135,6 +141,7 @@ Begin SetLength(Result.t, Length(DTM.SubPoints) + 1); SetLength(Result.asz, Length(DTM.SubPoints) + 1); SetLength(Result.ash, Length(DTM.SubPoints) + 1); + SetLength(Result.gp, Length(DTM.SubPoints) + 1); Result.p[0].x := DTM.MainPoint.x; Result.p[0].y := DTM.MainPoint.y; @@ -142,6 +149,7 @@ Begin Result.t[0] := DTM.MainPoint.Tolerance; Result.asz[0] := DTM.MainPoint.AreaSize; Result.ash[0] := DTM.MainPoint.AreaShape; + Result.gp[0] := DTM.MainPoint.Good; For I := 1 To Length(DTM.SubPoints) Do // High + 1 = Length Begin @@ -151,6 +159,7 @@ Begin Result.t[I] := DTM.SubPoints[I - 1].Tolerance; Result.asz[I] := DTM.SubPoints[I - 1].AreaSize; Result.ash[I] := DTM.SubPoints[I - 1].AreaShape; + Result.gp[I] := DTM.SubPoints[I - 1].Good; End; Result.l := length(Result.p); End; @@ -172,6 +181,8 @@ begin Exit(False); if dtm.l <> length(dtm.ash) then Exit(False); + if dtm.l <> length(dtm.gp) then + Exit(False); for i := 0 to dtm.l-1 do if dtm.asz[i] < 0 then Exit(False); diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index d505930..f0f033b 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -1841,15 +1841,15 @@ begin // Init data structure B. W := x2 - x1; H := y2 - y1; - setlength(b, W + 1); + setlength(b, (W + 1) * 2); for i := 0 to W do begin - setlength(b[i], H + 1); + setlength(b[i], (H + 1) * 2); // does setlength init already? if it doesn't, do we want to init here? // or do we want to init in the loop, as we loop over every b anyway? // init - FillChar(b[i][0], SizeOf(Integer) * H, 0); + FillChar(b[i][0], SizeOf(Integer) * H * 2, 0); end; // C = DTM.C @@ -1869,25 +1869,38 @@ begin for yy := MA.y1 to MA.y2 do for xx := MA.x1 to MA.x2 do begin - // main point - if Sqrt(sqr(rgbs[0].r - cd[yy][xx].R) + sqr(rgbs[0].g - cd[yy][xx].G) + sqr(rgbs[0].b - cd[yy][xx].B)) > dtm.t[0] then - // if not SimilarColors(dtm.c[0], RGBToColor(cd[yy][xx].R, cd[yy][xx].G, cd[yy][xx].B), dtm.t[0]) then - goto AnotherLoopEnd; + // Checking main point now; store that we have checked it. + // (Main point is point 1) b[xx][yy] := B[xx][yy] or 1; + + // if Sqrt(sqr(rgbs[0].r - cd[yy][xx].R) + sqr(rgbs[0].g - cd[yy][xx].G) + sqr(rgbs[0].b - cd[yy][xx].B)) > dtm.t[0] then + if not SimilarColors(dtm.c[0], RGBToColor(cd[yy][xx].R, cd[yy][xx].G, cd[yy][xx].B), dtm.t[0]) then + goto AnotherLoopEnd; + + // Mainpoint match. (If it did not match, we would be at AnotherLoopEnd) + b[xx][yy+1] := B[xx][yy+1] or 1; + + for i := 1 to dtm.l - 1 do begin //change to use other areashapes too. for xxx := xx - dtm.asz[i] + dtm.p[i].x to xx + dtm.asz[i] + dtm.p[i].x do for yyy := yy - dtm.asz[i] + dtm.p[i].y to yy + dtm.asz[i]+ dtm.p[i].y do begin - // may want to remove this line, but I think it is a good optimisation. - if B[xxx][yyy] and (1 shl i) = 0 then + // If we have matched this point + if b[xxx][yyy+1] and (1 shl i) = 0 then begin - if Sqrt(sqr(rgbs[i].r - cd[yyy][xxx].R) + sqr(rgbs[i].g - cd[yyy][xxx].G) + sqr(rgbs[i].b - cd[yyy][xxx].B)) <= dtm.t[i] then - // if SimilarColors(dtm.c[i], RGBToColor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), dtm.t[i]) then - b[xxx][yyy] := B[xxx][yyy] or (1 shl i) + // Checking point i now. (Store that we matched it) + b[xxx][yyy]:=b[xxx][yyy] or (1 shl i); + + // if Sqrt(sqr(rgbs[i].r - cd[yyy][xxx].R) + sqr(rgbs[i].g - cd[yyy][xxx].G) + sqr(rgbs[i].b - cd[yyy][xxx].B)) <= dtm.t[i] then + if SimilarColors(dtm.c[i], RGBToColor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), dtm.t[i]) then + b[xxx][yyy+1] := B[xxx][yyy+1] or (1 shl i) else goto AnotherLoopEnd; end; + + if (b[xxx][yyy+1] and (1 shl i) = 0) and dtm.gp[i] then + goto AnotherLoopEnd; end; end; //writeln(Format('Found point: (%d, %d)', [xx,yy])); diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index 40713c3..92323cf 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -98,6 +98,7 @@ type l: Integer; p: TPointArray; c, t, asz, ash: TIntegerArray; + gp: TBoolArray; n: String; // DOEN end; @@ -105,6 +106,7 @@ type TDTMPointDef = record x, y, Color, Tolerance, AreaSize, AreaShape: integer; + Good: Boolean; end; TDTMPointDefArray = Array Of TDTMPointDef; diff --git a/Units/MMLCore/window.pas b/Units/MMLCore/window.pas index 5a71218..b642811 100644 --- a/Units/MMLCore/window.pas +++ b/Units/MMLCore/window.pas @@ -572,6 +572,7 @@ begin H := Attrib.Height; end else begin + { TODO: Raise Exception because the Window does not exist? } W := -1; H := -1; end;