Немного оптимизировал InlineCode. Теоретически должен работать в 3 раза быстрее Добавил точку минимальной погрешности (от 0 до 100; 0 - полное совпадение). Дает маленький прирост, но после 9 почти не чувствуется. Скорей всего, прирост будет зависеть от изображений (чем однородней, тем меньше). code_35055.txt
------------ Дoбавленo в 17.07:
Нашол свою же оплошность, исправил Add(Button,3183747,91,161) { Left=20 Top=20 Caption="Искать" link(onClick,8282293:doStart,[]) } Add(Bitmap,8059100,231,42) { @Hint=#8:Где ищем| AddHint(-21,-26,65,13,@Hint) } Add(DoData,9296008,231,98) { link(onEventData,10552383:doPicture,[]) link(Data,16257815:Var2,[]) } Add(Image,5758247,364,154) { @Hint=#8:Что ищем| Left=120 Top=120 Width=40 Height=40 WinStyle=2 AutoSize=0 ViewStyle=4 Picture=[ZIPD60B000078DA5556D9561BD915ED3CE707F296D77C413E20EFF984ACA0B9464D0833191BF00062B2DD606CA3A94AB30061A0B18D26C0066C26A9541A40129A80D8068CBB57C776A79D7656675FC96175B48EEEBA5575B5F7D9FB9E734B7FF9EBFEEFBF697CFE8CEF9FF0FDE3D7EFEFBEF943E3BEF0F5F96F3F5D91B39EE8596FE2BC2F717E237EDA1FFD47F762E54AB868F2E738FB8EEED12BEAD14BEDC426757F533DB1A199D8D4DEDFE41DA9367FB17DBA680E14F4DE1CEFDB37F80F78FF01E72F1883457DA0C078F39C37C77A65E0B3BEBC7EA6D4B670D4F5F44D5FECBC3FFEAE8F709D5D8BBCB9BA58EB9C2B9BBD19DE99A41E6D69263735131BDA890DD5B7EBDA8997CCC32DCE9134FB72AD817D4BB06404973FCFBBC155D0070EF43E72097C832FCB7BB3B43BC3F872FA60D1F2F8A873F9F43AA1787773F5A22F7A767DF975CFD2517BB80428CE99D23E780521BAC94DEDF8BAFADB17D4E44BCC597BCAE0CE80A8D55F40E8BDFBAC3B6FF01781CF8849DE2BEBFD32EF93594F1A5CAC27CB070AE670ADFDC99B6BB18BFEC4FBDEF8BB1B608CBCB9FEE4B863EED012C8F3424AF7704B737F93816390D3E08234FAD1B651485B02FBE6C081C97740F0853DDAB1ABB36FB3AE3DDE93D6FB32BC47E6BD19CA2D339E2CE3CF9967AB9D4BAFAFC5CE7B1317FDF1F3BED82951F45DB563A668816458F7F095F63E4C7BA1BEF75C73F7B976625D3BF98AB125F5AE86FFAE248271EE51B61D9D7D47EBD8E1843D564C716E9958E7966951A20499F1E50D33E5F6C5939EC8DBEBB1B31B702F7EDE1F7BDBB354EF9EAF9803FB4651A6A776E0957AFC054275178A9E137CB78CA0DD12617125693149DB7728C72EE5DA659CBB8C98E2BD300D0B644A4C53A2CCF90E8C33E52B8B27579F9DF6C641849238EB7DF6F6DAD249D77CC512DAE7450944F04AF3ED0B82EFC9D0BE2CE3931B44694A9018570AB03A2728F62047E36C7089295694184F1AEB41A41532284243A8D4367FD4FDF46D6FEC7D5FFCA22F7ED61F39ED5D3A69877581BCC9936EE40FABD394472644A0F066582489B990A25C49AD2BA971EEE91CBBB47357E720068214696083886A41D60A69AD887A285AE66A9D4B27D72367FDF18BFE18FAE8B4E7C909C11700986108788616D38C47E6480965C8E8CD420E6E52D844A8B0EF30F0CDB6ADB36D634E0BF03365C4CAA6C382AC13B3ACFFC014AE763E412B5DDC5879077CDA956505129C90635D589C65C182EDF0910C8928729941D132429A7649942B453B93B483541D3DB5053A6C136A8F1325D603168926C9EC3162C6102C019FF31EB0628E1173BC33C33A64C6217382AC872241E6D174A2CC886998C6340CC42514E95CB02ECD3853B43D097CCA411469A7B6B4A4C85328458C2C921124E09B67AA0853A86C4047BBF7F5428E7165696786B1A739478675C92C761CBD20A4C9E89675420A7218779616B14719DA2951F65D688163C4B4A92D9D8D88C21DAE816F9AAD9B666B96F091257C6C99A999A72B7A5F89F31639310F2E0EA29C32583807C634E112538C90E23CE042B191BA259E346DB1EF32533B8C6D87826FE4607C057C7DA8649C3E34872A084BB8DE3A5B6B0D1F99C275D374C5182C1BC1E53E0017EBCC32CE3444310E84C44197287162B3AA256C318286390E89B6A7903C5868DB16D95F62290E841CFC31E2180C964CA18A098ECD56DBE68E2C73C7A6E91A2E8D81B2317068F01659C295010BD185D1251158E822D2245E206229679AC64968DB053EEFC9EB9A25E1440765F5DEBCD15F44E8C1153A344C97506F1D4F8EBB96DF5C8B9C767C77027683AFA8F714788110913D020B44B950C612EB4C312E0891692782F4D7D5C5A3EE85FA95D992C9871295184284DD44B5E45AE70FADEBE753B98F62E5B378F8F3D4FE87F1E40FB737CE6EAD9E772CD48CA18AD1736870970C428173E4396716E5C73A329C931888407B92FE7AB8D3EACD764E977A166A3D0BF58E70D980B78F98A15C52CFD36357E18BAFFAD95FFB97AFFA93B7F22974FC2570F2ABEFE8D709E9A3395C37CFD4CDA1BAD15735FACA064F8915F639679E736439478E475B8919E0AB8657D5A36B8ABB6B9AC9970621DD162C5C5DA8753DAE763EAE5C992BF645EBF6FC474FF9274FF993EBE0477BF67BD7FE8F984CE53F752D9F1A67ABC6E9AA79B66E9939699D3E32FA2B066F85174A9CABC0D873B4839CCF9A9135F5F02A5814645C518DADA8C7D7F1E2B3F8F35D7395F6F9CACDC46B7BEE83A7F4C95DFAE8C87EFF487AEFC8FDF3DECEFB2B4B752E80B76D491F281B021543B0664484EAA6C684872237E95FCDE873E06B479F6BC75E6847D7B463ABAA11B0AC2AC656B5E31BF4D4EECDC8B1B7FC4BE8F8DF33AF11FF09D43FFB2B3F3F903FB42F5429B4187C70E7F5DE03DE5334F8CB467FD514AC9882554214AA031F98AAA115927933FFE1B86674453D92688E7F1F8A691F6CDCD93873173F07EABF90A87D110A9FEF6CFFD03A5BE03C59CA9ED2D9249A34050E961C4E00A3B760F01D1AFC95D6608DE43FB60A1CD5700CA37A7445F9FFF8AA9184F2EE9AC99DEE5DACF42E956FC58E7B9F55DA42797330DFF1B8D2335FEF0A972DF8E78093135507221BCE2519270C873F129E02F0096C232E012F25A886A3EAD184626405BC8AB10442756745311A6F198EC13DE5BD3506B5E7C13695BB1F1FB7876BAD81A241CCD17689B225695B8AB6490D7CE289C21A6DC2FE061C13A248359C203112472887E278048D78AA1E4E2886627FB3465A4612D4E4B649C874864A57672B5DE16A5BE8D0E8CEA1059AF8CAA1D8256C3360976634FE55144C231B14C3B246A5C5900CE64A6B4239140505E1B5AE28AC71E5485C33BECEBB5270AC3B8CF77EAD51FF71B27828D6CCB9C9D564C15C3314D72267FC7C30813220985632C1A5BA1158A01A8CAAAD312C530E465503D196DBCF5A00389AD04DBE6CE25F86F27FB93529909B9A80C7D4563C051DA012AAC1B87A68453D0470721F0B54580F0AB21823F11008C069B14609FE10711263730B94C0B7C62EE9B05E717B193F5758230467A08189188C2907224D6A05600917B983945A06238052347088FF7804F64640AC069E58570863D32B6BF4F2870DFC88726099C46004E9A9F0A801A51A882B07628A5BD1164C06E3CADB50146F1920F8FF05B9670808] Point(doTop) Point(doLeft) Point(onMouseDown) Point(Handle) link(onMouseDown,16176673:doMove,[]) AddHint(35,-30,66,13,@Hint) } Add(MoveWindow,16176673,413,161) { link(Handle,5758247:Handle,[(419,152)(405,152)(405,194)(377,194)]) } Add(MT_Part,9384028,294,168) { link(onSplit,5758247:doTop,[]) link(onPart,5758247:doLeft,[]) } Add(GetDataEx,16257815,231,84) { link(Data,8059100:Bitmap,[]) } Add(TimeCounter,8282293,154,161) { link(onStart,2366711:doFindBitmap,[]) link(onStop,6823186:doString,[(200,174)(200,223)]) } Add(Label,15385577,259,217) { Left=85 Top=20 Width=4 Height=4 Caption="" } Add(FormatStr,6823186,210,217) { DataCount=1 Mask="Время поиска - %1 Millisecond" link(onFString,15385577:doText,[]) } Add(Hub,12533344,259,161) { link(onEvent1,8282293:doStop,[(284,167)(284,202)(144,202)(144,174)]) link(onEvent2,9384028:doSplit,[]) } Add(MainForm,10552383,280,70) { Width=325 Height=230 WindowsState=2 Position=1 Point(onChar) Point(doPicture) link(onCreate,9296008:doData,[(319,90)(319,118)(221,118)(221,104)]) } Add(InlineCode,2366711,210,161) { WorkPoints=#12:doFindBitmap| EventPoints=#8:onResult|8:SumError| DataPoints=#6:Bitmap|9:subBitmap|8:minError| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|40: TByteArray = array [0..32767] of Byte;|27: PByteArray = ^TByteArray;|35: TBuf = array of array of integer;|15: FRes = record|19: found: boolean;|17: x,y: integer;|17: percent:real;|6: end;|14: WH2 = record|43: Width1,Height1,Width2,Height2: integer;|6: end;|2: |28: THiAsmClass = class(TDebug)|10: private|0:|9: public|12: Bitmap,|15: subBitmap,|45: onResult, SumError, minError: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|81: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|15: x,y: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|45: SetLength(buffer, Bmp.Height, Bmp.Width*3);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|38: for x:=0 to Bmp.Width*3-1 do begin|24: buffer[y,x]:=p[x];|8: end;|6: end;|19: Result := buffer;|4:end;|0:|88:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|3:var|36: y, x, yy, xx, err, color: integer;|32: sumerr, sum, pmError: LongInt;|5:begin|54: //максимальная ошибка = в диапазоне 0-726 на пиксель|54: pmError:=round(726*WH.Width2*WH.Height2*mError/100);|23: //sum:=High(LongInt);|17: sum:=pmError+1;|22: Result.found:=false;|20: Result.percent:=0;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|16: sumerr:=0;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|38: for color:=0 to 2 do begin|67: sumerr:=sumerr+abs(buf1[y+yy, x+xx] - buf2[yy,xx]);|24: inc(xx);|16: end;|53: if sumerr>sum then Result.found:=false; |52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|30: if sumerr<sum then begin|21: sum:=sumerr;|27: Result.x:=x div 3;|21: Result.y:=y;|60: Result.percent:= sumerr/(726*WH.Width2*WH.Height2);|10: end;|13: inc(x);|34: until (x>WH.Width1-WH.Width2);|11: inc(y);|34: until (y>WH.Height1-WH.Height2);|21: Result.found:=true;|4:end;|0:|35:procedure THiAsmClass.doFindBitmap;|3:var|24: Bmp, subbmp:PBitmap;|21: FindResult: FRes;|21: buf1, buf2: TBuf;|12: WH: WH2;|16: dt,di:TData;|89: mError : Integer; //Минимальная ошибка совпадения от 0 до 100 (0 - полное совпадение)|5:begin|36: Bmp := ReadBitmap(_Data,Bitmap);|42: if (Bmp = nil) or Bmp.Empty then exit;|42: subbmp := ReadBitmap(_Data,subBitmap);|48: if (subbmp = nil) or subbmp.Empty then exit;|73: if (Bmp.Width<subbmp.Width) or (Bmp.Height<subbmp.Height) then exit;|4: |43: mError := ReadInteger(_Data, minError);|4: |25: buf1 := LoagIMG(Bmp);|25: WH.Width1:=Bmp.Width;|27: WH.Height1:=Bmp.Height;|15: //Bmp.Free;|4: |28: buf2 := LoagIMG(subbmp);|28: WH.Width2:=subbmp.Width;|30: WH.Height2:=subbmp.Height;|22: //subbmp.Free; |4: |51: FindResult:=CompareIMG(buf1, buf2, WH, mError);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|57: dtInteger(dt,FindResult.x);//+(WH.width2 div 2));|58: dtInteger(di,FindResult.y);//+(WH.height2 div 2));|24: dt.ldata := @di;|34: _hi_onEvent(onResult, dt);|50: _hi_onEvent(SumError, FindResult.percent);|40: //_hi_onEvent(SumError, mError);|8: end;|4:end;|4:end.| link(onResult,12533344:doEvent1,[]) link(Bitmap,16257815:Var1,[(216,89)]) link(subBitmap,5758247:ImageBitmap,[(223,152)(335,152)(335,194)(370,194)]) link(minError,13965698:String,[(230,138)(349,138)]) } Add(ComboBox,13965698,336,63) { Left=20 Top=40 Height=21 Strings=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|3:100|0:| Text="0" DataType=1 ReadOnly=0 }
|