Вверх ↑
Этот топик читают: Гость
Ответов: 8
Рейтинг: 0
#1: 2020-07-07 20:37:49 ЛС | профиль | цитата
Здраствуйте, хочу у Вас спросить насколько возможно или как сделать распознавание фигур с картинки? Например, разных цветов, пустые внутри и залиты цветом. (Треугольники, овалы, ромбы, звезды). Если рядом с треугольником будет звезда и ромб, может он это как-то интерпретировать?
Картинка
Спасибо!
С Уважением.
Ваби-Саби
карма: 0
0
Ответов: 2267
Рейтинг: 676
#2: 2020-07-07 21:06:05 ЛС | профиль | цитата
Wabi-Sabi писал(а):
распознавание фигур с картинки
Уточните про картинку. Она уже нарисованная с фигурами или вы будете их добавлять (рисовать)?
карма: 11

0
Ответов: 16884
Рейтинг: 1239
#3: 2020-07-07 21:07:56 ЛС | профиль | цитата
Wabi-Sabi, почитай: Хорн Б.К. "Зрение роботов."
карма: 25
Немного терпения! Дежурный экстрасенс скоро свяжется с Вами!
0
Ответов: 2059
Рейтинг: 132
#4: 2020-07-07 21:53:29 ЛС | профиль | цитата
Tad, Думаю, что дело в другом.
Такое впечатление, что это не его картинка!
Если это не так, то вопрос звучал-бы по другому.
Человек владеющий всем циклом функций в одном кадре задал-бы вопрос иначе.
Wabi-Sabi, 100-500 ответов на твой вопрос (смотреть не только "Программирование игр" https://gamedev.ru/forum/ и вот https://www.redblobgames.com/ .
Разбивай общую задачу на подзадачи и говори суть - где не клеится, или ты хочешь чтобы за тебя концепцию решили?
Иначе, по простому, на картинке можно искать по шаблону:
По части картинки.
Add(MainForm,10552383,231,84)
{
Width=435
Height=214
Position=1
Point(onChar)
link(onCreate,12795964:doEvent1,[])
}
Add(Button,3884042,259,210)
{
Left=170
Top=5
link(onClick,8282293:doStart,[])
}
Add(Image,5758247,532,140)
{
Left=120
Top=120
Width=40
Height=40
AutoSize=0
ViewStyle=4
Point(doTop)
Point(doLeft)
Point(onMouseDown)
Point(Handle)
link(onMouseDown,16176673:doMove,[(578,153)(578,237)(529,237)(529,202)])
}
Add(InlineCode,2366711,378,210)
{
WorkPoints=#12:doFindBitmap|
EventPoints=#8:onResult|8:SumError|
DataPoints=#6:Bitmap|9:subBitmap|
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,|35: onResult, SumError: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|65: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|17: x,y,c: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|43: SetLength(buffer, Bmp.Height, Bmp.Width);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|36: for x:=0 to Bmp.Width-1 do begin|52: c:=((p[x*3+0] shl 8+p[x*3+1]) shl 8)+p[x*3+2];|21: buffer[y,x]:=c;|8: end;|6: end;|19: Result := buffer;|4:end;|0:|72:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|3:var|29: y, x, yy, xx, err: integer;|23: sumerr, sum: LongInt;|5:begin|58: //maxerr:=200; //максимальная ошибка = в диапазоне 0-726|21: sum:=High(LongInt);|22: Result.found:=false;|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|55: //Result.found:=buf1[y+yy, x+xx]=buf2[yy,xx];|71: err:=abs(byte(buf1[y+yy, x+xx]) - (buf2[yy,xx] and $0000ff))+|91: abs((buf1[y+yy, x+xx] and $00ff00 shr 8) - (buf2[yy,xx] and $00ff00 shr 8))+|93: abs((buf1[y+yy, x+xx] and $ff0000 shr 16) - (buf2[yy,xx] and $ff0000 shr 16));|51: //if err>maxerr then Result.found:=false;|29: sumerr:=sumerr+err;|49: if sumerr>sum then Result.found:=false;|18: inc(xx);|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;|21: Result.x:=x;|21: Result.y:=y;|59: 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;|30: //if Result.found then begin|20: //Result.x:=x-1;|20: //Result.y:=y-1;|8: //end;|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;|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: |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: |43: FindResult:=CompareIMG(buf1, buf2, WH);|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);|8: end;|4:end;|4:end.|
link(onResult,13902867:doEvent1,[])
link(SumError,4467059:doCalc,[(424,223)(424,258)])
link(Bitmap,3103349:ImageBitmap,[])
link(subBitmap,5758247:ImageBitmap,[(391,180)(538,180)])
}
Add(MT_Part,15868768,490,154)
{
link(onSplit,5758247:doTop,[])
link(onPart,5758247:doLeft,[])
}
Add(MoveWindow,16176673,539,196)
{
link(Handle,5758247:Handle,[])
}
Add(Label,7469250,616,252)
{
Left=230
Top=10
Width=115
}
Add(FormatStr,8296708,574,252)
{
DataCount=1
Mask="Минимальная ошибка - %1 %"
link(onFString,7469250:doText,[])
}
Add(Hub,13902867,434,210)
{
link(onEvent1,8282293:doStop,[(466,216)(466,265)(319,265)(319,223)])
link(onEvent2,15868768:doSplit,[(459,223)(459,160)])
}
Add(TimeCounter,8282293,329,210)
{
link(onStart,2366711:doFindBitmap,[])
link(onStop,6823186:doString,[(368,223)(368,286)])
}
Add(Label,15385577,434,280)
{
Left=230
Top=35
}
Add(FormatStr,6823186,385,280)
{
DataCount=1
Mask="Время поиска - %1 Millisecond"
link(onFString,15385577:doText,[])
}
Add(MathParse,4467059,525,252)
{
DataCount=1
MathStr="round(%1*100,0.01)"
link(onResult,8296708:doString,[])
}
Add(Hub,12795964,280,98)
{
link(onEvent1,9570550:doBitmap,[])
link(onEvent2,9881532:doBitmap,[(312,111)(312,160)])
}
Add(Image,3103349,378,84)
{
Width=160
Height=155
AutoSize=0
ViewStyle=4
}
Add(Jpeg,9570550,329,84)
{
Jpeg=[ZIP690E000078DA9DD16558D38DD707F0DF60309808821BD2E18811D270A31202C26E24878C492825C824478980204A4B88843A900E41E99006699472E42825A56F06A326F1D7FFF5C49BE7C5F33CDFF3F29CEB5CE7739DB389B31FC0855B3ABA3A000804026C7E177036056801F4603A7A3A303D3D1D3D0442CF00BD008532324261CC2C4C172EC138382EC1D8D9B97885F9B9B8113CECEC0292020811513171314EFE2B32579032C24831E49F252008040265805E84422F22B9D8B990FFE79CB502AC0C801FE0470BBA0CD0B082685941671D003F0080E840FF0EF01F01D1D0FEBE17C2C0083DF77BA0FA024003A2A5A501D3D2D181C1BFBB4F7EF701302B1D9BA0AC06FD45B42DE4321E26179290C580D02CFF0C37F9B62D246FE7F98C11CA7E8983934B5844142926AEA0A8F497F2D56B5A37B575507FEBDEBA6D8A31C3DE31B7B0BFEFE0F8C009F7D0CBDBC7F791DF63FFE7A161E1119151D1AF129392535EBF794BC8CEC9CDCB2F785F58545159555DF3A9B6AEBEADBDA3B3ABBBA7F70B717864746C7C82343937BFB0B8B4FC7365758DBCB34BD9DB3F383CA2FE7181005AD07FE67F74B1FE76D180C1B460C81F1788E6D19F0156309DA02C3D9B061A628BBF78592E8401A6999055FE9911216FB20DB7F3FC06651752981326FFA1FD5BF6BF833DFB7FC9FE0BF6DFAE49808916F4FB79B4AC803AF05C617A5757D73A5B4722999F45EC7A7907D1588CB1E0FE255B4AFEA726A927B8826235CC8454DB9B6ED8D71791C539728673171E290ECEF8D577D1736227FCE56538A9CCD5BD915D73655BA34289D7566C25C6B1CF8656747F3629504A82BE77FA267E01E32B7574B410F4CA7B53A73C638BB7BB559C850C79B96BAF1E8BD9EE322909EF0C279330DB98ED7542F6103EDF31898053C1BA8B6FE077653986753BC5148689719889C0BE58EAB7BF47B07C6252F77D8CFDE51D5F52F2E613D7EFA20FD19D5726AAF870C8417FA8261F9DA4EEB29232E0A9BB81FC11BF6AD512AB6856A6E7ECFDB27BF9A2500CCB76DCF758FC02599A4513C37EC2DCC8CE8B2DE6508D6E967D79D4057731F8E4A1D5A3BD61544729613EED2C9EEEF5EDCC0DF24DF949562796E2083195B3D3F7FAFA258B0FB0BC542475BCE1507EAEEB1DEF476C7D9FB5CBC8226826EDDDFBE0FA9C21ECF21E9939AD2E7F8B745025733AA6145D810AC1F90765FFF84A97D6A6C81D6283EF2E8057E63ABB3EF0AA5F0DD57BF791E12A623AD882AAF6CBA0DAD2374683239EA3D50A744F9BCCDDEEDBE2F06A0E96C5B3ED2CA9A6862ECAAD721CDDD9DB20B8AD10883BB33B32FBC32824425D6C31082E817DEBA773DBA13872D27D46FD0B269EBE499E87C95382F2B1928BEC5D9757AF462BD3F651510FE5A84070E6C2AF1BB825AFF22063EBD11AABDAF8F966211F6352AAEAEAB5E54491E79FA963647F440A7AF405413F4163F95549C753C5A51636B773EBC4F7031399986323F5B12634FD9D0705FE3B2CDC328956230E2A2102A6D626F4909DD2F4C10FC2BAB7B7061F89644FCFE8A8CF1D9072C637084789BD4FDF4E5F0FA58BD048ECB6A0226E906B3202CF800761223A2A34AD70515252C23DC6ED44BDB2D1BDBAE23D0C1B42BB55B4D97F7CA866923E35C77C99246774D080FD794892F2ADCFF009096D2238DBB544071AD7DB1DE19C0E2EDA94A35BD16B1E8CC7618F4F4E9BF823B3029C7688217543961574D61F78324A2486F3C327174C9C4A16C07F47EBA0ACA0CB8D6E9341613933AA1FC5D836253B512265B9449CE5EDEC5C4B038A9A276E7610FB9DBF0F113C085F27384CDE9B6857F19B5C4F97E8FE273F6EFFE740556827370F9DA8E8FABD173F32C916BAE77E3AB54B2F8C35FF23508C1CF158198C1C10D3315E6EEEBEE93F6C207141DE4094A6B9F12849B19E4B8C63DBA944C5A823AE9E5BDE5A21027CDB8B8ACEB8B5F2C20C2551FF08A684AA5D37C2487AFA01A637F91B73327E1AEA484D5328948F457AC9AA0685ED6F8B691E8F8183FF5A6AFB67D04EA2BBF1E6ACEB0631F831A945F65EC48233A57A5808A7B67B3EB26E91B02B9231807114DAB2BA98EEA94E1DDDF63BD62BBDDB3083D894A1C0B9C4952A1D3240D6E7E53B953611B0D8A9AF5756D3238EA9E344F74299613DC5C6D7E884F09D091A7539F55B47B68238B7211D8F3E9DF34F04E70EB77E0C0BA44FC935B70A874C7DB07F55F069386BBF34A3CFC4C444B5B1C228B97323CABEA57352B53AB4FF7A6CD672C32CEC891C7EAFE4DC82D2C797ABDFED76FFB21AD0DC843CBD4ED8ACB686AB369EE7B1B0D4BE7A06A4475ECAB0F6DFFECEF124FFA799F38BA6A91ED1658E7E1D563153038A52F7C801D7B3F2B087608F38AF88D57B0559D9E7FC1663D238920D51056780B5E25251D6656BABE58678C6B57564DC251BCEDACF2A6EFC0B2712EB1569A648CC013543F48DED92C5BB9CA175235185614381B82603851389CD05A1D1ADC0B4ECE1EA70D9E3955C1BA7122BBD515E187BCC1816CB093675BD2630C0F9BA94A668D65C0F56C4D29FA1D5737CFDB4DAC407CAFC6BE7A957F9764BFAE31389B83B9D70FB8A7496D47BE1512D61E1B703F86F84BF19CF83D9C9092786F138D6A56EA2ED7E0E9AD1FEAAEBA5329D0161569F6A65563D1FBEB696DC50430F4C8C1F075347774925CEA2FC0E90BAAD2592B7A0344EB8FC4BA066F32FEDF91B1CAC2C9CA7E42DE7B7319BB18672DC3501D4E1BD80F8AA1995686662C041C987CFCD6CAFADAAE356BF9EF3AE8D63B207127B7B379FAA5B902FEE7B34C69D3C1C19FA4CCCF41DD9C4D8FB4AB6D24175111358E2290FD2255BE0A5D25C08D8CB2A23B40A1D30BF5AAD01158E8D09BE5F35E9C91B316BBB7115BE8AB48F824ADAD078111B635CB53139A436F4BE6E92DB4B5D6E57955F3EA54C8711F9562299C3B9263DA19B92B0B24572CF0F6C53A8A96B7B9EC968F1FC88C0AB73617D6EB5CAEB1B41D5B1D0F42F565D7B85017F4F1C395C9ECE0AF891D0EFE4A4C6DF3282684834745A22CCE8F7BB262EBBF29AA3B4A2D78EEDE704F38FDC99CDE6D2E235948CE8505E1321837377D963E7F68955A9AA6632DFBE9B5BE9ECB8BAF0E6D5949D78A05AAAFDBFC208666B8FD9DAAAF656BCF838C89C8D5338EF2F5210DA9A7F06A9585D411B3F0C7FAC4730DC7BA5AA94D3BA9810B980638ACEC91C3456E77ADDE63FD3517E8415EA67B39734BC0BD9835348660F7A9D06EDDBFA64D4C6EF14A3279582A3920240DA2850B44D6014A8DB588EE104591A54ED67D82FDF1EC6D8B69A933B2279BC08AAEBD64F0B428D9529220DEA834E977DD0DF78EE67E48320DB25BD09FE7CA83C9B7582A49CA5917063655BA757051C223A61AF9E005FC634E6780DE548999BA7638B66840E720D1002E7AB31D4F8407FA233B5AC29CA2E6ADAA283A68832FDC469A44AECA3A89897CBBABCAC47075B6DB7FE816288B24D4954CA29CFAF83EE756B798BF3033BAA2BA60792D18B97B8CBE3DD5AB1C4EF5085EB012DE1D4C0C4F6B4E9861A23C855606135FAA8872E6E1C07C1DB1E61C75A18BFE51DE29C52AF6A72A2CA686AC96EE4259421BBD26BD902DE5CDF954236F1CB31400E00B54F1EEC131F21513EAE56BEF2BAC75DB7A9BD728735273E2533853722B3135BD3B8B3F58DFB69373CC7F791D2A5CCEC395FFB59D2D474896894106DFED280DADB1277CB70858A44C317825211C9D586869E0C27DA3E5E5D138A51E793AB6BAA1FF81A57A290EEEF48E5832EE91216EE966F4D47EF9007E38A04C9A38BE05D0E8DF822B1D3FCDA6096B52BF96B787DFAC5014EAF11BEEAD9A0216865A0C9480762AB9335917F76A7CBB9FF4ACACD5A13781498B5F389081F592FE9686D60737AAF47710A0C4854A10A756164CA19B08EC634AAE66B0717685DEBEA89537DEB35ED6A73E318C86E9AC2E0AEA7BBE4195CBF43392DF8346790AE0193EC33A5E314DA16ABEBA2F5DE83C3DE87854079E2341079DEC89A2AE561DD9934A348C1864669A16DB9B7033D981EE3C8ABD301A5A5EAC4DA6284A6732CC6CEA6AE875F9F7222E73CE6EE3DDE5CC7AD875002B9D5F225EB196C37A48E91B8BE9094E5D860F89884E3BB46BCEBCBF2B8FA8B956B4F943006D8B05F7C96F882DCC435C3374EC55A2EB6DF9A5D68A9E36367C03901BD607ADC1CF392D36EF7D28944A774A0828B62A45D2467566D0AC2F3BEBEF4F9E17406153EE50538852FAA46C26F3ED64C79C4168305053DF52E5534DD4F71DA2834227D6049D57574944D12F7BF7F06EC7D50DAD5737A99A2092945DFBD25439BC7D4FA4C4ED6FC56CC7DD65264BAC1BC9012BE6A215E7A799058CF2BAC36EE127F3247A85C90666A2E2FF8CA1B5A082E91D18A4F88084269E96FA7BC7E6FD16AD3A4C1847F57B41422A55A16FCCEEBD673936B0B7795ADF0C3B9E9060952F891F4671FA6578CA72AFAE51B63227C47DB9EC739971B8923F73301682B194E511AABE89500E0BA6A872593A6A68F948BC6936AD4EE1F3E07B590F74BBD04A72B2AB65C3C0063F53797E3999DD83F5D4BD55FFD1556C37ADC7E1877755F35B8B7A466B65F3A3CEBF1658799A899EFAF0CC567C2EA3F3B73DDA429910F59739EEDE52A35D3A5A834CE4AC522A70A35BB0DC367CC6115BA69356DA67F35432C248CDFCFEC06D94553AF25DCEAD91614D9736C0D4BF0048E2B1EEAC3ADC2C01916C812646F953B3236D6EA4B28403F4798AC0C958CC1C719DD429612E6F9FD8DEB28E6B4F89853ED2B38B4D02701A6A39028AAD7DDAED4BA056C5884E1BB5818364393606ADA489A894AF5E17A12EBB4F83A47E7FBD34235DFB5E243B236BC38CE326A4976AD3328694C13D4DE32EF89CCCEEF8ACC7ADFAB825E549A9B60D92E953E7CEE8357CC7C2A2F7540EBEEB5498C16275471DCAE7C1F31B19AE1F8AD031CB8E8165C9AE77023CC160849E85ED286CFB413F1C50A0D3CA435C3186B47B91BF87E18DA1A63E6B672F45EE3CE19E95F4E6AF589]
Point(doBitmap)
link(onBitmap,3103349:doLoad,[])
}
Add(Jpeg,9881532,343,140)
{
Jpeg=[ZIP5F03000078DAFB7FE3FF0306012F374F370646464686042064F87F9BC199818D85958D95858D8D958D9D9D8D834B808B8B93934B848F9F47405C4442425C444C4C4A56555E4A5A59464C4C414741594D5D534B53525ED74057C340554353036408233B3B3B170797301797B08694989406C9E0FF0106410E06790659664625062641466641C6FF47807C0646564630608002462666A07BD93938B9B8810AB60A303031323333B130B3B2B2B000656B81F20C2C82AC428A868E6CC28189EC4A8522468D131772283B6D3C281A74F1838A71525113279798B884A494AA9ABA86A69689A999B985A595B38BAB9BBB87A7577048685878446454724A6A5A7A4666567149695979456555734B6B5B7B4767D7A4C953A64E9B3E63E6AC458B972C5DB67CC5CA559B366FD9BA6DFB8E9DBB0E1D3E72F4D8F113274F5DBA7CE5EAB5EB376EDE7AF8E8F193A7CF9EBF78F9EAE3A7CF5FBE7EFBFEE3E72F90BF181998196100ABBF0481FE62626161666107F98B91A91CA440908555D1904DC831903DB15058C9A89143C469E2C28D0739958D833E8826155DE412533179A8FA11E435B0CF88F35813593E837B0CE1AF5B0C3CCC8CC0C8631664B067F830BBBAD6EDD4FDB76AD7421CCAFE1C787EFDD2EE78B68A6DD26111FAE91E5777324F62FC37DFEBCBDBBC439C8A3755BC6AF90CE30C1FAFE5E2B6BCE6D1AD985FC5F0AD3A7AC7BB8777B917AFFF3EE1B9A9BAD767F996EB6792A75DCBDCFED632E0F8C4B8390F9E3558FE6710AE38A9BB34E3D19634D7DCB5D6DA46CD2F441DD53F2AEDA817BEE7BAF665709CD3D1451DC995DDA77F6E7E39B97F69D5D2B5735B9F18A95EE17A66E4C85235EB819D469658546A53F4DFF9DF59B7755CEEF967C278E0077BB855DEB636079BE5D67ED5697BFF498685F05855879F95CAE1D55BD4E876B57882F185AAF0FD157191F2AEDBF5FC3E98CD3FBC94A1FEFF4D00C79F3DA5]
Point(doBitmap)
link(onBitmap,5758247:doLoad,[])
}
По части картинки на картинке.
Add(Button,3183747,266,231)
{
Left=20
Top=20
Caption="Искать"
link(onClick,8282293:doStart,[])
}
Add(Bitmap,8059100,406,112)
{
@Hint=#8:Где ищем|
AddHint(-21,-26,65,13,@Hint)
}
Add(DoData,9296008,406,168)
{
link(onEventData,10552383:doPicture,[])
link(Data,16257815:Var2,[])
}
Add(Image,5758247,539,224)
{
@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,588,231)
{
link(Handle,5758247:Handle,[(594,222)(580,222)(580,264)(552,264)])
}
Add(MT_Part,9384028,469,238)
{
link(onSplit,5758247:doTop,[])
link(onPart,5758247:doLeft,[])
}
Add(GetDataEx,16257815,406,154)
{
link(Data,8059100:Bitmap,[])
}
Add(TimeCounter,8282293,329,231)
{
link(onStart,2366711:doFindBitmap,[])
link(onStop,6823186:doString,[(375,244)(375,293)])
}
Add(Label,15385577,434,287)
{
Left=85
Top=20
Width=4
Height=4
Caption=""
}
Add(FormatStr,6823186,385,287)
{
DataCount=1
Mask="Время поиска - %1 Millisecond"
link(onFString,15385577:doText,[])
}
Add(Hub,12533344,434,231)
{
link(onEvent1,8282293:doStop,[(459,237)(459,272)(319,272)(319,244)])
link(onEvent2,9384028:doSplit,[])
}
Add(MainForm,10552383,455,140)
{
Width=325
Height=230
WindowsState=2
Position=1
Point(onChar)
Point(doPicture)
link(onCreate,9296008:doData,[(494,160)(494,188)(396,188)(396,174)])
}
Add(InlineCode,2366711,385,231)
{
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,[(391,159)])
link(subBitmap,5758247:ImageBitmap,[(398,222)(510,222)(510,264)(545,264)])
link(minError,13965698:String,[(405,208)(524,208)])
}
Add(ComboBox,13965698,511,133)
{
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
}
Но если ты хочешь искать по определённым признакам, то ты должен их сформулировать - в чём и заключается работа всех программистов! - это искусство! И не важно, что это: похожее лицо в потоке, фраза музыки, или литературный плагиат.

--- Добавлено в 2020-07-07 21:57:25

Продолжение, а то не умещается...
Поиск на экране раз.
Add(Button,3183747,266,231)
{
Left=20
Top=20
Caption="Искать"
link(onClick,8282293:doStart,[])
}
Add(Bitmap,8059100,406,112)
{
@Hint=#8:Где ищем|
AddHint(-21,-26,65,13,@Hint)
}
Add(DoData,9296008,406,168)
{
link(onEventData,10552383:doPicture,[])
link(Data,16257815:Var2,[])
}
Add(Image,5758247,539,224)
{
@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,588,231)
{
link(Handle,5758247:Handle,[(594,222)(580,222)(580,264)(552,264)])
}
Add(MT_Part,9384028,469,238)
{
link(onSplit,5758247:doTop,[])
link(onPart,5758247:doLeft,[])
}
Add(GetDataEx,16257815,406,154)
{
link(Data,8059100:Bitmap,[])
}
Add(TimeCounter,8282293,329,231)
{
link(onStart,2366711:doFindBitmap,[])
link(onStop,6823186:doString,[(375,244)(375,293)])
}
Add(Label,15385577,434,287)
{
Left=85
Top=20
Width=4
Height=4
Caption=""
}
Add(FormatStr,6823186,385,287)
{
DataCount=1
Mask="Время поиска - %1 Millisecond"
link(onFString,15385577:doText,[])
}
Add(Hub,12533344,434,231)
{
link(onEvent1,8282293:doStop,[(459,237)(459,272)(319,272)(319,244)])
link(onEvent2,9384028:doSplit,[])
}
Add(MainForm,10552383,455,140)
{
Width=325
Height=230
WindowsState=2
Position=1
Point(onChar)
Point(doPicture)
link(onCreate,9296008:doData,[(494,160)(494,188)(396,188)(396,174)])
}
Add(InlineCode,2366711,385,231)
{
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,[(391,159)])
link(subBitmap,5758247:ImageBitmap,[(398,222)(510,222)(510,264)(545,264)])
link(minError,13965698:String,[(405,208)(524,208)])
}
Add(ComboBox,13965698,511,133)
{
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
}
Поиск на экране два.
Add(MainForm,16152671,259,175)
{
Width=167
Height=115
}
Add(Button,3183747,259,77)
{
Left=15
Top=10
Caption="Find"
link(onClick,8272130:doEvent1,[])
}
Add(Bitmap,15450061,441,77)
{
@Hint=#45:Сюда вставляется кусочек, который надо найти!|
}
Add(InlineCode,15546554,434,126)
{
WorkPoints=#12:doFindBitmap|
EventPoints=#8:onResult|3:dbg|
DataPoints=#6:Bitmap|9:subBitmap|
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;|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,|30: onResult, dbg: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|65: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|17: x,y,c: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|43: SetLength(buffer, Bmp.Height, Bmp.Width);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|36: for x:=0 to Bmp.Width-1 do begin|52: c:=((p[x*3+0] shl 8+p[x*3+1]) shl 8)+p[x*3+2];|21: buffer[y,x]:=c;|8: end;|6: end;|19: Result := buffer;|4:end;|0:|72:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|3:var|37: y, x, yy, xx, err, maxerr: integer;|5:begin|56: maxerr:=200; //максимальная ошибка = в диапазоне 0-726|22: Result.found:=false;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|55: //Result.found:=buf1[y+yy, x+xx]=buf2[yy,xx];|71: err:=abs(byte(buf1[y+yy, x+xx]) - (buf2[yy,xx] and $0000ff))+|91: abs((buf1[y+yy, x+xx] and $00ff00 shr 8) - (buf2[yy,xx] and $00ff00 shr 8))+|93: abs((buf1[y+yy, x+xx] and $ff0000 shr 16) - (buf2[yy,xx] and $ff0000 shr 16));|49: if err>maxerr then Result.found:=false;|18: inc(xx);|52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|13: inc(x);|52: until (x>WH.Width1-WH.Width2) or (Result.found);|11: inc(y);|52: until (y>WH.Height1-WH.Height2) or (Result.found);|28: if Result.found then begin|18: Result.x:=x-1;|18: Result.y:=y-1;|6: end;|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;|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: |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: |43: FindResult:=CompareIMG(buf1, buf2, WH);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|53: dtInteger(dt,FindResult.x+(WH.width2 div 2));|54: dtInteger(di,FindResult.y+(WH.height2 div 2));|24: dt.ldata := @di;|35: _hi_onEvent(onResult, dt); |8: end;|4:end;|4:end.|
link(onResult,1981070:doEvent1,[])
link(Bitmap,5200148:Bitmap,[(440,117)(391,117)])
link(subBitmap,15450061:Bitmap,[])
}
Add(TimeCounter,9308098,336,126)
{
link(onStart,15546554:doFindBitmap,[])
link(onStop,3796541:doStrCat,[(403,139)(403,188)])
}
Add(Label,16719776,616,182)
{
Left=80
Top=10
Width=32
Height=17
Caption=" "
}
Add(Hub,1981070,483,126)
{
link(onEvent1,9308098:doStop,[(508,132)(508,174)(326,174)(326,139)])
link(onEvent2,1569587:doSeparateMT,[])
}
Add(ScreenShort,4677498,336,77)
{
link(onCapture,5200148:doLoad,[])
}
Add(Bitmap,5200148,385,77)
{
}
Add(Hub,8272130,301,77)
{
link(onEvent1,4677498:doCapture,[])
link(onEvent2,9308098:doStart,[(326,90)(326,132)])
}
Add(Label,2751625,616,259)
{
Left=10
Top=35
}
Add(MouseEvent,14350900,560,210)
{
}
Add(Timer,10241311,511,259)
{
Interval=100
link(onTimer,2407579:doString,[])
}
Add(FormatStr,2407579,560,259)
{
Mask="Х = %1 | Y = %2"
link(onFString,2751625:doText,[])
link(Str1,14350900:MouseX,[])
link(Str2,14350900:MouseY,[])
}
Add(MT_MultiData,1569587,525,133)
{
link(onData1,9203703:doValue,[(564,139)(564,83)])
link(onData2,4171558:doString,[])
}
Add(FormatStr,4171558,574,140)
{
Mask="X=%1 Y=%2"
link(onFString,15336817:doText,[])
link(Str1,9203703:Value,[])
}
Add(Memory,9203703,574,77)
{
}
Add(Label,15336817,616,140)
{
Left=10
Top=55
}
Add(StrCat,3796541,441,182)
{
Str2=" мсек"
link(onStrCat,16719776:doText,[])
}


sla8a, не ты ли это рисовал?

Редактировалось 4 раз(а), последний 2020-07-07 22:28:10
карма: 6

0
Ответов: 8
Рейтинг: 0
#5: 2020-07-07 22:28:21 ЛС | профиль | цитата
sla8a писал(а):
Уточните про картинку. Она уже нарисованная с фигурами или вы будете их добавлять (рисовать)?

Это картинка как пример. Во время работы программы фигуры могут быть разных размеров, цветов и поворот(360, 180 градусов). Если можно сделать такую программу, насколько сложно будет возможность добавлять поиск новых фигур?

flint2, спасибо, но поиск картинки на экране не справляется с задачей.
карма: 0
0
Ответов: 8926
Рейтинг: 823
#6: 2020-07-07 22:43:18 ЛС | профиль | цитата
flint2, ну не мне вам напоминать -- одно дело искать по полному совпадению кусочка с зарание известным направлением и параметрами, другое -- даже тот же кусочек , но повёрнутый, и совсем другое искать ПОХОЖУЮ фигуру в любом положении. Для настольного компьютера задача на миллион лет последовательного перебора всех вариантов.
карма: 19

0
Ответов: 2267
Рейтинг: 676
#7: 2020-07-07 22:43:34 ЛС | профиль | цитата
Wabi-Sabi писал(а):
Это картинка как пример.
Вы не ответили на вопрос.
flint2 писал(а):
не ты ли это рисовал?
Если вопрос о схемах, то не "мой туфля".
Леонид писал(а):
Для настольного компьютера задача на миллион лет последовательного перебора всех вариантов.
Во во. Я вот думаю что решение понадобится проще (могу ошибиться), но ТС молчит как партизан что за картинки.

Редактировалось 1 раз(а), последний 2020-07-07 22:45:46
карма: 11

0
Ответов: 2059
Рейтинг: 132
#8: 2020-07-07 22:44:42 ЛС | профиль | цитата
Wabi-Sabi писал(а):
flint2, спасибо, но поиск картинки на экране не справляется с задачей.

Понятное дело!
Я же говорил
(смотреть не только "Программирование игр")

https://gamedev.ru/code/forum/?ai
Вся печаль в том, что это не твоя картинка! Зная координаты дерева объектов(когда объекты свои) можно и не такие вещи определять, а даже со скелетной анимацией. Но...
Придётся делать простейшую нейронную сеть - это классика, учебный случай. Но на звёздочку, на квадратик, треугольник и на овал надо натаскивать её и + масштабирование(тоже учится).
sla8a
Если вопрос о схемах, то не "мой туфля".

Наверное я совсем из ума выжил - ничего не помню!
Я уже года два рисую линии с округлыми углами. Значит давно было. ))

--- Добавлено в 2020-07-07 22:59:48
Леонид писал(а):
одно дело искать по полному совпадению

Я это и пытался донести, а примеры как гротеск.
Леонид писал(а):
но повёрнутый, и совсем другое искать ПОХОЖУЮ фигуру в любом положении

Понятное дело!
Повёрнутая(простейшая фигура) по пикселям искажается + если H\W (разрешение) экрана не учитывать - совсем беда. Для этого и соответствующие функции в графических движках существуют.
По этому только ИИ, и не обязательно сетка!
Эта задача на Прологе решается в 30 строк максимум - сама суть. (опускаем аппаратное сканирование точек через GL, или DX)

Редактировалось 9 раз(а), последний 2020-07-07 23:26:37
карма: 6

0
Ответов: 8
Рейтинг: 0
#9: 2020-07-08 00:54:27 ЛС | профиль | цитата
sla8a, картинка - это скриншот.
flint2, нейронную сеть читал, пытался на hiasmе сделать. В итоге я не понял как сделать, чтобы все работало. Я видел Ваш компонент Пролог, мне интересно насколько возможно в нём подобные задачи решать. Если в нём эту задачу решить, то насколько сложно можно адаптировать подобные задачи?
карма: 0
0
Ответов: 2059
Рейтинг: 132
#10: 2020-07-08 03:30:16 ЛС | профиль | цитата
Wabi-Sabi писал(а):
пытался на hiasmе сделать.

Ты крут!!!
Вот простейшая и более-менее внятная для большинства задач http://leenissen.dk/fann/wp/ сеть.
Тут как минимум два компонента со множеством и множеством точек надо делать - один для обучения, другой для исполнения, лучше + запись\чтение ещё.
Я когда-то делал порт под KOL (без Wrapper_а и всяких dll) - попробую найти.
Правда я делал fannfloat вариант, но для графики, думаю, то что доктор прописал.
(сейчас поздно, никак не найду).
Wabi-Sabi писал(а):
Я видел Ваш компонент Пролог, мне интересно насколько возможно в нём подобные задачи решать. Если в нём эту задачу решить, то насколько сложно можно адаптировать подобные задачи?


Разумеется, что такие языки лучше справляются с таким типом задач (ИИ) нежели процедурные языки.
Но!
1. Тебе надо научится писать на нём.
Геометрические объекты можно представить следующими прологовскими термами:
P1 = точка( 1, 1)
P2 = точка( 2, 3)
S = отрезок( P1, P2) =
 отрезок( точка( 1, 1), точка( 2, 3) )
T = треугольник( точка( 4, 2), точка( 6, 4),
 точка( 7, 1) )
И никаких кубиков - только скрипты.
В моей реализации русский не понимает, как в примере, вернее понимает, но с экранировкой - не буду голову морочить.
2. Тебе надо сканировать экран(это отдельная задача) и передавать значения переменных в терм(проверил, работает передача).
Это всё большими штрихами. На самом деле, при всей кажущейся простоте пролога, въезжать будешь долго. Это не с delphi на C++ перейти!
Не заморачивайся!

В общем задача не простая.
Думаю и на кубиках задача тоже изящно не будет решена и всё будет архимедленно.
Я бы взял SDL.dll - https://ru.wikipedia.org/wiki/Simple_DirectMedia_Layer и сделал на ней графическую часть.
Очень маленькая и простая библиотека - примеров просто море на всех языках и на все случаи жизни.
Может быть мужики чего нибудь подскажут. У меня мыслей нет.

Вот о чём я хотел сказать https://yadi.sk/d/eDJGufmiULGKkA , когда писал:
если H\W (разрешение) экрана не учитывать - совсем беда.

P.S.
Я не могу понять что тебе надо?
Если распознавание образов - это одно, а если какое-то взаимодействие фигур на картинке - это другое.
Не знаю как Newton, физический движок, со звёздочками и сложными фигурами будет работать ли, то chipmunk точно со сложными фигурами будет работать.

Редактировалось 3 раз(а), последний 2020-07-08 04:08:28
карма: 6

0
Ответов: 16884
Рейтинг: 1239
#11: 2020-07-08 11:00:01 ЛС | профиль | цитата
flint2

Ожил?
карма: 25
Немного терпения! Дежурный экстрасенс скоро свяжется с Вами!
0
Ответов: 2059
Рейтинг: 132
#12: 2020-07-08 11:31:17 ЛС | профиль | цитата
Tad

Tad, спасибо!
Почти, но иногда температура накатывает.
Врач говорит, что восстанавливаться буду месяца два.
карма: 6

0
Ответов: 8
Рейтинг: 0
#13: 2020-07-08 12:44:51 ЛС | профиль | цитата
flint2, мне нужно распознание образов. Если в прологе можно прописать все необходимые фигуры, то можно ли перебирая экран, сделать перебор размеров этих фигур. Если программа не нашла фигуру, то она переберала все возможные размеры. Если от какой-нибудь точки описать несколько отрезков и они в каких-нибудь местах покажут одинаковый цвет, может это как-нибудь помочь в поиске фигур?
карма: 0
0
Ответов: 8926
Рейтинг: 823
#14: 2020-07-08 13:22:09 ЛС | профиль | цитата
Wabi-Sabi писал(а):
..Если программа не нашла фигуру, то она перебирала все возможные размеры..

А сколько времени вы отводите на эту операцию? Если час-другой, то вполне возможно
карма: 19

0
Ответов: 2059
Рейтинг: 132
#15: 2020-07-08 14:49:28 ЛС | профиль | цитата
Wabi-Sabi, правильно я тебя понимаю, что эти фигуры расставляет не твоя программа?
Это приходит какая-то картинка, допустим, из интернета и с ней надо разбираться?
Если это не секретная информация, то подробное описание - что это и какова конечная цель сильно помогло-бы делу. А то каждое слово приходится клещами вытаскивать.
1. Думаю, что решать задачу на прологе не совсем рационально.
Чтобы определить принадлежность точки фигуре понадобятся тригонометрические вычисления в каждой итерации. Конечно цвет монотонной заливки упрощает задачу, но при разноцветной раскраске только усложняется задача.
Если тебе ещё надо определять тип фигуры (звёздочка, трапеция, ромб...), то чтобы написать такой скрипт ты должен ориентироваться в прологе, как рыба в воде.
2. Классика жанра в сфере распознавания образов - это конечно нейронные сети.
Но не понимая задачи трудно чего либо советовать.
В одном случае может подойти обычная сеть обратного распространения ошибки.
Но я вижу на картинке фигуры со сложной раскраской, да и фон сложный. В этом случае наверное больше подошли-бы самоорганизующиеся карты Кохонена и может быть понадобится одномерное дискретное вейвлет-преобразование порядка от 1 до 10 с функциями определения разложения и восстановления сигнала, а так-же очистки сигнала от шума путем удаления несущественных деталей.
Это тоже виды нейронных сетей. Их есть у меня в виде исходников, но стоит-ли копья ломать не понимая задачи.
То что я приводил постами выше, это нейронная сеть Хопфилда - многослойная нейронная сеть обучающаяся по алгоритму обратного распространения ошибки. Там есть много плюсов для изменения конфигурации сети.
Делать компоненты для последней я в ближайшее время не буду, плохо себя чувствую.
На сайте всё разжёвано и можно сделать всё самостоятельно.

Редактировалось 1 раз(а), последний 2020-07-08 14:51:17
карма: 6

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)