opencv/0000755000176200001440000000000014772477422011564 5ustar liggesusersopencv/tests/0000755000176200001440000000000014576572451012726 5ustar liggesusersopencv/tests/testthat/0000755000176200001440000000000014772477422014566 5ustar liggesusersopencv/tests/testthat/qrtest.jpg0000644000176200001440000054501514576572451016624 0ustar liggesusersJFIFHH@ExifMM*i http://ns.adobe.com/xap/1.0/ Photo Booth XPhotoshop 3.08BIMZ%G Photo Booth8BIM%qydB 8_28֔! ICC_PROFILE applmntrRGB XYZ  )&acspAPPLAPPL-appldescPbdscmcprt#wtptrXYZgXYZbXYZrTRC aarg vcgt @0ndin p>mmod (vcgp 8bTRC gTRC aabg aagg descDisplaymluc& hrHRkoKRnbNOidhuHUcsCZdaDKnlNLfiFIitITesESroROfrCAarukUAheILzhTWviVNskSKzhCNruRUenGBfrFRmshiINthTHcaESenAUesXLdeDEenUSptBRplPLelGRsvSEtrTRptPTjaJPColor LCDtextCopyright Apple Inc., 2023XYZ XYZ !=yXYZ K XYZ 'ȗcurv #(-26;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Kmparaff Y [vcgtndin6RC& PT@333333mmodDٓOpvcgpffffff334334334" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzC  C Y ?﬙MS4/`h +"2.ڮ=臂q|'gQ_s#5^W1_ ږ}#ŲtTKG W[e^A<hlArOSھ(ﭕpREC'Y'4f]>]y cmIx+p„&70[=fk[P`E|[Sqjp㑊Fwe~N4:FnLBsX:+9p {9SVRi Fw-VJ3_: dO&jI,n!qliU)a:cjRtWOՊ_+oAkUh~aUʏ*Ķgː+4Q"8nV[Z݉3AXgoxWW7nH[Yv޺V]?s^O:=ڦ9GCtZ ?|uklҘظ^ Ԛs >;ׇKODg QOcU4F>%'~W]=Za^i.s'35,6ؑ g,:&R,~ ׵J5GOyiT_1[w=uxxt=wU4Uw% _٠vJ}uzz U;Y`tJw)M_ oTVo.z +q^{=2:BR1|ԉwjSH+Vҭ:NVţybܽk|Dp°4sp ZcFY\VE'^PDc^ep^ [y7+xV\H+(+iX13 v2q\~bqd4Z)Ni)ɫl+'į{P?l"ݛ?K*f?7f(Ľ6Z^F%sv?+~"-Mqؠn9^ObqFh(ܧWJ becYr#:xVpVP{4 F#SC-u E.b>wCjxZٌyqeɧH^}WڛJ8𳷆M-HYcw ?4>*Z1}D*S0SDLoŒ9:MCM1Xs^/ᗑoj x⿪MQgd5q;ޥ 3.\ۑ9\%cW|2&Lmr0wFW3G#M 5€xYԄo2}Ym5ݐ~&MI`v?*"ĿK}NRm\c5M3tcX_^!m~c隅sl5:@Z25 rG|bbp)uڏ#iaPO2qfkH@t2$S0il&0&N%* V[2Uf-ær*NB4V*E\D$ Qv)XfzGAUɦ.JJ"i=In&qڭhE ixE'ҥOTՒH>L wU$}Gć8S[ A<*?u&IsMjFZwzT-{@[j6z|QJ_C&W0uˍTk>k̝:$6VI2e9ϭ0fSg%8 N:•:c-ąHE!JW%V\sU.esڤGGRT.c+arc+Wx+d)MNp*SVVfi5VI$/eQ˸)=DBLbjbӚrc ǥCZL둉Nš.pk"2$zj":ztM?SaHVlzD+qm1N"֕y4_4jo7WJ^3WUa@s\>|G*+e+7cӼgcq>ho 1޽Ѻ5EG\M:u0\zWxCAZд=u5(=D"'9cWc #~ʗw2iC_Ri1__LE͂]r}c8 01Q*2K >TTb9R_!95CZR_^!ݰp*;>R+XV6 ^o$B{f6/SkM+Sk$P2rkQ3nb}RPzxћNR: +6si'\trm48\邾斝j#cV<|7N)W=Ga^{xnJN:~uiPɭ&i\ HnxW :McgJ0SKit Y8'F᳸[61]P4Je%6RgI޴K㚭LG*AnpjNRbT%ּ*Mx\r ەWQ6*"yB~ƪMYb VaT2*Xcګ8ȩq[ZLf"KW\*6*EH¦'Du(aJ<ܯ'J8-TM 5]jBOsH^*^u⪞ւ /֣9#-@iaSuNr*ѰssQm yEvk:aҷS&QO55^͸Kk Wu%͑5~',WZ͝wc-6q xV~8\*Bב"OD#b%t*aWI>4_Efֻ !ĊH۠9'ٗknԥ /zѱkKiXe~7\_ +]Y[© `}+enR%nTMR}OK;ny3:xZPb01 a] s]4ڔSFsvv)O7Y1cwPkbb.TrpqD[zķu"ŽU۠ 8ZE!9%47x5`M>Pie$`҉U2z|yeR)<'-4ir11HH9P9ᜧ.N*ovWS5EFoP t;\h5-רx1_֬1kBp][@-՞b+8$_CVxo xI3__/Dt Yy5F@5>67+WڿVOB3Z3r&e!qs/܀Mx&NװW!VQ+{C}!/ُPQHJ7?x|1/IdNF:sEȕ&9{*g|3*(qjҠ}F~5ɊzF.מ-< .6'׊mbK'9ck? *p6WZƯG}(ƹ!Nj.Ƶ&fX#ݩB) G7 ֨2LSVȮVk4X}3My jʡEs7q2rk1K-ɒ=zU0Z[<5LGjʕ$^ <9j&Zgf *; rx9lbYnV s99-O^?4P΅hVaޥh ⩳Zk$wCPj{y;n"ح$a]2Z]H;U߁k7"39$Wp@K8b1N:]TK?84]oZЯ$xhYO*k4oMXQi sXҾ{ӯ|5k%zח:XOC+Iu{J=7:>\ev5;W)z;W%Qws{9G(U'c/KէF`BCz#_zV(+9M"'`YsRUaW-dJ2CȨ*Ǡ]I"xVHm ^ڄF6t( <ު)bs(W_e= D sI%C+IϕakЕd|fv#JJٯm5_fܺ\_D 9YGE+1Ue$i§ةlcھj1|)@p$p }y~|/82̢"gmO:bCg/!ls_~6o;KvG_lFxO4C0JI"{HƩZ٧3Ҫȧ&Ѫ-iAӭ9UqNfq;Ԯ4ZVCqUQRJERf 2l黹&j7lSAOF욀6yjH O'#(asH\haޑ2FO4M)1[F3QO9Q61qj9D=sNjaEaAVBGJ-RlJJqҫIeP UzwS1'F}M ʒUcҧP @HUw;G8fiƩ˓VU@TpqU5uj`) b* TqHڪ>IlZ "U9_n&wVr,Cxx<;p&溌Wb=eO5YYK$JL>I[xx@OSҼG&_HM/!!@$mD ; WA7uȎ տl|;*o[}pMtAh?: > _M ZDJW5ҳ|?htiz{ mR=Š<5dqv%|1{O1Q;>#-^i 7Jx)޸%J~EK$ q*à4rF m- %kdט=5Wbka'&< :qL[$ +ɷ?^r/XБ :9EvѬF:HX)Uh;^M<|O YX0+u˝Gyxqz<zڭ6IGL4v6yƜܴ(KiKc+RV6?oP{WsF&dYљij}t ewo!=*M2Z}xpKI%iI4JGPgk-[Q/0.5K{sR #4x$9`>hkHbVb[Z\T";a1`.ۄLΐHEa r֌wv?:n(9|NEJ$V{M97 PvhS:S7x4C怐uSY(b ;fgҩյ'U!pijaKӊV;*0wLhD͢5Pj6Ojafi$yQ\!r+hNFMh9ķsfψmUfڳ\*O xK|> "@ 2}zc"&OPj(93jOxRiV-#3ֽACkU#ŌHUVmڥH٥N2X GknGBVl[m2(^NHŘ}.,-Aly2-  s5ܬ񭹍&Hˀ.MvEoPCr7O4ɥ0*9g)LͣjyTUZxұnETUePR>f5\6SŦ\ HnSvP[Gyu' H]uv0R[SecL6F==J÷ixeu=q]^GJbKCC)f8jRMZ3lwWU0SS`y.'MNkBMU <]˚q&DSr5XjhU'a"0zѵA34 /ڪ.&cŚ auǽ ZynM7qT.9u)ԡmٮŸAݏo3Ո<>i6MJn_E#h4_nR;R |9\I9^ϧh:nlij և~0F+9Hy}ΖyNtuz^iz^`XnMAY9hwĨҵk9rV&jttQd3U!$jY5f8BrQ+J7(l 6Cs 0jsҥ3Lh%߻Jٚ_I2V)'CV<κj6$H-9"NWֹZy-p JS<ٴbQ~%Ď6j7d*FҐHmx6f5xAc~}Q\nNG>U9&ţV})s%FX3ZZUڈ0F2>R8F"EInնHR3֯<1 ݌U#9hiXAsX|׹rH۶23^Mik5(+Ӽ;q5k3|i}=4']ȮSs6DAS]R0ǕJNhj%v" u~mmhZMw;X)-GcQmg n}gW7a/voW(r+J4TTC.\ Ţޔyz|a\N6irLXԼXY5 iqE@qUFMXBQE8S+qP 4[柼jsFMĴY2Pg֔`.Rcժ`cHA"RԜ*0EMZ%WmȨLdT!yܶsiZ"gިjSIrJקAg+"M'5yɵ?'6w7ycqx^:5mPQgb.ߥ8DJmĄ$c=jgenigƉuۘ̕{Rp2Huo&q{}Nad0\9{1PϧjY?gF(I=egڍox+͢YK6ڎ0}qFYstӞe(RFoLO59eEڶ:[X'ک-+ry_1kij x[ p+o9fq]ck✭sG#ָ 5xin<\- q.>v`De"s[T?jW0;FV^yx$MʏޝVNw&od_˸ yX=tUdkГKŒ'vS9-5ȹ"H@^ k^S6U0n_ZN@,@@)rp uI ;qZb?g38Ñ|[0۩V~̴s#Lz[JsS+sG=B[#UyW.ݼ!8*§Y8g,T^xPH4Jbͅ۳TDe&v~yJ-Gƚ@2۟ƾ. yJ+ۉ]؟ζ-H9dHG}~LEc9=$,gwz'DHiZmV=Ht8m-bU R E4c*mrbL(RA3ʌL{O>#d%Õu])J&ֲmyP-qj[5%Ȏ#ZRsWqD_CLfq#F\V1Wոȩf89I]bNG4yB:H#\ 9ܿ5x{tRӭK>&4E [BEU,VJZ|ZCO[3,|Sn5$|¼ïuюu+P 4Q˒3DQI߇Kˈc޺x~EGktňqtm"cl'רO 21Wu{(-h=c\y].S^ߧh ybs/4pB9Eg'a(Dx^t=-,s:kV5 YT8Us$NxDcҿ@5mk;\ʅڙ7>'  ^xk|1B*ZH˪'U[:: VO }h)"aڔ75X8(9AEUz\USn㊮'I&KJ Ujb% j@I⫃ZP;`)7sCE&nI4ب3P9@)sU4?<JBX .QlC㊌A8 4Ԭj#; g+t4i3J*2ǥRdD6:ZX£'1&aR259YMCRMƵV`SIӊAHaTC*(E$F}MG!5sVqj&awDrN:U 1PJd|V[֫>R\TlsRUzHj5`  [U"5ɐ p>$VdG=盛0ߴxğ<*+i0y+^cU~F.N+_8xr^M\+A$++-\|&{=ܽg6sl4:SVBd,6זxR׬t9 GQ^&{Wkťx=WP`hv+c#4v*/S:oFlˆ#9㽇n4;rM |vN-^"ԵsܨPá"mq8dQɫf@⢕0YN3X۪͓)ŭ-  (vUSec2Ucn&Gu$dZ>#jcI>~ʹEg14Y/ٲn.Mν{_4Ӵi${Wǒl0H>Q$~j&LZL\WIq8 5M Jtv0*ƪ0:uXH4֋k%2jm1"%J[U*ث 1G03DGO-֭!Bƻ-'z* LO\qS̜;Y;rEli ֩0(A_Sxs(QrҽG&cG|V7܆||&IgR翥v㷎<*(T__?Px(_HsQn+ɌObR6U>m­q̆]r H 5Q.kBF\ɞRR7scpS!*\XW68z Q_K|u}=X$W W8+RKm+dWߟ ,>{`z~־ ~]VEvE=rWXY"pjq\M ƒ>1qP`Ÿibq*{ ̍տcɫ4!TyQiŏK.gPwJIeNB*MiF%Oq\ ZW"Dfb14szͣ?fZx|H{[>95-ªGL!~aҚrI V*ePwu{W #݊|6F5iOKp$UOYڸӿoBxRL*̼OC6/n hc&[y⾐t<+ͼIp!֨JB"[!PECu8+;aj&]IӉ'ҶJIJs(ke50n*vڤ<_=BR¿Q` ~J~ծ/-m<,0?M]4%oCEʽ 3k*ISչũTC=\ST4n9w ӉsCR F͓ ٨@٩= V&@Lfs@OEFN -QNM& >Rh=i $SHMu犍*F'IhhC 9'4M`z,})Qyu!9i#>bH؜lp)r*4b6ɪ&9V@!ZՒ*LJaSTG9"&UU皙 $qP6MJ=@z*65hp^@R `Wl*g$Xz|Sy/sq}*\D1\95?*0sX 3N=&'(2VefNx_1oAN+. w'^~-w9Lb'+-YozwsF A|=Aѣ/U0K_O \x{teJy{v5ΒxTq_ѣI| .H?ֺU=k_w,maZ[WȞ-z/:W۶ǖ I6ܶg|r:Ϗ"HP-U06gh~p*?Ƀ޻^7I;P ozѼjwI3OڰtSt ksI*9澌8\|my)ķ,ttmV۹bgz҅z.Muonf#oF` ;x W~%{xS/I(r6>Һ? 7QDeF1N:>YZQ#!r*4Ҽ_ƞ%ԒIxDr*iEpjVau S u1r&Tdi X>"4}8][ z yc ԋr@[79t((1OTd ~wRp:S[Gzi9wbMKE AL( NHHP @aOJrƑP$Ue$)z_h$\RI>I=5'֛L ڕE8o_:|rC/W vDoa3$۪28}lɦ8` 'Z$d_ 4KVjG, zg]+rSKׇCIAC)-I\+X^O<;kld|Ӷ[[y?/jtK9G,)bj:DhG$WA kFsG0OH)Mz5V@T wE1IȦMl(LVIYvmp¦||ԪERREJ[]BCWgLJ]WEhПָҿ|o3?Ԝ? ִOsEbla_[d&EY$zOzTPW1c9JPyp,QP+5M6Q>3Fq.<i& N;ү44+ cUٱSi;g@iF҃D4UJ[WnhƜzTM/"|rnDơ8SV#dUf^;f 0TZhN&HҥI&ߏ )U[iLbO*E*|{;Ǫ^$'IkB<~Ust23zW)A$W=l> KN"$dny M:g&a5B;WBj H*LMSkC-<|zx3]L\uGڿu/|<">mωGw W{-JX,:g *)XL򶦑c O{5&v6wWxA=r)RW4k::k5đqy?8_o4iJ8@ Wmѧ7i脬7BF=I_Dq%QѳU"9لo-=k++cq>#4>I\:WڀL+F5և;ZM[ZϘcWsբY.>'}(>\kz!XZ:Fd@$*ghna>:姉t[mjdT>#%ִ KIu "ZVzUZvQڭGZ-#0wŸW[lv;mI~j+Om[\#c%ņp,ѩ?4Hnn.DKMdzqVtY_Dw:ѳv՟ |;~)~7/w M<2w;pFp}E}->v:BBԏ-76=l-~/.pۓݎI략Vnxۣ 8=zQ?,3_4yjZ6-.y9SAaO~4eƽ# 4ӦO]>4f|ZD(RO۳\ QV먤!v`EMZRrr*rVIߊ׀V#'N1^FGx'ßx;x!g5kPF}kދ޹Fw&1\ m9HP^jF*E4 )>@g]nOҒqJa )Өšy84+\~е zPdW|]٤|![oF@=+XRlfg }c=q29^~ R=XDdz/i9AQW'gGen?nEOos]Oyђ.d_#.Nj`pG]PV56?0\幜VC/XL {Wg58sx@V јYFZjo$UթE9#?~x\?h1yhzw𧂴) +v~mg$}*~K,{ ]'V"5Z6SUEib6֬,BjSL=1/^*hj؅OjU7)EȌ.C eR5L65\5aH'u#Î'*9ˠ5bBrGZl?+JCfB0$—ڎ<cs:zcp搌p+2=FvdRI**䶚DA5q]YVϨ7 x=ls vS>Wc] 2OJ7A1o3ntTYUf7ոݺF7S\}E.+Ŧk#$Vd3 8楍A\qSw"|U|l.L{T9&y4;qG%ƙLЃjPi8+LJu)AU+Q7=+AvZRI( pLڅ8/b#U hT8K=jB1/xt) \Rz ĸO9|SJ!rsIiC2-Ԇ\VsQeJqԟ0:pa:Ylid4b'^@i%T p*eV$6]VJ1TclsR96M+jk3G~qeu ȿjuJe9|WLPgDMi@dvHWӊCqڴ2E2@R:ԕdXVRځ@RfH֤qQ ;9!8"9{xr]{Ӯ2a!8k[uC~*4ֺj}^%M~qyT\-C O34Ҳ8 aAmQ,8vrit3nzStmg5=Ik/ _c.9L@UTԭ/t5sC $dk?Ίxdѿh/ZgVz P$Fd3 d{#{x{_-zq J`擾)pHC Wԧt1;d,~TM`J[FJ$ Ust5uw]H$8Kxds-kE)v?o\ߴg/.4>ꊧ% X[>_pwrUiXJF⽚ eN۞m<7^1z)n72b%c$c沙&[]0rpiѷK6׵x[6QA󻩯0_ UbkÚc$é3ϣF"P+״eWz6#J1Uv}N$ j0MG6j\VC@ ZtRXjmjDFMiW(@A)qU(ܖXj}ZaF1M֌\УS5( (]VG27՘^rINͼ \)Lj`7!Qz`Rz&6˰ZT"{wc#7Z :4٪BEHы7'<jpW ̗A|·Mxҝ @54iˆ3KJf rA2hGx+N{VU85| 5-+# إbKLf60"tLէq4<4zu;Fڤ+"QKf9]nͼO1\Xlzo ?2M\LM?r1P4ȗxEѰc9WӱqQZ[Yq][#𬡛G'I ~ `$g<5N^? Hx$8|V55Qn2~P?kbڱm+X׶BP~/l-Eކ,U9kucI?ºgyaP;DKLGErZ>Mogxfwmo_6&_+ѩ\R}4;->MJ(<"P_c^>iEwہ|q+SY{^6Ún{)y58aNtut/GBǦ*DT9_j~ǶYܨ?C_nȯ-y_f 4yf/ǹ&?WGbZ 8_Nq]4oJutv0V̱;2hhajOF&#h9͝}W'/Akuvk2-V"1K&sP26n1^3Z'RqYKcrɯm[xg& 50<J֒G\5ռr%ČW;XbchccVMڥ"oRNԾZ 4fGQ#+|FMw<=!6`Owv*q$FthٳQV `/Z =*[_p8!Ѭdٲ-,q]FnT6Ȳ2 6A@:RTRC:Z)aRF4U;N*lLuɣ I*ay4hw{T;9bA>_0xs. f\+۴ZeyhFM@[eF9RҬr"LQd\qMsRVJD*MUf%pzՔ$UȫQE+JiaUA H,KBM&N+CM&F*QIm& ZeЭI,R.F)O"rMXGWղObl8D"PyId̎F:t8{k=J+~ZnS x܂4@$ק2K 1<^DHӱZޜ5mS_ҴU/=J%etyc ?g Y mW5ځ^wsFÿ 7>x, 8F$yaKujE8:l?W_afYe}d~iQO"G`Z]NQqi:1Y5zGg$a]fiȰjxw7x|65kji62@f| u C+7<,:=,n)FJ,u/&ʖ^6Pz?@lS$Ű{}EA8x6V!?ʼ\lIr ~Syt#b(:EGuѱ_ { @WGߓcGּTcY|bE凇`N A #ie3a.?Ho۷ {Gk'n CEu$NZu&|m~$hE.IBqa5~=i䥰2ZիBVq)a̙sSHP!|Y~4jځmFϦ!C] or+p1+|mgFWɆ^ɐ75Ɏߴ UT wR?Pp/>5HOOhr8g<1q9V[>«_F +jٕ NdSRj:پN %Ÿk|t5~:7fβ㺎ƻM+&5"w_Jʋ*JF9˟)߉~*6$o`qI/*oOGHiGl 5uQՉR~h[-pg9P@"5X:Ѽvp'%HVkh99^p83ᓵSm IN+xJ4*&"JY,$aԊIio/@j^y񐎔5Icme6ȧo5Bl7[A4qO$Mc4msqW6r ԓֳsZҟje+T g+ yҝO f҄KG#>Vb*e|dXj xb"HMc؊.s?{}=Ks,My'=g5֯FxkI"1.1STjtadKU&슌dt9jpsTU*zPfax9RJHODp T2zP͊b(c1AUT%JN* $n)NԇdnL@FK*8i^*i9S905wҘF94gޣJ9D15qO&cP!Mc4Yg/rxrY;R؎q+2_Wکbd'vve+Q{K5ʼnC YzX r"v ֥ijcܖQ4v8'#R%b8D*{D24)BzWaQ~"H{ "cu%̫prIוz=&Y%W-5u^$fW߱g7WhnϚګ&?}2gX(U;ӌb0u(?ޒiqKN^nBW{ѿձZ[\ ֿP>|H{_[ y% s/ NwE̐yQ Cލ.CCtb=ɗ{YV哺;T੩EFh*N=i5ٞrj6_AS7">Z\YHFK`v&$f;{_~26RdB s:ΊfP#eI ڠ5n ?CGtDfHs $=k[F~ jEVOdO]8j4(ӕc}i^ǃ~(X> q g H5]٢{:@—lk-5tnS"Yt0434&<҂)I4tѳ*%K{Rzy<ь'8o=1LE :̝HЁq}k뿴ݒdܢV(e#.5/6Ճ§96+Сem/efl)H{$@R>5$}=Xevνg.c󓹩qcItEw݌b.|? p W^zԱ'sR+8Nɢ\)6fKBd{GS36BUӁ]kb O|#, sXZ6o&$RPҷz2uJ}fu;5S2e>eJHdW^掰|/nR%(jq!E-qnVH9RxR~;F9cԥq@Xu>'/.#H;S:j[&}o&cE}ڧ:P^&RghϮ UNfHeVJxIt(,|_L+iڄ2Ê-PHa9ǚ6[p;#װi8ofd}ZH5Ha$?z> wIn_Boý}ԒqcVO@9F bkv,S$ 0 Up Ԇ]Y 5E[J#!犙 jrjPNKq[h替q4z5q4^ &P,=iY&mxqTH|,kK9T81CB 9*?զ޽x=iB[#e#"8t*E^k%l|i48ydEz_b>MዘN宿H ecSҥT)36<33@d/8Yv?[ly/؎Oj#Z^2 Sg*Ȝ+X~8Ͻ`ՠ}n:R@gC}84IL2G=jeIH):)$H M̝A_ucZƪNհBx].~\zG b-H)-B18OhK^c"?&y#_7h C->l9H W&A6Uw8]kV06yAY c>xx[Kԫ&<8+{EQN mt/bS whэ6]Mzv#R]'5CHU~W ]E*0Î !YFX!\`T(ZRv/SDgl17EN|Rs[" {HR28_ٻSu߃ZܽJG9bicgJX)\NkxsoDc? Wn}k A~ Zi!Y;y# һqCY#|K:+.kg JbhmcAWG=.AiRGZ4[GQmgXe7Eb)ֿ [HjCp { մ=[z[׃G#s_,xF83(<zu>,x/dddw#ʨFAXc\:0U'>-~KnXW/ ̞.ggu%cR𽼓xW3$KJƥ!8ce:> 8Ģ[+w!(0+tM2P3ID%^\qryi;0'޹h*n&h\yO)ֽ6d]jW(L/z< jŶ}F⿕mw\5)=~c=;3&:sԐk#vN:0 Y%؝\CE#dΖZ,¾.@FEmZW374sK\0!Eej8+WᶙȮgF#^mF+ Tfu"b6S #O=k$qQzԀ֋jNaދH3iRrE;9:ИXMF1 gڗm(=Z`wrNM($jb>\ OGԓDϭU2u82[S%qOElȟE2Ĭs4 VW(ɦ^P>kIz}O:bbQc9X>q'%s2ldv+ 92ZF{fSƓvāX |@[Ju%k-[.z ~!X12Tg4BG  e_PBqQ_*բʞ+.Qy+EXrx)2o< 6D澍.Ȍ'ovpgSORrF=GSIgnEQaa,繺^qE*doQV\wzK@rS&uʆB[JQ:8#֦ď_DxOiW5b>:%~<#ƃK _K? 4F5$iB1? mjTn~UJ[̏)aBNGR/ ~| s-<ךwp,^#м895qsjԁzW>`>YA=_Fi摫iw]/3[\ȫT*UUXˁSShrB2Tĩt54U@҆RI+@lii%nqVqMhTGJIAfkP8,Y֓y9# U%Lf$<l W~ǖMiOOg4;dѩcQQ9󯩿e057~CJ#E \AJLX 8v{=jM\H85Q-cu< Ռ;O `j&zv*zګS-N3޹Ff==kns*dt }+P "yU*[H:ZnMn]ݜ+<_/qeףԦi $ccPO-O$!@+ x|wi.d+\q~>';`{Ӳkƭ-N{N$0☼ Q[<'W76sOk2 xMKj'/:¾dE nkzagz乑u\6)lryz{bxCthx[kH¿O:ŏxbbCMy y+ 8 ?Z4ջJZНJHL>f%_ kE9Y^Vh\HʞW'|mi׆4HePHLĚZ H\ו*pq/ QgPC-kP5+xc,rΊ~l =kC/B/uJ3G}gF|}?5ײk^3FBz_=[D눣[yT(q5&ׁcWw80.9=>ٶ?i͌ӡpr;զi>z-go@;ִFTevz3 =i,KqE~ 5?b*MrI)z஧+-"xR$Wq܎zg|F%ۏ'<+cӣZYȱC!$>0+?7qꗖK 0mkbkia5`d1(׋R5ƗxQS^s5=xƓ !ThF\ we|'¡*}Ծ!KHԼCigy7,Ȍ3 ~F;-[rKm$][m$0W?o?? ;l.IVzho3'Y`2z'\oKR]JoO{J== kR'wh]V`NaeNqmռ%u½֕o¶Dnqڹc J?<=.<+:yo mQ39+`v}Ԃ5_5H1xV$2%ىXw ]9AE%zt_ Yu rI#u~6Cཅw2N[\쟢I|RKĄ8 n D18S(p˓s*ݾ7Iglz7&p D w Y b?Zbk7/TERlu[k;$^dJM sFÐ?sT+z]s$S̥pOC{$zvq1`~]v9MkWc?7<ʑ"€Q{~~Ś?oHĚ4/ψ&\_KmW37GDI>%۶[IO)v;FԒ=\ iq*6Nx,UYV**3 M(Xa0=rk[J tku#֯*ωwi~pr$?0?(5z(|-r2s![И/5-cG?xcd'{R⊵U6Oyoy*;I~[E~J|3LKG0}:z߇n*FXӆO4JNta;8906MJ<I5>s#>SN4qTi[FCJ2ȋȩSLQLhN8.Z姞EW0`qRp"`?-zqPǡ!<טGw1*:S#sfP5leGJXjfQ[5cCT$Qն; )P2jʀPȓKu~mC \֣Ky1ҽ_.oR8`ir+4e:g^*h0G[cb+ۜ\[ItģaW/nJ+HRq_M+U;a'r L~_[W/^d| (O vڐLdE"\.ǽY&\ե@}`{T!a[<\I 'm6B6e< LX̏ۃQOij?ykb}?_s <7noFC9?j3AnmxrTApޯ#z$XSQ#$Y{TjT5yӋ E(sE'Uq "vzRd@lR枥\RyҫRM><pVj`4i@Rխ,x\(p*"t:Yp,B;5β~3^$gfېfTƹUguKt .ckX,q* _,];sl0>ӚUUHݔD[Ӭ$ѩ0|_ |3BI+8pOS O>ikȂhoQ]B<%cc kVJW7vvD)E␷2)Ic0ʫ$g5;ڎ}J_0&O=j6\9QuD+ u{uBY-ס_3A=#? }_c%Ÿj;ԐIo O?em ܈sF}W8,|+þ*akg=?t_-qx ރ' ߳m4$1H؆ 'nga`8?~0=17F@UG?'y[[ŨG~2kwx͠&a'H$nWUwwep(ʺh\Inua鯄9?᦯'Ğ{OƪvJ /úΣ;V,Nzem*̶qE2k#>[֮|;Oz-%ֺϕ;8G|S3i G&~?ni[5)m;c>dN.>u~ g:fx>'Tl}ąnoY}fubWw|16jNGNìޟ`ͿiRw̯&:g+!|P-xv K}fu|$JSSI D%˼Za鿁F|skU"|Ym<qk\B&|uhR̊0XmRp=sîxB/kDFeO吥ԚXhmTߊ{O 7QgsJŘ[_&8`cnoJ?g{(3[$6#|od[| Whk=3®[?T>jbuEjKGÿ>s{xsJ&?ſx썏9hi4ijR*Pɯ;WIvOjI|2H;G+ы)y" p+řm"0\Y+hq" _!|n=kMSѭnϼ^0IjqUX]S?{x.. Lg;Р#mNUz|>|>K ڃꉴş.gid`I,0QjszU* Sk6~?yd{7NG?)A"VLC_dt_^ŤX m:trQ%>ʬU~6M/zޛTn$ymSPqW5Qx߀)6#_?tYAW:|csr$+67,/vR?OiтWw?TSoV?j`_E g1_{2#B6+bv"gnM𧸔LskgN#cv\ pAq]6t]U~uZ\45ܶʿc>-ꍤ|>k1gk/ qkocO.\k:V kEB]T? <1i u+q$:|3`gtD6Ѯ? zg]kτ4v*DD!G+nr=v1L~;m]zuQr@p+>S2KMiIjECx]k㕗Pn?¾A׽~:ߴ^c[6 PI(R=3P?5z1 ל%d?1Kݤ`k5:bzG ӲN u>>$dl}1_ VCXCW{IHV#4Ț?GYmkݬ3"#2ޢQRg2fzSYrsHRqHf=hQf5_((*Jkm.(늁mMݚ\j3tG56F+=D7PH lՇ!5)|viv䊯b5 kjn;ҒlV#O@)Ej'$`ԬJ n*z(0j[BPTXEm8ܔ(#b4Pt$75gv846haGF *u40Kh7)犑lswZyO"W-]J_>3nҽ#Nv>N־j{鳆P8 ^s{vqgI>H$4 U嵋jzDRMxrca#M&YlVlUv|Sٲ+Ǿ)|WѾ- $jͻ^-мܬ>c|O;Շw!;oA^k0$5+v ?*@+ήv-LWcedvfi];<)ǭ`vU%MaՆ#B́UEF@xX77_ 59R])+ӵXDak.Y=Ϙ.L.cؠgjڣHX1fFX#JF*=i7Uw'Bg }93G7`~k/>?(xB~;~#QFe.T4JQ3ZoP|<ŏڗ2 w/~?xnΓ`x\*v?Z<;uc,*0\ƾ,'xZ_$vw^˨X 8Cꑨ1*Z3ѵ} wH+vRkc۠G]b1NeHNPqjjR~l\۔Eg˓FhX߳T ?r];K-Ť2cP_G|QuֿmWpp.@<1־O6zvg>Q#@U9ح+b}ďwu;diblJ+G {J2/[^.|wFkFs_PcoK{0\?*F<]dN3W~?M^[m9([ל%Ze|=]25cĒ}ɯBeڏ]-sw@1?6k+$lkO3Ck >%bE9c޺y"6zy%~hmJWGyԠPx>UyulũB|?FZr|{> =B1 -=1^i\uHm#yw8 +[ }W͵-I'd+/cgòݻ<,IQ_>|aH?? c+m#5V&:J.5[S,A C3oٓ7O ^Atkyb=dy( OT׉XlH}ڗß`Z=O00m$񞑭MCseaqJɯY;{pe}csG&Ndl*aMG_~?:g'Ξ:1=Gs,Yg ~QP|p-.j~j̉#ss_M"DCAI 1?cCGy($:Яؿpű' }8ֽբ;VƯSx8SrW _??<WhIEJ2ug= 诫l&Ɵ @rb+ ɡ<'J:a}k+Vvkwac 5DQ+M<=]T _ W|ml;:? Z7R+eP_U]xQLe{ـ'b-QX8nu&n,?:,GR. WF0^3 96Wiaucgҹ1@ֹM|r#Jw:i$A3z Y$ 3^}aw@pevzlDh_V#eTp&P"ĐujR}%FT@TX5(CRն A54X'R*T2EݜʆDj 2T%j@Ur8vv櫩4TZ$)E ^␞ՠ(8RZ:@Ӳ[NE皉\ABn84A.P¥\g9PG4Q9G $+f̴`BF~X>9>VeŐRtgw_P3_) a+Ba{Ic6gO⚶*85Yx;DԭRꢼS ᛰbZF+9IC4G2 gw;lOITt #վxOhc(?JjQΫKYaܤup澚67:: FK[g;i; j0 9ڱnylXz ])[!cnAvPXU:3w>Ei#[_ҾѦ36;)}  ŁsߊYKtp[Ԥs%֣xñM,S^DaW;n6D~j~ 4;/]+w{jy3_Q(ZO5%} cVCgQ*u\FEsҦGZ:Tq- ȧDb+2u[E<4;b#;]Ԇzz'dAZE\SVFRg!r\;p3J1M 6q҅jpgB-vN*$n94f♻i&xNuትs~gsӊ'uok\rIPO>;~ M{UgE\zzIӧzY=gsva9..wU'M I\g.Epv{M۪??JQ5H` icˎMT7rFѐ;jx"2lh:T8|qD7$OAV #l*+w-q Djp@QTdj0(R: yYX:]^S. +SamVc[#T}oМ${<=çOIjR{d8 =VRb5JA94H;^GjeyԎ'b}0~(VkfGog3߄5'lU>1_1c6م ƾ1] 5X|@,z+u.&qYiGf |+:t58\=)%~T!Xj_1+fS\5[s U1)KRu F{,Oj=R>nx^(Y3)>>xSǥj:flY4lP ~|ifo"vXڼq2M=s/]}: ]14Rd@oNτks"4Xt&!tk6!8m^iG|7A㼲+fٍE X}q|ElmoUnVe)5_O=IIZ)Gjq+A5?t|'K_xkO=f8uĊX>" ˢY8G8XμgmAmouİeu09ۃFch6ʩdq޶Rq80= h&ѼGno<;GB:M>?G?/ 6pWz^[ඖO. B'(-פ%?o Vy%IF"?,f_x|3O}sx2xK_ЦKE I#Y?\WoCMGҦuNGMk"+q-4(oAJ m _7OٷSF[]-aА~U5Ƌcu0i]dn3:iɱD}HZUOޗS̥uO%Ñ#OZ7%CՉ_;⇌|@.X_߷k)*xO\׾hP_$zv'ה־*]e| Kk{cP3R+Qstkzǥ t٬Xq#QzM R-jvwQ$#5⯆>9 '0i93^5kt͌ub;m9,w5T:QvVO𖍧Ak/z!PdOݎյ~Gmk?kώG;8"غ`n"IXAͻZτ?6;tʡr9#\B~OcQ+[E|wӮZX#*SֽE9\Ru1 9=tGSUk=d7 Oc8ֿ^x)#!8wWؿƵ˝}tw P }mk)ԏ5Z?&ĻX}^#K. k5ؗTѭc*F'W/wwk۽o}sSY$.qm^L ГLiπoeVg+~&Ҧέ[g9އҿ]uS bk@OIƭeS.h7]Q_HN[{{4 gl]83JtkE-cRH5 aW`ND4#@SP2 t__.G8$vF+W >n'I{*n_C'tOkB% ^_;MVg81u8澖ՌOZy+X~̒Iik-DN3UOj+P3jrS0A6| Qm_I,10mkA$4=?Wl,# O9'N=YK("di<1⹭x8NjtOo /^j$`kxX7K Tn9WuN^oǫ4-o u\5! ]5jJЖfjoz^-FlW|Q~ ֮|Gkpg3(Y"{Śǀ5Iw &4*廬~ {NR+*uR=oڞ/:sO&ݡ| ^ Ҵ𕿇df¨#گ?Ӵ*JZG'ۇg۴6_LmK&ilvшv9<**r3ISB&і N]G9kKZ T9?ßkz%!I QqJW&6X_ZJ3, `V[X r)"#S;9[US/O=Hf $O?joS3i6Ӗ?(q}w:$Mi'>էh??+8mA-ġW'nׂש7$~Q?Oƫ hfVFiX/v7#->Au;_֏)~g"C .kk|ƉT(~$|?hC|Y>༉@:A߳Q\6p$W^UHP{=ZT &9hb%I#tM_:aMqGZihSX| Եˈo}u&] ~;?|oikȧ*9{oU ;!P%ՆO<-ªh)Ք|4`RH\X+CIgu,EE#5-_E$|mf<+῁7ּ+C]/q]5VcXn/roz:ßkSW 0ҿDGTe..$|9lmm~o~(hG>__~ [ipJNY[]02bz!i!\`w9>|u ^3bݨ%e g5"3+H]@>mmE81*\'ص^qWsZ&$*@>1"oso}oݬXeBzgMFPNnNկ4߁{H.fUc~/EasYMW2H}ERk6iEy*R>57Ï |to[jHgHd=8RL֕uϡաWr*tWc5 >6CYE{4|ێ:5v؏k+hk3ЬNP|7a FOfSgd4Cx *&BW1 Ȥ&bk4BaH<O Z6 #trۏnkD5}lŤ(~zx")= YO{v8Dlf̙`}m/kӕG㧁m!-Kq4ψ? QLlHK׀5{*Wtkv [IW&Ě1ul00~^ZPkă xsTcL 51[nEaQm6`'5ǯWMpCܙCFnT&!}V+P~w^7~1\kK#0~Vx~*|"0jɥBnvUe<3?p@{#)^tak vlkR@CB )+mYSǣ?{J6y< FkiCWBfT*@q_j|4#NC:P?²u-S(i*? D~]Gs`O+WdՕaTF U1ޗ娔*y@S;(npr5j6sUJ)\&Y,fI bn L@Ⓣ;XyG3~R5PRm2%U]p(ªyNa=k)ShަPN1ҰW%#/iN;Rbđ1*:,UCqҵQL b5^2jː # UA*x/Мu QcT*%9S5!8%<*5BHzh'4(SRUTb8Qh&FA %B)PdC:7O :W4Sڐ'R*}0jbqE%=iF*x qPKzT2*5Qd5#sRy❴gRDUQH9HFT]s8 PzX dS1q`F B$ҞzU HN<!85 7Un)n⎴M$ @Ƨp*vjNLiq֣844Rc @A[Bޅh\`nƞ5T?qfq @8\Ѽb 3<ӗ'N)hr: Aw%Aj0\v$ߞSBbci7g4Aݨ1V/S^=T <%&$>Tg^^I{vP)f,p0>M_M5αcc~5dtaǜxZ/e2]wbsֹ+DKbY.=s>$gHaҳO,\* ke6,xkZx^Y vW*G4\BMeMǥ5#i&Ud+PK 媍qj35+AzՔ.,q]BTc烚 R̬3ff 敕ֵavL n#߼,2+[ryDqWi='~u0)I/j4 C#j 1rkn 1\r+fӕ&iF2~ם}x'<>yl&ԮH>io0:ֲeO~~+0Br~ZZX\]oMKޛcP=0+Tub5P\؍GI]4ܞk |9o>-+"F$ ^{*mC?m=B <)T`FU' >gO:tk.raOJs|9y]}r4KYn!GK$pq0~DPΕ{m|qV?/|QAx#ѣw#?JՋKu!UBLa>iw" 8A{t+ӡm /A_a{wi ]#!G^kz4 WP\9+L-uRgQq֮|UM^9bPxGif~5ď⏉&MCyw38qPӑڲ7(# 3 o_K.3(a3{@Il;8of4aU?xdgV{Oz>c@UJgOـ>9+Iȁctld[GxJSߴBa #HR[c1_>#u'0b^7EQ 5k8v"P~ջՏ 9M5-_eO4𝏎|;ƙ'@O C⿅F^I289{Eς,0=D;{jgI&sJ\0)X:pp+ UMƼ785lpؠ1}ŀ-+ 4[ȕx#=J2f)J ࿎'W-XP9xb3?x֟PH1][H;*3~R7=c5diHCW =k'd:W?mOH֖ L4|0`:bF$|Hu4Vi(9#=J'bO|)4MDS,g5S|?ӼIxK;-PL1xvQIވr;OS_OU[/ #/x¶9=ҵ[#r [}R aOJ:KKkKSny'׾xG^N#ʏ(v_"w2/ڭTSON{W^n-flmD[1SdL^חIg N~ܶF7HʿTf^%1[nB0>Sxdڋྻ;ASOy.d+sWƟس- O꺍@B@s+ wχ~a<]CN2VkĚW|: pEH +L+چ%B?/5X#R~95q;}n' 4FI$+bυ(4MSR-mbps Ƽ9t ﳅ?ҼT#ևL2|'m/ 6c˷A·R67 A_,~1h.Bm: XĠPVxƒfTiJ|7~VPֵ.‚3)=? )w;%Qmo00$U'MֳƖtm[z6s]4KHf~@MikO8 GSϵ~0_:g.{)UA_7~|oS՛= $o'u~ψ^_`G<ƳUcV6uy/uhzpQҚa=ԕPb=j DV6mnnHf*u|C|R6?(3Iږ!ɽߓ0| FAW9VNfw5UG\(؇#5>4k5[e+cxw&?#V'!Lc'vwS莚op=k|)MC·Gh ׆}ʌ`E˹"pآ> *Iwz+"@R<}2*ܦ9~'mfo+'PI'bSޔT9+^7v +!3b8M[[}k]52Or7=Nk>7ڟN-%ȇβ}o_^ەô YZAֺaqYsޜTJHҟ[h[.x\\&ܐ c?65$Y9j "UœbUKsR+r`OV#;\daPRϘI5*F*9NTW& <* G;ǃpSAs7yLU H%4gȪa@V)jY2D#eQАK9$qB{50hR.a sK4ꐰ"gcNh3bIvjF{ J=i94A)j ضL#@>PO,}r~$hӌ׹P|Vo|gľ)kj|I^aXUoF|fū}n82}kK:)$mjW,T6w EEYI0; Z{V'5>_5 W:(6Tv+NY8捖_ 0Zl{xqjx`A$U('6BN2֑L#&4@l44Ƹ$RyrkdiSKdx85ʱgvHe9gb-zS̍k%gBS֥cL[y%j38:5Qꦮ09kzzֲjVhe8D'qWk]lT:Z09j׹=B]cR{d/ݎWM^="Pt_ ~ 8QRXZNQl᫈MXezqQnJś><׏TV7Ҥ* Ȭ,l"Hc8Ϗ/&~9 m- 5p$*]~Wm"C7"$S(rMtj秹?mgl5o謯&D%Ѐ8=:;HM_Y `~ujŏsú5Ʃy+q1 -Gd?WwXyy :HM:k٭S U\6~'5Dvo8?ݑNZ>6jW 6*sS_ 5/' |24/Rcpydsk3DX#>ӧT&Ls!~5YsW&CUNA+*% *~Gu(È->g[7'b*C x_a{KP%*$zEH7tg3U gQu ܅|繞ww嘞(c\v/v7a xMGPrA |ؗrJ^xb+rb,l|02JQ[_^uHlgypmqWIU֑quǟ,c 1W?Q{+vU˨ΐw1I~03KuNs3{Wq)M^fZ/7 ,+ M?G`E#jW% kڶ9htlJ +'&ׂ5]BH$h `=ka׿h]7!5|!G{x}*7rl6 yR-_ic&騣N"Uʀ&o ~ٟd57Lv_ψ?/uOo$vȬR 9cGSQgjz}Ɵ+K(u_^;v|=MƣrNI؄_x_[e q5: _&/ ɖ_7>TvzwzSybF92AV?mL=̊U#nf#~JU7c~;׼Qg-+'1*sJ֥zqag9Ʀx_~?h ' "B=ӯCᧈ|5kZψ18卑q+ٛL=QX⽆%Dq3:"UW N5aSSQ8<=x"03U!Fjz.8-J{0~>&NiD-gT$x3H2-!$~55:_7 =w mT +CF~m Ki.ⶏv5ZX#Ds|+=6#_Hjnc4VZdY$Im7 ]-օk$\<ʼn)`Bčg[kfnpr`'71JWf~Za;"?/^YK ݩrNMtFHZ]73rk7-'XVMXr|);.ZX' T*ŪSf?ęI8r*eHQl,@5XXd5q;LidAu5[F1:MN3P&5,8Sg嫋|rQ3pr8KS4κne Tjב֗E1O&֘2J1{>+xBH&abTAT?|iIDm{\nXh> CJި \X\g{c!FsHyj"TZ*(Y B"G50fئ 䚓e8V ǐjPy=kDܜ`,ѸT+VlSOT!\+)I3K4$.:ԁ! lmPj<: B|"uaܐ;R.ԠPX2Iެ㚧S `O TCTJҸ,AePv,NjEt7LjJbO40qҷ;r)# |pic"̆N 4jvnieapaکTSsTD%5z$+ pE9PM1)MZqSF82iZVCf0Յ(⳽rڱ4۹5XH%R "V UXLT~O}(bOXe=)8L'4ӗD 843d۩«gY3K4&NN(*-4XjDB8*L))ḨAN12 {s@$T;R)Z/i'<ӷPqQښ ?j 9Z8c42 _ %"8˷jon⳷v JX__#]۱H<`qƔdkJ3*'յiwJO{^k}4d٪3݉d!Myev{z6DW7 ғƹK摇c4f7"U1B|Ozڏn7C1/>ٯ"-5H8*+TvXL_v|*k4{{HѲP9_q f+"mǝу`^5.፵ ̘ImTw-m#Rfoqqt9}~%S<1^>ӡU},6|_s?}%&~\4~ =_._8*l]\7k~>>!h/fWIE m5rV. z?)ߎ$|:<xMl|^#S?|Z]|8QjFT'ퟳsr&eЎ}[;SGt"$T0sNޭhgZwKsuo&W ck-]Zj%yT\ߩ%տb;'3qUS'WUja%SD5i/T8jSMeUOT7+I+vR~_\b܀s3_zIgL1sg 4K >rilAMp-)\魋bimȻ^=~u^{U'm?ړǟY,fJoz(Evu</QmnXŸN't AՖkp8n+_V72=̖jlFHǽ|Y\qֱw2ڥ΢xFtso3Bx6|fG!SC~6~ xwǷ('tu;HWȈN3zuqfO^5w? x~-+XeK O2#ه(ǚ_~FkyѡYOi 圜|eW?s"#T` e㟂u?=~.ap'G(~( |?q}q¤ܣ"Kjߋ^&.lt[ |rLJOp>TER9#<Ү31mgRmXDބ|a$mY-bGzé75و|/;]m!ܜvO| ޽Agxֵx;|A\Jl&0+־O4n:\o\*? ч9| ^} ÜaGj ௉t_ xRdQ+G?ʸ(g"4@<¿wѼĖ6`*tWyuJOwxB?_O\%q遊TZ_ni٧?>-zZѪje\0j.yGuiZ{YĚ8߆iHhֽgG4V.gjcOqu!ZSfp5M<$u!.rRU1U]kZ[Q~+UPO x&% sہ|$D/z Ao OғA5K^ %OsI7o,r95UGJo ڽ6|=kaN/Lus=yH N+n2ݝg<YI -gG$aA+ƍaaa9@`pj1&[l ^;{pW#ϵvҒvvƠPUf;"ڌOjrB J 6ͬ0kF+r'v?+dTL'd9(0lOv({WE"30a֥G<])؉KAW5)r HbE8T5u*ɕ7ԇLvZޕ Cg֗$75zi#֥ުpyNr*U=kP>օ5 EkH͕o`TFjN .%F1ɤB3\T꤉0g֞G'=#52C[< OTk/ic2_1*W)Ҵ7)[8in5fj]I2iQ7Ui$DF3SyU7(; RKe*HH)b8U9&Cc!D9+M\GCRi\ripj39vhԠ欧)G17d| j9⧘v!U`⭆ 846*0P_)#>bcL v 4NkDh8j-qK* hROZ<+XJ%5(xJƙ hF{S):2Zy,ZR.ZraǽH*dCbƎ*R,HsST*|sJH SEWi4+bU9`L8zҖbq֘I ST4=6X-E`xEzӰEnD,qQ#Ocqwf{ =(( fBߊ|S;_ ~\8KX(*+S_C:||§/^4SS~.ׯK|s#a+2p\w CjK=n3,,Ji;S$>mt&cܶёޢy^j&v *SffTee5%ӕ%k8O'c!6K Kj6 *]cX,xTvm̿)氞_/G6AHUTՏ2o^rXH/JW]p5+lGԐ3m1/M%,1(dWHPr_j֚m΢=]b*0k= "H%0aN9 (+XU; bUߴԮ-275n&nhIqk ޫ嗥=p|nV#AW}NJ"i#)Tf'?ZKgPFϠ1fx3<]yRguS몟0qGw{?iPgPAxZ Rg_ƾ __tlVy&Qv\_hY[K ׯkZ*3Q~SV_\"y+ q@iqF?xt]>=ObK80?WbmV񾏡\^[^ `| |T3 O'wDK? ןp 8-;WAuklS8#N+wo2 i?aԮieV;gO__< 4{&dS?δtc8ֻx;.otI8ݱ }%=Ʊ|U5[ȭ.2Si<_}|ks~h\g(kV!ݵWFAڼYS=J҉,`&8y'R*Anik#H/&@IA3jw9J'=q_i;hZB,`d׵ vo/ĺ%kӂRbg^[կm"zvz;n/ 0G| *.||[’g6\tϵ~||kIv$u ?ݦDN/H?fm: okKq 5}g_(<@-8ƿ.}p$̠0ٻޟn*]JOo3֏4ާm|rE m7_.wv'.o&H9b>* G÷|nccj~2Ӣ3&R9Ʈm8oZ?5m|g|zA]vKc${_h< e˒X=5?irN(Sui+u8*?M`;kK ^]N;262qqM~ W5zi:,:H%g|6@KB䎵f٦*-Uՙn]H/ğ 1Zl.p;5 ~"GxWZY%DSm]?<\xX֬n, 09oO?t_ ͭcx@u5[7Ŗxrrr0.BFkkǚkm'=,1.&nnswa\U oS 09Ra5܎NAF<2ʵJ{U`EJRɷzԡUrJ:ԦLKɩVV#Jqr2RԺm:7zV R q*$\4ԈZ247 P-ҥ6(sz$TRY('4Ƙn9 Pr*CqR*ݩ.G& )&I>qOY;U|jrz6O5!pW8ra& Hqcǽ( T,ޔM17bM;$TmHɧ+q81I$X)jjMRL9.hg֑Ra=XHPe$w53 ~:j?|-U'5Y;P^?5mf1''MH Fy5ʣgӊ-o ,X'$*ʛ 1"wY"Fineu/ǑIEw9wڄ2V\(^P[iƘ!;%j$InSLTk0*wyp8țV杌Ve&JsnuPJ$ $֪&7!MwW_ǩ~x|E|Ihh'׊Y95^ծr=j];;R,j߇4ӻN w/($ƾMB|>q ?mRO2yN^HVV<=+ yi(-o;*Sir%1frqIHK5I z,`b \R(Dɒ 玢9Ȫ1LJ ֵW>'#Utg ƈA9&9܉ 5N6W_.刺\yFPFkVzwǯ i1[(T0*dxDqǦ0O$i"m4N濨!8/Fm˰ӜRsFqҼGԇSWži iFkJQ&nmO~)^,F2c9"=5:Dlt|  ?-  zWoC-:ħ2jS:wTҥ)JYUaQ/x;~£wuڤ8#>ֿCb\|i:_yͰ75RPgO5I?κty5*J#hFW3=ICYO 3Hל|X&-.%-vR"pXl)S/6aFyR:h44vsXeb1_ O(tkOZ 0+?? o=̋'Hsٳχ+642Ys=[%53穪?%|38Ho@3潣B_uic5[*Y?nx.r!n 9i?fƟ݆izU'&G-ΙR^?|cm۟ I09*W g6Ju̾">~my?XDbe$O_> 6w|Cow4'w@(Ku=\DӦ=lzR=)>(^L 7E*?a+=NYj {>|hӬ]:CƌY~r\EtxC Kž >[j$8>kqInBWe))J6J56m8uv>i8 3H1WcbF "u m$2l&e¿_ϫ}̶Hִ]Z&=ۛ>NYpv) {6,;K!=N[jοx3_Z/3zn#m(I?'Z]^YYE;l 8qupWGFN-=m{a2_B Ȼ9Q ~~_ u |';o+99u"VT8ɏoQ2[Ќ}ziœxFn $q\\0ß.b5 +8b@͐g 5MK֭w5ԉ&333c8f 6:墪vAtk])b~|1u^%B:A#⿃~ּ ܷ \dc[~-|_L!f؀1V،\֦4%R/Cb+=Jo;ŗ6˸+p͵}3 sƞ'_.m9 िn$X [`Bkumԣ7!aʪ̰WOn~W~(I tR(f 29smoZh^ [vla]$-~]?(|P ;{h D>_,(<A+)Pi=qi߅hG#,01$o>pO&1\gXq_6Oi&E\##ףWMS]L%lsƒkԫ4t'~HJJ=ko _% 9W77][TүNԥeHII|5~]OEޱ5ݝʼ@ccJ% <(?_Nڿ%g'\* vmm t>5}pim*KHBSgv:򡐦W8tW|J?<+Wòxo¬m#n̄I&?=xb[y)~ʚSYw|@xsk8'nCV3Npwт8˞ڞ'3^8[cxkX*[-sXt/Y C-xl5R,6f*z <+KEomIױI8~ :߫yoKW}]^t^JKI<Ğ{-%MǩJw d]&6mMڽV1{fPp*B+(8Vo.<%=NHkÙMswuJ@)R:W~Oa$­@nmTkC JJ6mȬD}xsLgX֨OG)aҡTMly5X5 oZaVN"hBdA#ML/Т\QryQG\sM1Rv.S~ ҷJPpj$W,Y WV8 7͊!bs`jȢS=E?ZStۍ85dNAPx5vܴS S xm$o®@qMRw`rlsN3`{T|J,152˕._PJV$-VL bA)6Z, TEsڧGi-ʝiL;Urr9Nz8-F@2ȣTb*i4j`P`T\W-#L\Ҩ/ZV0zSҐ''5(`UQ <1 MP+@mUrzՎzT 1C@KTԥ8޵w,38!t})6`qAw%R8=*=H]❜Ut$RSJ52)7 p5v 8W⁃J ,-G79"֥s!f#2$ݑB~@w2Nk߇"gu=HVW`xT-+9GQ? OuHv22H=*kWưx,YjdGQ^L&抐'1E#YdEcJnu" "xX  d\DW6GjyqK@KVݑD=NgjJ#IHXD&eGz2"R8iTp]Ú],mg(B"2F2MfJpMî5_Ca|G.Ӵ|bg A8+%>k71=<^$.XdϬI 9SֿoNQ[@^ ]УNaQrS=ZG.o` e ǝjZ<|zI H⿯Ilmͼ7?覆3Xu\5 Y܏ͫC:b)4#׎~"1Mcudeu=CyZu 0in( V^ g%푏E#?G[ 5_^kHH1F?zT;-=J)Xn-cl S[Nq_ਯhguoKb7C+o/>;Ëkg.?&v|U,|g]Nı_H('9cxO{?'VkNKV㴐bEBnʾj/I6eylM'9{Kcd}ZmH.9ᴕel|N9~=Bk7(rI#axWċF׮ mA@=k/Q |$m쮴ieX:*PuB)8i:u5aߴ^!Y<{rkfms]̽bY[_[<[Ƀ C~|3NAҼ=xF V;|& -Ӊ?G!MK׎5CLdxs 3]6MNiF=;(|ew/ŝOW)oH u}|F-9F1'}iEԕG |,Ɣ)E>!q\B}yG99zYW̶ 2,^M^K{\E*7!5Zi,VU4ծsGm)ϡySW[8,Diߙ\|(>xEu QHvcܱ[Þτ-Z:zi9X x-`[{u[ۦGEQ_ïZǃtkSV>WO,)ksmGcώD>-vX,@Fdν:sTY#/k EꖭN6rx޿0|A~>eDRvLu~ƟDO5 :T#ボgigX$JOW ֶ޴9¤r69n5KI?\Zo2$B<ҿ/d~--bY("|{sm5뗒l]լ|bRJe݂ĻDr`1JޔȕmcnJWuxl vnq^g'Ŀs ^m64[U1+ub[ny_s铟t0`9+R+~՞״7}UU&H#x¿Lo:1}/;!L'_혿uuO>)Έ׀q+mov|9kie`Fa 2S5+Gc|_= z>;/hᐔ(fui .g~+;&uxO[˝-Ug~~_~|P> m8& ~4T\C3;kq"zd-rTJ7MmxW}G%wVfM)O\C QyjH L@4`ET'p0-RSҔ~x6MT sVؚ-/Jz uTS 2e95cU#ai?i5bw G4ҨԪۇ4(691Nq+TREV(YQ6I5(b*bƥ^;杅aH4д8Z:3jpX6qSwLT A"qOBZ. jSvEݞԫf8e"O.j'8j%@2@)¤V[ ~p*r w2irj@.Uw"ŐpyuTɥ=i93N$3QdPq֩1-ڂ20*"Nx8ly/A%M2B{PqoϤvNb{^ ~4?kkgF"Dn:ם߼OgWc=+Nz֍r YNrr=r3nXgV CV˖Z4 [J/uQ\tF7Fz0{#yEdppMCJzJh2՟ujٟȪRf Z$՛4%NOJ%UYb끕}+HɓLyՏ|lb1[Ӡ ~qU.9XK*ywgtk2*0=љ8\cդ4^BU3p)[n"bN/)daT(8=+9W6#%lz*!Ve֚zS ێbm!ןPg/ӵm進ץdD+=e5}l]eӑLF^*vgz\{tˣi)=qw)>7%,"ݴbR;S_; X$5QLRV?%M;#w1ЭOAf_c@?;M{Ylө@󎱇^aIQx;UgeUA88 7.YdWE)hZ,]ϊ/;Z Z9^6`rzgֿ;e] azVlq,M:A뜊˕eߠ]Э'n~YU*||4[7<7Im,9F?i3-wqedg? oUƗzI,}ߥxFOhڤc88+WmKIFZ{Ɩ,,T'ߵ›n4P0dC1WkJkb':'vs$:2CVPI94rR_ |q13_K~ҟo E_:o ҳ2N}_zSIhBU|[Y^| tѯ|COZ@Y(?/iem˩5<S)j7Xy BB;c5ce/*hnxK/Jkr|Wy G JfƔP1cS{e&ܧ.x*]/ b]Cfp7&a|/OIiHex_[ boL.-n{޺O6*?:xY-mD߉ O\Dh7; 7~iM`2u*?]xswą oF7͡8UO̝s E\h/H=y7~.xRjO}o5ڧ$0nٗ]r{&S]hŖW-$*:xYʌ'#땠~:|4 'lJC nb\A0$Sa؃_ȧ5CR֭nq%`wcK?hv2c{h*f57 iI;pxW~')^CjDSLg⭙oD@r8fw^ 474+{Gʙ<_Pt]|TRI-Pp lmb⩴}U|_3W?+;Ks ߷>WK ~A,2TxrG?~|v߀x&H"OG3FPnONjiԴQ.jR qoZzk9eq |'G/ hi)PcPcSX"馪jk)?>|i ,44T3! !>"ռM Gu;呖#9sӊ%QJ棫|_9~*Wt[YmgO'dYؐ PIֿvҟ|M3^(񭆛-!tFWNf|NFRҭ,к4va[AJև?LSD|SGYEMwLξUh?grM PK.G $_əLx%y+ {⦓WQܒm WU߲]|=yshrg>{J^E}KZ?r.nbO\q+:GZ֖AAd+F__ӑulP&}ެkˡyǛzׂ#x>yZHPqmEӉprMO (" (.'!2uR'UxG#5c,#"sOd$k42]hF\VlmS$TkvϵXguKL\!Ne92Uw݂p*pÊSxXk85Y3*P8L͜"Gzv'ONf ,1VJYpjK H׺P82s)>gN2!kƌz\E]yz/ CsZ)\\ ^⫗R(ȪQ ;"OX[$W TJʶbw4V  sXԉWm4en1Ԓ&BGJ$U WT^{JI)UNw]@<ԣR,1OGr+$GبH99ii1fڬFF1] c}kqT)VAұ{r Ԋ„`&]YGJ6?|xv*&QFOSO$ 2d;>:0*@[)dRqȫ5E4JjUU`Nߞ*I,EH*À*{ɢmئ5rpjAg 'ALb0#pH R#ciZL)0٨'eD0֤$(j7Z2Ea]0)(`Rg@1Jئ#băVIbR6*9 LV/SyUԀ1LeVAU PާV9H6%ě$)p5u~'a58pHeMHȪm7U<Ѕbf@7! hQ(lFCqN/4!ÃN,皍zRu8rY8e;H5U)C׆o-c*:v5ԗ=/P\G OC.G⟈|+CbV@0IXzkwG./]^/RbOW]j1ANMy">ۊ(,oh .ܮ:X\)b\uTG:|50TIrqqNja;/pA6_(ydG*5jAsPJj n[={VŘcc]Q˞5"HUJH7: ӽ&2Q''Si0yctkvlJJ"< QZk6Gi?~$ޡٜsVn yo(;W5og5o"[F*&aTHhh)CDF80=[5/OHܯĖNeϙ2=IjKy4RV <5@ԣ?Ļzjv#ъ慻QN~z$k1O~dzpõ{g??tYm!-X?CHKa\{s [$w9$Wxe]1- 8kSE4||=SWD:i&H3"M]f=s DY^MP3%cpg랃q"[ߴ{v^mޑ;%U _ƭfTyxq4B`b wAUZ)d(tY_@ã(~'|IH4O )t^,hx5XIueDnt}wE[~=6]au#Ҿ 'ưtbßT)RV6V"|*ďYׄm[x<@ e?^#_JՎw8+f<>P,v5&NFDD~Z &q=0f>?ߴgÿ~k v` x<+g+]Js ZuiG $TW{nxzf-5Pz,30?oԾ;;`HQ@P'#asjvh|'}#M_%nMWI-1X6`5)+Ƥby{`+o/5 .2'pPǷ}qSAV^I/rYmzs_(Mo)FW #ӱcm m៊6}9aUAwʴ>'^Dе&38My$=+_[ x{9m%Ke!RL".dڦ|5-+ZQPq 6`gcֿ`>||~;:b-1d9ҸITw^hɤOwasTuu$2$T/S5Uzg|%vv}Hoo[Sg&Sn58'jɕn!&ᑒq_ٛ?5?Rkk✺a"}% tҢ2_E`Wv0 '(9bd#׍I޽s/^8ۨkMN;#.VuaޠX̍Mztg6DPDwS,^MXw_Z+Uvb:SLa EO"QX(;*:xPX8_0ݞF1Jw5ghݠ>SD.:`c9yсT R6&K$rGjShr83Ңj XjM˖k[hCfF]YYZO1(~)us:lзj80+pgq"-ñȨÚ5'Ҫ*A6 ccj-[st/zjdu5^<եRU0Tc"k[=KsdQ3-+95aZ8OݷUzw5X&.=i#PFH↉WLɐҧl(A#8RsҴ zj)U̜jUryk3) qTpdJx*ғZ,0V`M8⡍=:Rs lu9)T,vj[0|ii)A R0njPxNqQ!qq%QsR" a~+TQq%皔zUH/SQpC@юURwհyRN0*/7h995rv'"樁&OJ1CsSHUd$X heǽ'sN1885R# H*TArELWwNm뚥qS fZ V/UcIGfR@P$ЎT2TnSe9inix#8nd%=sRDLy3U[G/ϟRpA&+a=*{6~{U <Cҗ!wcjF=k1ִ-*2EKCepI 6[ӊc-uڟ60 /*Vsy24EANEzH~=Xyo-ѳAph^P1E=Fx|ڴ߳G"~V~?lgMdg[M^·:no4k4K 襅mXW$ezw?:fmrdm+`܊fHfwK=*^m HS^cE~:"y<ۙs5.#Ϲn~x|7ԟE-ܠvfa s^z~ztE_]KO@Iuϊ|aj7ԑs&TeOşOuqwkje܍DCްNՂGc?AϤ ~-NM#8P=>QM/>ѥ""YI~8'{'W 7:ͿS "#kֺbk~m~^oPݒN*!Y$3q🎟t;c◄/b-$|7 oo>* ؋⿄~*h:,K"O57$nc_2DP1Za]gMY_>IzlSz>†@pG__PQku{ڤ"Xrcõ/>&ohwb{NGW1`NJ'J+YxG)[8P'z䣊u)*]tM Q4}V`TO?I`'޵ǩѷ`bs)ecE22::f+c:ђW59*xמj\L"?.MLOJ {RQFAOq@rw[5v,&U]W c裊/JcSҸg^p}^ݴLp3/;ź̏gIrB=:U;2085%Th ݹ$=*gb~zϼǃRTJe'٪$IׁU.pÁMIxU)^ jߐ9ZY6(2)TlYU&,h{T)UVs v}SXL2\1e"]֜ Ҝ6?*3%*roD|jRK]29\+F.2텎jt - Vm2⑷yzVTQ'K3P3gxsCϭIxp:&Mˑ1fΈWp'eK`֓js\J8⴦v5 xL-?UFGkZդ"K_$_JQxjOHnXlҺ[%wk`+iN kx:̐NW Rsm4/&ԯ[dQH x`t5|5[ſ<7޷HI|)WDim|1k _S_|~F"L] $IWKZccci XmPA~wU1G `8!T*8aSuGS,4%d&BWK ?7zbbK75 J}':u&Ѥ[31m_nǓk!+c %F|b@8č_ @ V\WrQƤoY۴d?tW14 zb˥K|;mФ>7x&u7u3_| [xI-c.sxd EQr*/~ v۞$ `;:WӺlj~6xW%>4{{–+=͆/NXhYw17 iޫiLw Z+[gBܮ##"{ ?RFRЬn6_T_x ixbD}8VwcJ~X qR6 1_P~džhxO2agldel2s_ڷoGvwYdi ҭT/y\YȐQWo%ozt{x!F̃2{ =Y[r9FW+<ϡKeJXe-6+Vj͜Gxkj=7HIT)vim~)DukYn||U>W oU%h'ECӊ?-{xngFti\|Ǩk̩ntQ[M4f8[73fIO}яbUV24 6lCPyda6p+9k6Dyl{$1uਟ :MN3䕒6Ex7> |A|M9_P9y'ۃڽSO &dW/uy] x ?gIjп]tN2j))RB\hzgi0x̵58tm?g'+o!~v: ;2&4C(/XAqnXQk(]Ah~>X./[e$a)s6Ԃ~GhW_'83M7uL*ׁj~8thDpxʆǡ O Wgl}?iR DԨBZE"+[rZvBҴZ.vbmx3äH($a3ta"c坥69Ȁj.7 H埜✨^IBh)s޳iEV66uu9bK1' b0b3 ;,5;"F 4ͼG~^Lj6 <|ZqYP'"?C <=H\DcOn[ go,c؇T( h F:E(!8jn 0W3ZZL*̑y:('-LjOZ.9LUX g3>⾡9/ZWu@58߶,FzTj&\4X"ʀ:SqU:Vp5,lqUBxN0ϥA\LSJA!i `EVIN*p*(b0aUHqS/K /i14YW歃U]bt py(*;Y8 nvjBԚ<axZ uCQ-2eXUTRUD$S gF=$ul(aN5{TF(Rl"zj2:<\I=ir2*Ozx;*D0iIPE9&ɍ3R;jhQ*=饈Qz]?/JhE#J3׭hK Q&N1MWȣC5.sPb7 g|R?Zv)1L)_^Aae=Äؓ݁#+|Af$qHQR#Aqu]N}I;Mt;cį7v 8u_HgeA3^ǩ\ׯʩn,ƚ s/ .fzDAfW`+.y66tFHk"XVLpENgys6*d$ uƘŒ߄y6-FE@ҶҠ=ir*.b<z<.NwT&Bd杛6˂^*Ŏ{TIpU ?$T~c6U/hM"]۱M\K!cڮT W&gmiAd=pB5?g97 q_&/6* s_?SԮ~ hhR!yWns~)^g*tPYF0x`G#Eze5ta3u#h}1^K?_Y9|3os+6vS9/ ~ߵ>ZNܭj^)-6_hv*ἜN1\$(?GK~ξ&͛C&D~ᚯ#hkn$WE67"=Qobu5NWב+<ԞWWwU7~(vm1nvȯxsKvc/*BF¾)b6~)O -F:p3]sqUy?J/ ׺j?XHӮz):ؤ<5necoKޤJGh>>J8tݘ#$I<O/:~(ׄ=Gƺ&B3 0ȯ ɠ4{Hث+̕-M%VzW|RoW][wN>*<13S8F@>;Ѿ tKw|,ҿ_ޠQn/.- `ϹZingV16>׿_xk6w0~zͅ812sjπZK=-#I*A"cO]_a ?|H^A}Up*-"a NPȉ,g_o>* 5\)=#=iz,wv70, _x&2Yks]? Yj%JTMwmZE=!M+uu-*+Zm֓zzGu A7+ii7r^GMq _jK-Kg>φI-q|[im{+e  \Ƣօ֧s⇋'i>%֞Ӻ;`r͒z턟|_O?~&ܠ?xٶ}Sew}NUdGM'Qsޚ`DK$Q9,x䢼7Sr9;zǩV0_uϋ~.֑ŞL7_vW H/s|<Ԑ._S n0K55:Q쑏;|rykӽA*p> X-O[ %[±.N=Mu| I,fhqUs^'tr6wt4I$$#*rW>CQHY*^yG4Cc,5xmp Q$y6Zĵ82)}S0S4;S>̡w6חcl 669#FSF0zTLR7ZnQ Tʛ'B8j+&y] uZYgqS⮨N>fE9U5`mޢ"4U$kJHqrdT9歩\Ub=vT^i/tI Y1"Smp3֖7PdnwzU!r8gsU"*w۷'p)foՐ/qUQRT,L "KO`09T iUk6%)~䚵zsަGFylS2-N)GJb0mKEwzQ7;# T"oCYM|~nX+6֊DZ洒F=Qt9\A-ҏ \uqk$MIX/1AOZwcLD*!sR@OZcj)!z UNK9$m4/CZ[qLGwjF77&Py9ʎ*[+LׂD W!cK$SqaS[S!>u%S\A!N2+UF LAf<Ȭު<kʧt6p|V}ԻkU:_ i>6Ր羷=9q_-"*^?e-8x񉠊RFP¿hX8TEWDSz!㊐N^sl))(f.Ė_DF1 㺏#Vȸ([?w#>] .Zw3O?>k4`;2|)= o9;W c*<֋eW?k f*,Ar&v)d4'?wIu? ^M座¯h΍EW9vȪXZ.~/y0k^hW}O̟&WxZo5܋ 0~*24ZEZ#5}k$+ȬcQogءyvh[z>x?S4U]>n+osO(UǼgi| d9 b4 Z1}ʪ0 X`_-[ mYw0_3u~P 3J[@+U̡J1^kk_ɷUU9lFns滿 ~ʿ;kMk[bJgl}OŚ0Fd wXݲ*FQ?>u_&GYɡVX5¯6 ep13Qks8)q C=z[\\DIWixK=MjSnY#mMSKT0Wy0|W~z,bw?gS# tPkIu]SNU-ntl;{_$hZ0XT ϝcȏ <]x:jM4OLށֱ湸 ]k\ɝy?C_?Twb *_#~ o_Y.k[*:@?1ctaq>R~.|F1'D`Xl׿x;j֯^q+Gۿ~ϫ#C: $,ڿ>ji~]<{oqSf  9x|$ Q{_Iiy t㞵SR0k:Ga5Iܐfj hͫQ>uOψno/m8]<[,z`HUCi@/4 nCF֦ ]Y8=C 5߈gB"3:g,mmʈ*p +OeOC̲GjIM7<3 %Э|D !`W> MR5Ig~ǝjٯI_J_)#ϋ-NF*Ѹ "`_hx0I]xQDWwt\m'OZ_𦁑ilQc)u=M["Q?ׄ Oy?{xL?{9846mݑ{SR @5*xoš~"k^F/nd@k__Ti,~k&׾NWG%Wga#dE*6F:*f_'}ew9Bۂq|r@U]2Nzׁ]{YYa6T/j袕rzW/(.;u*\gM&ɔ1U): `F RIdx&z>d}V}Ȏg2&vX94Ȭ9Yd1dj!$=T|Ƥ֔oBlT] B/#31֔/֤;F浵@rth Z#ͮ5@*d㚬qޟbˀs&=ɢ$]b3)[S,N8SJK)r~ 1=)#|-==KC<R6H5]wU`W($Q0 fx5^I*L499j~@SV`?89ҡܚOB.$`qT1Tҟ9Qa@ j( J89REFsLpT|j3xtcWDbrÚW 8'V[S"5]x<\eګQd4ANSqOzT G~)dUZi&G0M[E㊪ qMcڑi7 ذ83PiJV@&zPaX#Ei[O0IBaU[5K+V#T`.P4֫;A5aSTx4{b⹩c{C t9ZH,5cɡ "lWU#&*;4$i$tRP֊(V/J*5| SBE;c?vMW ڟ'f_JDy&~*]M$C=yYKԠ)۾n"D ,y5Rq dno)Y2Ƴ%Ċ2qJ|*:9ZE\cȬ]VSaSk1 WBhWrTR]2 w,0$4r*坷7aOZ$CQĹ&By ٢sY\nM]=*);VJ*pثY5xفnslcRF e*d:œbԪIṫ2JAɥc_j1gLT8~t\'AM x/޳㸛vekA&]pDI.؉*z԰pK)yP9]j"Q} $OBs]*ˎ@kQ,s>^Aj}BI_:8.O/~4iS[^I#]s⢺j(ϚH]a|QYYϫ,+;nZwgi0}A@&EE :5:xd73`隯H< u.5]bL5(b%קGCږ_y\|)Cύ"k.xTSWXLqE"OQ=LVsڈef˝ֿ ?<_?3VwbHW܍v濛o(O?s.~N+˩N(qZvg;+WNb ޽Nrr+s< W;p~5h!;®z6=R@\0o5ScEPJ}֜pxd)pY6b6)e Pt< [,@gV;E(NjI"nS+5i'۞:I %`r)K; \Uj},<Z<_(~NhtaU/7*b2*8#x`C8-bł`3կ&/jvKj_-#E` *ˊ֭ O89@ZpiU~U?;Uuo; YGHnkK1nZ-Ep*LyJ(܀Eaܱ[3:'a TC*)%rxTw%V$S4 jGNOnz n5 sɧ8>:Xxx_QZvu+jsE9]jf^܂}cbۺ֔^9YOZw+⯎Fxra`-tmO說[ݨ?AБJ4:)bٯ{^],kw#$srVdfB*0hQMGulT.@ r*4JpWztdRKQHu3%m3_oI_ z>ϖ e][U`M$̚ϊEk#y^Z;sl0|ބw3hP^zDAjgK-ZN:]zp=c&A՝l@3Ҧy sѥL4P.ɜT+qt5Rg\뎃rzF m⩒qȩCޮ-:|py<棒GIHG<Yɧ ǥ lRH7 Ojn }WCmaȄ1S#'$йլsN$*1USS1dE`U|bػzՐnE@9+186x'sX5KdOzz(5g@" B>J|'#L IJj\ h本O֣wMO!$R&@VGιj&!fJxLҐ3zT0֤W rjM+FZjL 6*ȓmQX|VwaU2[;8i< M[3R:t*ldsZESZP4%(RUsS3LV,IHFdPpO&zw$J$#6TדNEqOj"?7&Bhy9ORGZa8;u݉,59<6wIb,Ҕ(SVb?GS݄pAZs_m~e &WQ7^Ej/VM~'2d;X#p{&ZJ$ňU_ ⡎ʀ-ɐNHXsn'=kܸ5c&"L,jN޴sXxA]ŇqcfrI%OvҨFd ckcRq)aMS M[`*Xʣ޴UTO,^v4 @N>L5T9oN}MXXQNÒ*TcO[#;sVq&\jYhO8F31UsܖY=5&q櫉6XRN*d2pK0d9*wm@)k-Ɖ)cX`UH*+zqWs7"K=w(P6#`!@{d  F5LtykY 0u*=t-亞!.:e6ak4t~b5$͑5wָziҼiqW^N+KM8#d V?|])I=+3JSc Gk֏hJO1ʌ+.r#=X*З7-ϧ&ʤu:{=o$n4Z1Fz Tw1[:ZaF;HeH2ZN֒C#'Z$GCJmJZ&e;BZ^9sڐ2X󚿪^C=~[eWV`bⶍkrR/̤+SmxB0P\A?uA5ZbF6s Z6+-NԹ-jJdqRs֥cjFV&XHI^Ǭ~0uJ?]$=+5s^޾*)gF2NMDܚqPfR<\6Z\\*?Qغ;lϞ&F֮sְà;/Кg*jǥO-rWL8#!ԏ4pkXu-J2+:|Ʒ@n<ܙGox>?BtV#i[UԳZO, E R<{8tIO3l {3uYqzTܭ~&%ռVV!qB G(0Oi-dg~)7Q+3LM ii XڡqS7 -ؑUe| TgZzϟ|5Z,T9B& w'ϫ:ѿg Wf<{4+䷌Ga}59B* W@XZ|NgۂUOVUw k >\vs&םRgDۆR8oP@'XZ2- 3wQ,wA֢u ]ՕjB Q?VwlF7g j3u{׸Zˇ%#aJ,xC= ֚01vZ$`Y"1֞bjF]8 *&ҲN_)W5aN&2,!y=*$"VsBV/W!jD<@C4fb۰99q3ldc r qNcԨ QU3)0zըҟUlHuLU1NBUt ̓An*=ǭ&7VDl*mQ :I qHKKWv*5[9`SikZ ;ot:Ը"VRj\Wvօsx;Gj/aUl `r:ӱRM3PT$M<oVA ~~?4inwwٹ2\@&3܁_{ZSE%"uaA*Oswt~!~U=A UqW?o-K3?q!i8~޵k8\"{ JϛtW1{$c=+\bBڲ6S9wQ\/5ѵmt *Dɘ>Kc3Isk]> '[E " i rSqI$#"ʎ}g?tsW,旖9&+$!&0J ._ 4N MG$px6ZI^F+#9sc]aLէm͓ȨЙydq@vN}j`ad[rí(|K@Z=inb:w@p=j!6g 2q6tʍњl ]Ỏv,4F:O>y.o^/H;?Jy.8U- ' q?` uOڏIQJɐE}2DTp FRH߾\jQ3_:3p8R!U gSL+H>1j)>_܃F-ՁAⵖKUt9aPo=i[3U䵁̊~{o^['|g;:s؜WL]bzZoitlYSxCDNpȭxuQ+{0xH`d{kGI -!ʹ {׫4rT5'p)) xso(sxO{ҙ+|=Re}UCqjΒVHYqɯQHQ`hW$utfWT|Cc84ϭ}#>NdN}b]R~B5<96x7W(ѹ2jW -Y֔X|:,D٬%׏B24{Ty.Ln˗GwW3U77"BS/*Wx'EӒI.(5j+N4ϗ̪'=12ܟ `q+t#̢nLqg<5M+,$Tαu[> Et8ǭIK*Ѐ:]?[YG 28ju=R-B*:mk# ֶ?;va YiָiջQ+^<iEuナjXZH)tfTrnRGҞ۽Dϵ=8"r9RFj:Sѯ1dU_0^rϚPq=c)U,N\Fcx;0G< {z|֑7&f\Ė51Zo%zWU6ț5RHF~+Cɞ_ґ*=Đ\AMGR(qGA@5C9TAѪcc#EJH2һgR>${vN*hРr Euy4zЌ *u>XBx#_|zAL+J 4E bA@Prphݱ8%{sN"=渙m\J$CO*-+̒q?1FGъϓoJZv +<:oS89Lۏ=*&_k8[cf3Orb#n1R#,c W*{SwX-uRjGf][˔?`Pqk-Hf'S}qe>-c\5[Z5s|w+׭1 N.-[|kOӃ[4l]Y4`_7cR!> áZO \Dŧ+"uH=H4RM9Z:>u;y^UnI{4xM]o۾mn=0¬dҾ#MGt3x5f/x (kϫSzS+M Wp@M?Ҍ ]n>>)Hx~5܁MPZ|_k'־{xZukdo¹%39z3(4%2k37V9r~9OYli“uݲ=5kazmπm`[JCws>Z9TzX*mM']iZl˗4<GȈ>+.C-{GbUfeIVEb[ɺ˞Im";^6V^'5.%erj75șS(6MR:i8^+㊰u)y9n=Z>?gR?wRLLz2aAsvI3^Y~5UF'W?ZajQ9Zcޫ^i2+VЍ ĸf*noF:q[q"ʎ6lIϔhWU#e#39汒gdjk/˓P$(s~ZV_=9 ƞOj oRHs9My\TewR9Ȩ:S9#ƙٙr>lΛR9 *ƭT|՘vjM]q֙qNQ{C&I+Q8 AJ0Rr-SQU4D$ԛDִ(;1!^Z/^LMdB@}+TRL PRe@^Jr5 dt\j.K⫌(''47 =jYE& E7ɩw)ր5R$ irwJY9/,Ǧ?,cQpV/n'@M>H`튎NӃ VM=%2xV ̫W) КDF+%èK `պ!S@QKPpCdX֫xA4֩|9Vs9Dh/k~x[ ᨴ=kuM#*Gf)Sq^ckuc~(hkka$xMjI(}zyeDz>S6Ⱦțv}%[~qo\>^ OSWuGy dSZ3ھ˿g;Ɉ⹻bc'סK2# 4} {3jan ?_ı1:K9U愺}N67 _j3@5w/X}@Z{3ymxrBץxcmC$"W-1Y#aTօZ bE蠐+ E[ua)(OӔ[YD#_n7-`/UNh.SƲo'. 1c5ӣ>kbr~(LøxYN;nF3^q \%\=Z\]Qk$}mowl/X}{Cm_FȯQbVhck [cѥ)nEqi|3_ūj0^HZ;l $NOs爁Sھa⿋-2ϏZصϫF@G\58zz.y39#b^}mC?7~CWLkx,Gq5t)'+>}JeR=fE_ ] Gz5Er>S)lHE~7p+/ ~'ָ*dk/<8#Y Y:HW`PkY >Ls5`)__'hbLbA}]ȉkϥrwN:# UGTZBqQ÷9[ԑ}TUg;V*':=ws5 x|ie3}*4b',Ub\esޕ#XdN9ޗ+H 2ard&yr`zT-qU+VsCL# *i;:Щh`%SN08"HAzFUqށ&4p#TfJv-4::N|3H87I$ˏz=V٨lysץ)⧐,ɻkr*J`v繥5Q",֣V&q\V.ߺ)Yg&r&#)5(L*950mFV nb,֦>1NB$SY1U#lr*Q&I4c$朜qPYF@=D,|R(c n)=J%BHq< p8+zpLNT!1R EiIo @⧊U&,le5VE3< A4ɒ5,,TҪ%*Y5ιri1$C7+)bwLx`2i fX6cզ9)Nbqe\hZAp ;IGҿ%*վxtVn,o7I Cƫ}m’cʼT8|i^j캎p׳sl{ "vz sZ<4u,w+23,!QLMF]/ gCO{rkÉdMOZBEV`MVlZ 2iEkFzմ.֚*&z* @q["ݷK}(2z12elj-֨kȬ:BWmv0nƦhrZ#lq+6\Z5QFagm8#]CϩՄCԚ1Gox(_Kjھy/`*9<+9ԥ)}k\<[L,"X2~f5QZ\1{CQUWps_x{OtZ+8t;y7Nwmh:DO,4e'UhsE?m4WQݝ3F}0:ӊMT051 9Vbp@3ޑڞ9H[*ϡ  z=xZLeJdo^֓x zLQ8.4{~95nǩ*3Y^]4]*.%L']-#1Q\mHkJ5O>[?\|\ʸ[CIr}HxdO*pÿ[,&i2A-}d=:m̊Q]pNς$F١t[%fv1qgP`^x ·j|AM> V[H.M:@M(I)r=Nk꫟|sw?9tW =ɮБ< 6nj2B{W]X]\/DIQ79j1Q'1qixv3TеK+kp~"k35sjIk _u9S<걬_peYHh1Au͆B ޵i!h~#l*8ժilȖ"MdzMƗ20(𥮡 cǭy3r jYxU JJQR.ѯMQO 혉AڲfЧ`}YMnc5爦{S =1NtH*ry7M#TZr]GT ;@ZX8>溍f*WS<1j##FZyU9t;!ՏSYS]쫏m[x$Wlz\7VOҸ*4CХ՗Sլ~* 8=ɮH@IĄոիp=ԓg~"kR=nRwBm͜V*_]ҵAR%#cւDLQU֜ȗr2jX74_^jU@:RIT{w\VyX-XT|TqYzѓSṨD䪻~j0j2ӊ/[Ŗ8 h jHZ&KEp4+S7b|zS@*tp!$O.KÃHT4զ/JEw54|̄ հv{..EeԖ7gV UHKeI G5!1YRT}+93%d8뚉@9*0qPYޟT $*~j*_4nJF ,gAD_&bI'd9iNM}a1nj)Ig&9DMBK"`Ue۞l2ⲵ:ǿn6x0|9ɯX.#Bv=+Ƽ_vMdꦬptRȓHc#LLMn;Ac3‘5 -kإ&%ϧb}]4(YMk'#@Q Wy:jhNdx'oZ7)6'vcHSr)&J<ד-!ޓ(gqhGwo@},UoKUB" |Oen ]\RS6+oQw6Q W;/_w}}TWjpp:TBg$$g޹߂}U qTB|Pd q >5=hpk9'I<M^C?eM,Z]X-S\L9tgn_>]eh)4 z3` mhTs[{D۱YRl3_o|g'_ܥPIA?im~[yeHa##5^q=F>_,]9s%15a.+ج3屙n\#s\=+dA6(rţЁ(ʊU~1R;0*8"o#"$PG!\)V۴m5S1ؓHC5I2%PiG֞+i=+VhlO9NS8rO@kbCtly;YDGú[ty׶{Vri nN<C\k@@5/Sc>v.pn[;?95\1pUzp-xcҶu6 ŝrKcգIN#0  rjyXڱlP"q?5#"FoG8b9"oZTe9CcJ|~UiR;7ʠ bDY0[.ǷJph)׽UeU߭\i[bÈ&+Z WVV28< x$z*H y67~ԹSu+^ٮuڇj;vb~iAόJ|⹣w);Ҵwq N2+An8cڹxRbҾq^¢BY_ nG$׋wz8JS~t7f?4-y0oq8*JZyw(]F8ⵌ\uem=~Sv<:?`ZH|_ <^=kPK2d"6?~G>yEsH8 V*k\ןmKr\V?.GQ9-3Dk/֣n$R+o4҇Nu 0$z/\p[@S;'?x~u)>aןp?pPpX׽;84N*]T^["95ͮ Nԏz9' hflS/nBhFi[H8`isHjdSNX-A*^rJۉ`؉BP:UO֭SFMϘ넉EHǎ)EM; H ;ys3ː p5T^] ^DYhh37wV[X\fӚ"D85Gb$[,@MQMi3ҔH뛜Wx'W }L=D oyJqDdzd'́UYʞx:T(Ň4vsG0XHrz(+z)Ӛ0rjT3AḬXbH< UJPkBUJT^&DZ&y/FNza\zVrGJ~RAd1:VrHdzR.j|/QT ĬSQ\uW c4&[ޔ¤(VvNa` pi4N/Q95&#x5*$Rj17-SwSÚ֪ Bgǧ_ڞsO]ieb_|P-|4y1ߚ~=Lj0TigrۏJ,zFCTA'3Ռ_0zI Tzș(ةg\mr=f$'kzTuֲHؑ6V{c(i'fm4~~0\Ǹ}*8(rsQ!\HsK!mۻVX2oSNHYjEv`TFEVxFG+՗85bkMŊ?#ih#p*BXt & iN3 @\2ys֤FK9}s A1P)O bZolmairD;RtI҃╘Tԛ+|u5iQM!e? PEj)j۸긡WH E8W8aKW$MNn슙ukbM'$m.uҤ]m IHʹuVcS-r\i7D3~)D5 Gnf_Qq#,zW5+H=AE[ҕEs?sVSXs@g7"R9H.s򰦐W҆E<)Ifm9J@+b*!bMɤPO& IZRc< fsy(jB;NDl; `R)۹Ȧ&TGVXfjZ82s]7rz zпg^3l>N>i#M~PQ>f-75Ka-E_Q%)3rzn u260+3-oj588sh *X9dB ҐGZe`U'Zl,ˑZ#aOzČUșZq4߶*a֞"Kc:crMVfظQ[s:[SX{c&DʹҫgW@8j NҁS DSH)JJqVV*®zU09Q*.7,z{Ү@FXt7B6)Ut8INjݍbI2pEKQk2?W( ]VgPi$kp*'?%|ZIqVrs\r:E7,~\[FgN&:7"d1ΎޔjN*H& g샓q^c./sqhvT~cR݁3RzN:Z/&M\d9E jbAy]3q|qlSt=sK ࡹ:ԯxҹbv$)uj 6ZsJzW24:QҬ-AsM(0Nǩ䈔Q}^Z$#'8 K2+S=GO1iȕzTs.5fdJ2;dQ د;7.>d-UMQ $7Jocjr񟑈2߾Z6>[.cAZu8;N3ZzVaCr2qk_'lAMdpqUw3HSN8b2su .bpǁR dSF39 F0 L>lsO;Dž|h2@vI32@qsmqCbD+!ldij㎔^Q"xM[\`S26ڮQ3ɩnZUzҥّ22;TA~Qb(m.~cS<:եr jW]H\Jن$⭧Ȩ@KaJOBK;o* Ԩ@cqH4G'&jg`Q+ 1PenBK|5NyBҕ4*"R޺{Pg#5ay8swM ڵ%\';hIn;g ˷Yg,޵om[Ox)nxRdF+ԲltR:MYhze@EItP1WOL֤,q})'7@ޜ$ɩ 0OJЄߎ#GSB`qP2\pi"IJ."li&㨧UR,5CRhԍҙܖVkxڅ8F*y1K^*2^:bNg&@z梖ER@+5<Ӳ,jõvF:f(O"qM *g-BSwX|6Å5bCκdMys8St+Py Q>r%SFaaS<)89ljW] TV3T*6Vn.,.mEVXn0Es O+3]JَulSSdBI1*1cZX،Jd%f3V TSSY+R1-N {*1lhQG|S#4LA9nm(Oz\2PxDd`=;Ud3uޓN۹sQRwmEo1jTZfO?zV!p iTβ@ `z],9y,WJqjMAs2&Tw8V0b5r)r9̙#qڜTn┗JشYRqUP`94I^ANEf]] ě^'ַB:ffYIFCc5/*I.³:4}"S1 C٪d*1BQKl.y} R"@H<Ո4NIxFs*8X޸¸g"V K1qRFFkt⚭m~GBUSX2k2dSmj<3V1(6~4}i &V 3C%HxҟbaޣⴌJR/+d.qȩ| rœ~kNSfrH3ɢg]Gvr1@5O Lw1YU̓DA8W~u?+5 S,f)qya0Mz !/k~nye"LMy2ZϨM866{-R_8Ut6=Tݡ-@#SwlJC݁E;W$P88Uey2*&0p*c dh4֣,&7m#ڳ 8YBuN9rמ#;Z[."!Tc]gaR?:I+ ȟP[o+ w׽J6Ft"6ܸ: سr;3\~ktκp*Z8q*TY0r5lj$2\laՈZFF٦:ffLxJd!i۽*nygY!NsK q72f89=) QpnNDݰ9+^HT bpr0MXc'O~ZNeV["I7 Wu&dte(v&u&Q3ՅXddW? Z*v6I'Yj?O}L~#"|`9Qz`Zh#c35p<)>Wխ qk '9ߋ D,w2^4 /]<]g/opg .B5yM*=;=c Wi=[(' 7 1䇤$ycBkH3DwS@l$h`Fy96 t%?udA&x !jS,iC=kq$qVPX"7Hc0Uh%q4@3;+I(w8<;zFEcޣk^R͞`VR!j@ĕy2M:Q `#dzR|"P œB =Gq] '&1! Ft>JDC̔յTaהt[)mQHmQ\ĜJS(M"NC+ +*j'< ,S 0>_{+?ͱG#Q;*vC$2:^Z$F$.Em|Yc+)-ZQcmo3;~x~Sp9s`;ul1݊$`π]VLy5|&ZYp9tK6YIGdd UkE`Զ+u #mc)98ikzOO 1)8n['wx+ܻn3W|޵& o>A.O]K*N?DZŌr+Z;֔F85}y'o_ߵKlS{.jh=̀kZ>8V;QU+۷?]FE=k[  ԍՓs&>[\Z8PMpq)[ݭ֟;)KrM=u(׃ָ\2V.Vuͨqk&J˜MHymd4x9+I|<>risE_P8_+5Ȥ951I]lwJycV⸡s"H pi:.'s#dx$x=kmVX98+mW<N5uJTFrc&sS-E3] cWvG=6p²cк'Ls,Fj8*\N)"!ƪi Aj8Z^v 򶬼Ҵ|{:Rjk$F8*qU3$zV[ՌCtDhdbU\ mZHLm9ܻ]:e|lE>&ː)Z78/R$fjqU,^ZQ1Z F0+Uv+Hpk՛ I5S8'+H-$h g$ƌ`Ek^QT;O+xlO r=95|7g~Z,M&Y'F$~}"޸;ijɎLt@kĭSaԝ bhh8^3KTH@NL`*^GtֲOjƧk&uY+'ٛ=V}2q8_i&kBc˙pd׹@[^ša ȅ{guWMDʽ^iNGZ IќU GzLqFr)K-zAx)#1IN@愬1Q4ka^3\ߊIm '_>'BQǯJыq{QZM=+޹m 1/<ȭ]\HQGxOڍ5D|fhx,HS94Xh 5gdS6@TqRFSdV`PԞPT'f\f '@iH|Ȩ/&u;A֫B"!81V9.EFKX`}jRo=C+֩14`q!)m 1^q9nj= q-ȓcaK02gM qwܓ՘Y j%4 ɫU^"2;u!z&Y,NOjcr(CEbEE#ĚtoL +x=0/׉d>qZJqg4uR9&s{qQ2zP?3PUaE:To*968v2[UryqNP3dTc85#P6zAUC9GEX!r)Q6MVoJȂ岮^ʿ)kG5G&8n sקN7G5o "B` ǝvͫ]|F%}쳁ֹaQI)X🏟ZL u`Z)R}|S O_WMKnƊI&K熿:'$]Un''Ҭמe!'V-sɯGSlʮ wqNfґeB]4*CϖKjTrQ\ G-1U)$ ؾ@j{cT\6zՐW9YZnzUXԩ i&Nekp+sQŒ_$*(欙X2i(2H9s,͜v[>W\T@0_aOCl݊Id( {9E֦x tS$pwPP~42Z:(:%UlVXX(V3j\E ;-g ̋-g=린%jPR+3cֵ2*n D`kZQ9]!(gVY <UrS:C-98|X_m^rv^Zh>7v!m(UcyAW'""=Q+熯_x2{Y;uk|9M9Mb)V#,m!iW9Dv6]rћFt?ݟ'4^*ى%m+tRL,oЋ8M ;HjͻYx3,d~bj=x5K<ѳ?v'Fď̓(x(Vf gؒ?J/LHJzWH?i|51^]~*iV =(Hb r0d;;i s)ZR9HL67W:dJWRg}1Nuoow[ܠt~4 o$aN@asjUU2.lRd(N$gSbHPGŠ9ǖ<4wr2 vޟ4+i#F܌X" 4M9V1@iͅzİ+DGsFe8G)nZ֥*|kZRLx#yUS\v 0,%)rkv϶yb`2i.4;&YdռfB26ؤ:;gO ʅAjZ{EWqУ`2. ;y*G_CAi\bsP[};?Z]jrZU^G<%fkCITq6c `29M[+ ҹ+Ҷuː-ZB{זwSe7V&>^cp)SڹY9 鶟!6%ֈ!J VrGe%;S[OPMA+YRj*S2G4^+e+ 5w4䐤R ԁ+E#Qf*xw&Ij iHNPsR04S`RfDЮH4bNs6 z$%Ӵ[k4ƼG];$~|^7b{ +޼9湏 XvE@_qώ?j&q1Guu/Sױ~Ѻī Bf'{֜힞{h?dcg VVn[jj.Tdd}N5\Nw>ݭkhbpk4(eUs8"EǓ1(=i\ R9W|s5Q3 dLıP 2c\jbhpFS=kMLr<U:"_[&S$7cٰ1;ztmn7gt>Ztq;(Tc"({Tk2dϸR1 gCc7!f: 'Lg_/`zJAu"GU}jѢ+2ǠaRL_|t>bCc☰P,8HR̥2S0ؼ  yI$aF5W?O?Z2ep1P$+NZ{i9m8VØ*;f1+-E*DBhz+d7Ojأ'$חhr 1z,*69hؙ/ir Gl3ֽ79[rp5k7͌rd!-di y!bZ"\q: 2vME&i,yۻё%$ɧ ( Wu+n^7c}FU=롆K˄~w@ШـOӖ0Lj0;T&Lrm0%-uVN4KcH ڝ#H00AY" V_wZY% EG nCƑgXp0ݫ6A=YSv5bݮ?LgAǥ^[͌qћ~<$˟h“&ga p+#ݻ=г#+G)hk mD24ٷ7õ$3OcoJ͒@+B90{IQnsi'zl%O>IY&c0zUpz ˅Ҙ朒PrkU#n98Fgo8֙sUe!z+5*x8N %i$یZJWНO9JaP>ٻZR% P eOfXN{T+"=iLzVI Q9=,w)D摻FԔ~^Ho^.%(^8SZ.;ǵ8 BXbc7tڍӈ-qUL?kO~8PA;PxV2mN|K4T2J⼥"!p'pbǚxF VFcCDxPr-Z@+ʷ#ؚ9jӳ!NEEdRvU((02#'J!]#YZc7wеT*LV c>mMO)Ԉg`ıq֫yD&ϭQhʎ0,OJfkLS)ć{rUNgH,ֲWvjM#N95(85;֜{IdVor9V# VvT`WAþ=NJIpWzj7QƾZ@#|GS^GFzּrOZꥫ<2 P+-,x\ 2Gh֛V{ vT n9ڹe,2oʻѨ 6P۰iA'ts7=(e#nYa;PWH{fyR*"@Lʥ_?Etsc+5Jr/?ZrybC`tDžS0$l[KUQ* )Ny5[kAP Ւgߴ›B|YE@0;Ŀ~YC}n\r s_迥oO|:UPJ)YnҪOg\2ܚJW9ҨA+2*۱-5M!>cU\O UILG#g(c;R<8Y jQ՗/maL`{Uʲe']fm7tlUPFcU!}i% NR!5o愅g'/q=RD4^%!aj)KS{VDR;cڦ]9V&Hq*mtàʻzS'rZ$Dyأ5ʇ I@b f#XmT5 +nGUYFXըO?{҆[[Ugo38;Pri|£.b-YH$s.+vhwpa6wǽxZІ$),UNS$}ڲoX.NM3ǸGt#6GzL3yŠ~n*Eb/k )T2͕5Tq ^^Niv:U|*yloވPk R&9 bi 885ѣI'Zϛ[1t{n=)&= #o$m<2\ #Z-6*XVq ~8"[KEE*H︾*\b,kcjA/ɷeO rճDL1{\&mE$C^A QҢ`W"[d]) ZA%>dnY/1 I [9l;V nne=j(=)H~nst%V!ޥiޫ (E6;^& cT4˅Pf7erz 4dF_Zw,!G\vvc{zV\C֔7+)^iX,K"+AV-%M@!RA bq`^ܞ~XO0GtsM*hFU{NĞ9A}jA}=)v*ʌȭ(j)a}Y9ǰWXMp.R܈_|s:Bjt+qU7Uc[ u*V{0z`?^)׭J!Nb"9_xU92C ӊPLPtomֶ:׫iA?Ki1bƿm!Y{ue,sȲFt#Gݵ)U?5-6myu{Bt4_>{;ףiWSeeU~,f yWx D~/|2s*#PE~Ixw ].8v E{$FH5fw| 5.Ɯj"WZ'w8vZwZn>xJҾ RKc(Qc$hX̎?{zisNI]B]a-7'\WjP{n6Xgb%sHV' MY$yssioJgn8lkDlv^(`G {V;i')aHrj]QFN9ec@j*\QQ&qPcl)ɇaޣU ֥TrzQ$eҤuGr*i;V-)SzjjbE dTX@E938V"K #-!~5U;£FM8{:Lgalv=kAӎ[ۓ*ki6UYic]n'RUTzţ%SpvGIgOG;+CҤWH>n>ZF[ ۿ0sR}j);k4(CSS $=)K *9aPu(86&GʤMC8M`#*j/57"()!V[sf=*Z.: 6p+CV#4SBh9/y>`WTHz:MrF$JCH,r8q l#Q?%+H Ҡ3ntiKe 'ݪpz/mʀ 40VVhMCE)3ջSRLǵA6lڮBѩ/T2_rXz!{T/"HAP-|^$9jtA'PsڤO8ZrD.m+ÊUpxDI}1$pp*[tYWMR}g9jJA)$UO6$+@jp#Հ찖#-&̋rV$HrҴt)e$6dR;#MDygePnd?8g$K<$61'j.0QGp0OzU+$EɡއjՕ-ê8*2pǵkLw߯z Xn=곱 p=+D>b\)R۽XI"CxZo;3ެFޯ8T!##qav$.MvIjps MCM9@{nEhM;}R,e@"DS{quA,`5Qd%߈4Ьn"툎GsM-"JQGJq)r6wy!i6wyemx#vD91ޫ+dGSMTִQ4Q5ɕMpV,b -I΂lk!۹' 1#Lu8 Fvڊk~-ca;aqzԶvVR^UI$zhsn2v>ԝ;0qxc|rs{XS==k]ئ8)>|I$}Ƒf3[\gQ 9H)k藅||-=t7ryv!iX5樇LnK,k#n,QaWw+Ѵ:zַBwrجSvJ96tk2y"5\QHԼpƩ"ɪiҐTZPcbYiUbϰ|P[SI. 01%<əzTQ^*SG UNIKR{ n^j˻)z(@0u<UXyTNA춌s$J~lqS,#Iڲ)6k'=2xn5m059v_ih#IQMBa'u -a7B7W2RF!EۗzA ]w6t`;51lsrz4AҺ]_(\'vuAtjV;Sv:@3i9?ӜT,I59pxBI6H"*z (C!=MK)Ye] H_bBymW ÚF]^<)+#N|T+)b&2Q*+7"4kP b)KȻf Jw{(W$!C*cNIfbW楒j4+n sZ7".S,vӅPKp&'SKa(B*F *D <njZ [?xRe@BF? `EglUPOFcgR1XE*68C;1,R"eVR&fG6$0MH%qD`gk+glG'\`ϙ?!.%٩Va P(jĸr$c ɑj.̀hqBƊb4sQ8 m8VJ_,yp:*-~V bpEMİʢI78@{vx/jב 2d7 ?(Yt,Ba'f/ݨclP۳)wɘqԋrXPF>tf36Gz{;Ց9(wsP%,F#*Џ?1<Cd U|ǵgD#(҄jŵI{&N:eZDzuN ^fz"$9=.zhoJʺQJLq s,9^In ]`L@^iq4lw8 \Ky6,zJy|gÆJq!iTjZf7 DpG\SpDik .rtY>ʹެz`5^cQebZyCsLI!MZb/ؤ~?%b>ެtr $/Z|!m[=+XcP|c,h1Կjyj3Y*d0a`B9 A,.z{V4"'U 3uZGː};V3$Yz6qaYmr= y~ƉIF|8nbYf*E2۠-.d$))m)7M}_ƛU9=jN&Q4@ZE^:V4o3H.AB )AewMzb; Uv o* {S4kܲTR4/ݳ9=>8ztP4z*on"^1ޑX'>*a5dpb c&nFV_1klQ4YIJ˻s:R+BرHNX'9A3ʲW*z͌r}*9K|hFxV]29 \U1s7 zoVU'`<:~^E J'itY79cV'u 9֑z23>ҷ+3yAPrAlzOt.aU"/Ks+JnpB7ፙGEr ^+GFӄB ύƸ-F鮯q#8_C\"t[CY<ըٶe8V|g3[s2I57yv+;A֥Q9%K;R~P Y l&\ںcLUV1PΨQNT?jeha(-F: % 3S$ErA/\>@@G0\EÃL JtpjQhq քkù jRnOCS9/2Py+|M ykyUJ@sR晷+ʼnH)rM4lGZa8IR)QaESM!BU\9D')+Ji [q0`r'Hȣ.qHc" O0 qM۞dڙCm歔0Rдw9N>^ ֔JqJ#8Sp 䎵k5!18*QSmsIh]˜F H8aN8pyiEKw 2ݬICZEcqWᑏU+/*m^) qNFe֙#x4I ŋe` T]=hv>n*"Dnu4Mf=婒!IX8sQ2p9=*9 LŠFippzT,F3TRn)TC)s.-)aڳ1`Z$e!/P2qXrz4FV^+9zչf8)ֶV6&]j3 EqhMí g 7jX48㨫 jɻd.&bjrqR:RИiṭҲgȫL殆3OA*t #Jn1S.9ms ($+GnS&%[ul. KٶvFDN(!VM†| _#,܎+پr>2Id!Fڸ&⊔cRŬFVPF9⩬@5~iVIϸܟ/"{Z}mcXBJlxFZ>'2vc+J bn7'ƉDOS_>zmY[; ;B_te>d楊?0%j$C&Ý:S3dz⡒ VaX9%#ɪ*6CV1 m1DLf20$7(ҡ›ԫ1ؑiX Ty|ޜb8'-it|#3{zwqVb~aw8aADz1z4.#ozoqQ}գArýH\NIVbwr{Vy܊n.KHS=H6sjbPc65*9' Zi++c'A޳rL#DJUpQ SӽP:Sd`ZFj9H:d.I54)|*snŽHN[I~Q޹%yM/1zB2s5"+ONzDbUS`xgn7IF]?4d{-]n;eB'&F$\a($WlZnfL&2jı.z r>dÜbŤeΑdF0ùY1"l|V˵N,)R'N+ʑmW^{<@Gz0i6(MI bvzQ#!,d Ncs֭NޑɜU>dBReD[wXaOzlPTkE UI.<{ܞW~j96Vאi&cuWL5"*hh*6ɭD9j>^8#GYTw85o}m9Z"$J4%*?;EfAfA@gl6jr< ;V/wZkH6Oz|.A9w5bpyZQ kwHx [#g{%דH<+O9Ty^kA#wQZN;K[^RUX@jk, W+jBu5އr/joMsnmz] 2d(iTn0iV]$sTrY HgݪHJU'*w +Ui1pǎP.A6\+WhЩ6.X-c#;מ\yD+eMSM2F.P{WD$'ln̵j.Cbx~vF<@"qޥ0k|-"t ="ȧm,9ipD!pjAOm٧F;5k4WR/nV+ @@h8N!5 ) ԧ`\=qI4{".sOQ?hE#dt F88iF UÐ))f M7vF1R5YdR!ĜtqMHJ%F]9\1\RF3O'\XF9M)Kg;vF(6~p)AԟM ,J3Z0ƣe,6jc!"'.2N*Ѹ RHv- ,29g2c>|*/ sRjx X;Ҝ`U@lAZ,I!.PVܫPTU9$n1ٱQJqM,4o SZ֌5]9C u6V̖yZ\;7=*h#Vr\*[Z: -e!T`&;> 1ɭa#&E9Ȩ[qtC=j:q$jpAV=楳bE= d眊cLʢ! RTT@zsrX%`qڮ+dfuکX4iɈ"Y8Y@Iq1-R j]ѵtKB#5c}OЭ ('K +ZZ- TZTS= %cpVm'*ŁQ)%.\sU&? 6Wbw4/F̽;S~OZs۞j ];e& (z;o^ŚP0+zV b'fhmkVSh["Q~U4rFjdiG95RvF5xHT;^oD3K&*lY165Z(<9ɫl$$]iL$a,9&S#U VB=yZYVe˵}j fz"hN|_,Ƌa 3*4hX얨rJXS~66GEq Wl7ڝl13g'W$?#ҴЛ#䧛Ub;1ie"f(hU9-VvmYnYcJ ޥ9ĿH+I|>, G!Ա\I7fh)L@)M$RjHBsBdjP2Ǯ+M XBeY3mtnh3:z״x?/#Īd68%e(ZF*3ڰ#|dⵢ-ف8{Fr@ȯ(# WR-x^(l׍9`1Z #i.&m%=}+j~Z $k$$(lC$aSZ[ϸ:VEphZ"Ju^ةE܈{J8 >z&ZzR2LDwrT̤7Z_#Qqh[*8pOjψDJ2&)g;vQ%P:7AR[ $,`iH"2v㧽]y1Vt*laf}aiG*FBHQO(;)QI"֐9c.ۣ8^fNT62I S \>V L##>qM(!_ I:X3yyR9[nOjk=MV`FTXf.x~(fbzDUrǯ\azQ>bvv -ڵ^4H9sXfO,J-ь,gsچ8?8Oj-$4$ḣjd9yG1%.cOfŠ9=hD]5B+$;?h.M1]W)SҤ1g*% #dc#[vڭӠYoZmhC*@n ^-z½y*+a.( ڴ쵩cg ,R[cϨ8l׫>c|"WSb/ ZƪaCJ=kB𑐠>j'eǞEc9El.0*ǴףKa&=dx/WgU 0ǻ8&8%RM!݈7$3ݜ0ɦȪ帹8sR@78.@`s֠aU+bd1iNySriX9'"֤XZcc6敛qO ֣8"ǰgڝ( RqU.TG :g2$ZSVTڠZG8Y 6QoBXGdrI)9k)M􏑞Dҗ`k>rHaps 2=*j&ι?-T5#4rV"`C;"\~֥:kWO̪+:(c8ȮK$6JpEsE;rō@ҭ!֩I>`SiX80媓&ċ(NJ5皶kE"Ӳ$PF*Jhli0O^*Yd MK93h% #aQDLzSJr2 S0@fSFCr"[ #N*FN $fWtX$qZO fOCE-NJ0\p_m~[{dI4Lҽÿpzo[Z7GwJ[z1+GG2MEIkF;SȨWk9&Uz=1lUnp.c퓚MƴLuyJ4pZxڧ\[nnex6J|{(:@i% ҹ0zJR9 桳E2ٕU|2=)N%J!S'Jrnbߴ^L|ZV.L;={{MI,4Oh(Ѩ?7,6T&s~5Vz+9@S$1ӵZWyb/h>R܄0>9Eqa ?G1! jV5eSZݣ',zUxhsӄLXN)nVΓ< xAֵ7*|o4A_g^Vi &^u*WBECF+'ST0d8e,Dgg$MyFc91 6~5VxU1rǭXE#UF16fTrc r"] 'By>fR 2M'JƈR9HmITѣGSS@IcFZQɖf0GzS?1j^s"z|:V3D[Ve/'E=Fxq$dM|jbBǭzZF#׆hjwg'5JZ=طnq^h(twnk3)B{rFC* Ap[Y *A>n*3,D\^XTQNcWS(w9ܱ ; 0}Ue.#?ZՍ kzfw)&'Tc{Մs|zC76'_.qexfJec7CTy"sBLwG]w*!7\N _q<>lmh\ hA'}*²HqDo'=!vl zXUz/2C?ZV3smOCdbK#`}r=ie-WTb4`"H\⍛_SWʅ~n\]YR,oWr GzD5#c=jAH/ޟ.֘}ިN$Y+xɇ) @ ~)1NAEğjtH՘BȊ6u5m,{\篵(;0+6_ ϖ?{JlCwC4j& F0OZkydjld#lu><ͫVPGSQ#ebkޠvVRH*pڢGScUĸJХHLT}dG6V ad}kϡz ]\hDf*" /#]SYv)V<&uA`Wg&C=댉8cvEI+.{\d4y˴ QJ%gy>R81_wmxXRkgyxZ&zdMJSPWYɮ>ijR]F)B[ެ0pYRwk/:Χ4Q [>gd|` 9Qq iZ#@T*->ǖrj0KurCc58V$_W!~h.>Od簧O\FMA09v'R,Xbԗ5gO$bÊ_dz4!]P @إ0HYLk : 95q(=Zb>3֡A$_h!֠^^!m*)iZX+>s[gз K"mZ[frZiٙ4)P^Xy։x ݕ!1( u5f;AȕD%9[sEshL˖sנVh OZTRd'=^47Ns)#K~qj90MG%†: upXr-&rCnIꑺΙR:WIEEѠ Oj5WF_n13 d8D)v=Un:Z񣲼ܲQ ։\5+\L${π;J^O*͙OJܺHU3ޱ'"zd* ɵGZtڀ0ZWS޳qFݺA1ɬ$ar }+isڡ+1؆lDr;t Uy 361#96W$>XfFk5A/([6^ildѧ~y1]&ۢelVV}€M,/6Cӵ9DQB!T#ŒV܏4c{v1H:bdqU&85NcF9 *rƒ a՜ڻ c~)n*Uv8;q,ܡ8AEB30 f;[g JHM + >SCjli$n`Fp*lv0)#94[áEϘjA)=r;j/Zj£$؎qVȹ VQ[XUWlxTT{d#x.~"Xn+E@\ɼ&1җg,4t\151zlJTlMo 2xsa$7A8"υo# ہI4Co\鮾6־բOj Px/GK#8Er8j5?kK[U7ܧ ڽhj#⣒J7:.ժXsˀ֟ ^&Σ*P[]tU{TbrﻠڷqcU—@9_4JzJחɟ8W+.*9eV%#'o:6*'YcpFhvTv$՜^*FnlSR$5mnZ2Ɵhy{R_ݱvbJcw:c ? ITmrP08i1) Nri*DM7"maJi 5!p}1jT+U$)̇9'֓cR$SI ;\#䯵B +RTs!W ӕj"3Hiw`S4s Jg4žP𧰫3QT>k9#Tѧ?*~dY5i~Z! _[$A=BfEjȌ?5 Ԉ]r/Ӓds 6;obRf1)֢lu?o50 WoJ)^#Zj9>ڋ$UVcn'J| 29nsP fw'ݨa,^rVFT`v; AUr=ǔ>r֩l)c\fc87qgҫO)cUm2y+I8AU5kaۂۂEOz릮'",A0Lla`d;d{|ޔA"&2C̟~fzTny'{Uaf ߼tZPb:6;Սw֯bv|"cޠ/# p ib?f#cֳuDQE9 'n})R?7'_J OnWiqگ,m#gLd})-#S42w5nIzfa!YLS+$is*k66NrW$'o0ӱndȑX;SӼbO̧WYZ7274SGLl5Rx@TnJ xaҦIsV&sַXDj>ZfSD*raCZi}cy_R j[vVcc`=P#y znogIm䎵T7H~"Y翥NuIbzTZŶc;SE_jK(v#ҩgqYnW`,ZMA]V6r#^Ak0B&$8ywi!B Eu>üNW:5krvFٌTw*Uն `5v"G\Yğg)A6W_t˭t⾧|N0(o?=/́׊vai#剡yrS40榆fx>RYJǶ z}48:IS(U-T#4ıkRѭVveVR@M}&7o *֛hg ~z5NEk3G#91S5Y+KX%ؙF)H^RqZc$$QeŌ?+ԠzLJSgPҚ8ޒ7*L SE)y5;G?s6OI 旳FmRkSEL5F+iy4e{+"r)!qKR}G@v K Vʼn86bNI5R+֣ܵEHg&Uvx^Ňto1YU 2-!#5U0950j8`ijE.이 zFr53&N"sTT]R\ҁM\qM@;*EQRdSs$VG-75#IBwf5]KRJ&%LU$|;K r_l M8b =? NE#񯿡8.mj`WޗbW@ <ħYOzY@l6Hqn}W~\?"vK"ç&ьGi'#9|fzMݢ EGoj͝b)Ӑp+h!f akLG2`88TUh[҉+faoI$ׯ M>ʧ+@k@dŠΒUElZ*R~Z!*C6 ڴaN@҄4JgA6"GA[[0Q揥]6Ǽu)#I`fjɉcUI Q4 ۊuY6!]bBJj [ɳ>R$rve%ímB/\H], 2[KbL/\t,S M`"+".d1ƾ@ߟɠ Nco,7+7;@:;0$KcHs¬E,w{b!a_DV.G¾Tua)QmШqviӂ`y1dkjlԌ(~SJV?'!Yh`?9SB/)[=a0 fFhڰ秵) pg݇҇L|VV(y;QL"X>t%)֪ J#*&it$c$4*zSGJhfňnlG++&m1c"SN @2F㊌c*2h%RFF ߚƇ!=*?()_CM囃\cT.F*7Զt]n$EQ2;[Mܚoq8nYS Up52auc+UR2O XMF찣i٩2(rjH t>ͭ[WrZ¢B j+psXѭ% XYt͒=zU/M^Bwd R6}Hj`P?A=f4Xz % zQ*\oX:d'lҘG9Qf+^YVv(cFrCȑԨbQҪM~b>QRTN3.$ nQ?5@oQ ~z芸\2#ndzB/?n$H0 n\aF;Tf~+Ub&`K]l-b42lZ#i=4[ #V6 .J(6#D^\j BG{=ћBk"*yE-!8^(}M\n`Z)f$TGQAA֊B/znw-D ".X 7 ;ӊGSR6Bl"GQ^r˷T+SÈ^ޥ(CPwM:kw7ኩG 8Xn_ w+ W y:K0sq]:^]u0"qסr" =*rf&yTt-brB:YfqaTJV)bGz"Jvj7>TI3dlCLdIo{PvA\-ĖQ!s7Z̶Pq=4ϽN1ßjo,v4(d3]b[HqzkHHrҮ%)0[)L¡$$TVmo#7 D[ 25wHd#ş)zhg(̇ KysY)ktP2 K;0 =EBdp#2 ms@`,c+600O&>Zݎ <\?zB䪤=@ӱhyglnJYRGms?<Ɯmq,Ә`~j B-RK7_cu;IRK)>gVL+˼w;}~K~Ia\i7s Vɓ`l3MBsU =茏rhb]JtN6Ewzs{WJ_W݁oh\ n=!y7+@N}kT{DSPW4gƮH9c@# tSq42 V\*՜Th繼4 C8SwmVF(Dya! 6ycڛ'"TRބt5_#~lbe,pJHgɌ H5R:cқ29er,o cqYsi-ar}jF#o4y85U!a\åB8H3/"SRh1Ԧe9\dҴSbhA *D%=Ny5n46j}W%>c8=N3U$TE2]e (Yej{H1ֹkTHD3y>zuD`66k15]\wSyBzUN9K LD4N҈5MU1&(*=+6e]HaTw5. dU';qG$ӊ>y\ weF%GwKJ SLRF6xQݤ٦%Z=-H4B;V12ԇޘf$c5Z TEH3QFB'NQ4 3AHb: ZT=O9JXc(o5` b8lI\B֗~^` <ޖ ώ DeA1=)YGcS+J5k+&и$Ȫ4XjyNębwg~PD}4i wZ#Cڅ$՘icՈTuRe2t wO5${ lͱ+&v(h~x#Pov+}θiKP )yU)Ex?74qʃjS( !.-7\+4P }/ZC{%+Le7Nhhw"Szӕ2j` .M(7)|;tĀ4,/JA *Psh"]^\+W~kU@JU:{N;l-хyxV7&6]%0ў1pΑGG U+*Cz㠦/|$rJ bꏱ PǖujE5m!K .-Ա)3j$K'f7nRqE dG8l]~1ˀr)e,DL""_;3eEؙHTajSnMUy# Bcr&F+zr^żm)g< I'ɹHȤcY^YBjPb?/Ԛ!SX9fnIHi(9WijR12VɣdX]  K)vi#}j.s4'x*HfQ:)¾*7sL;(V-6U&i):V%"^,6YOJq?n0Zbt~SVH=bal!h$0w7|zCn*+e[5k^}RnV?1iJ`{U"ձS0EI ZX>qgUi3 ܚ+HHGz\|zfHcOCHnLQ?Oz()d5b,M6d$df+cҳVs eJ1<.6-V#fNը7Hob77fb0~gn,G{QjO522htk2MC+HUbmϨ^Ajr.ҬjK3#NЪ9jrl< 1Ƞ́E1ȩzTNW! ު֦XؚB1r"\v@qQgi8晕$RnkEAۑX6⑴YqzJA⛜tQ#8niX޴X9$OX m(`y5a0:[py;:Rh\W9d+[6U/@q Mc m6wGڻ#[ܝx^GqϘnqi($"6<:&Z{[[#5`O=k fPќW5a'VD\!+9(n Lt\XW;b> kc?l_zId[ҿ?~\YLsUSW84YudwVq{qjҹrqQ ֺ Gú۱ Lr!L9PI>Xޜy5 i)Hr\zU0aV'j4?ޟ:WDZ  *qǵ]OS`V 2H1N㱝y@{NMSĺWw;~S xHj9P"֫+vr:qTո2}+Fajp"Oz4B87CVbs?cY ۦ)HQGHW%qֿk 7'^ȡl C͢$k,Σ6ǞcCk18 )2IQjHd^R97ԌXI3eٶ4*n6trih^^{9|: !ÁҤS۶B&3q}>+y {w|ªSP]1\|b#LJcXYgJ)&%ߎv[Py>jq'E>Y%rOҷQv<{vdۊ{r䀍E33ޕ֮b=pM [!=]8mJ-+~VPc;ttWnۂ;֮JA:ȸ;TܴX%)C05Q9?+f#3M OޭL`LC,#qJ~SU2qR&meMc:mkh%UmMmU0Rr+,bb9 ILzW_j­ =o,<`ѓ IdT",l湭cDP\IZC9PTU=Kf;UfCG@;⹧NbH6t4N샒HG`Vc#fKRGD*29"vMi "OqHmj4D!926%{TfbwOMtSPEW#vTvsFoCRZ:μZ;~kr\4ɮ sUХF۞>#}4Af#rlJj\UkdT+W7&3Yr:UlsNPqQ.xzKbupwdum J#i1֓ (`*\iI #*qJ>chj11ǑEEyXU$KCGRJYJu$ |Zaf' `M8WD`e)NdUr֔͑Tb\1* 45LC1N !8Nۚ%"y!STԪsHP Dni怴}kmIfs4Se+O;C1SpNFL4;1ZDf*kAVsXsM-隦Fjf'Hp0kA#hJ@3hFv楂Oҩy9•+7c5:wc ;!6tvW>E4# }E~5ԓ^~ux¸Uoʿfg}I.rۃ-iheg@޼_{^h@RM;cޗY"~ ݼ2+N*}(.T>>-%լb"7HU|砪LHW[st9+ 7~ź9)FzMɪEu4S+ZfKW$buX5;ꢾyO-XІsUoiQ%£t`IZN-20+[%ڣ\k q+q乒.:L3ܾ-Òָ5̕^[ar?r㹷Wު` yHSry[c=hx n=Rycq ~. z⧔0pZ_'~JAУp S0LZ,l*:֪2kQ8&cqQ 8߻e*8nSTf^]>V9Rt78?xS${wkQ::u >'69L<-n-bsR' d"sQ&%`dNHn,z?jAIݫ64Ж!ZIC=9O~ѩfj,ir+0I3KXsJc*gr^Ɵ={|Wl6եH7*G!xj($gzӾС{!Xy*IJbc;LR7#8޳yg81DaZpP9msZ]8U'\H?j?zT/FǞą,J ozSZ zTőIqӊm㡙no*'*:UdX$nLԶT3Ri<яJcZv*N_0J֟#-Es4Ȩ⭤;$Ǘ\Ғ%P?QZQt1ӱ2HѸhOWVK{Tw20 Vsm#;nXEfLWc'NcX#Ƽ8Le89UQ%QF<;՘bcZf6E%\ʻnڲ_clC*..kdsص<Ѣ39!&{VBFqO!}+;JoÕQv2X`Ipy[RXΒ9"75^Hm=JV݊nOaFĦHCsq[~OJ̽_7NF!wlI=xg׌f%$;ӔS:hIrq ֲ!pjpkp=XgDTT5i+vOi+=ys@VEܝ#ڤL Y*sJ !ؾA1T*6ⵈS}iv& z4 P0sE۩jsFGZj=Vi#S܃ҡQA]hɡxZUN"47\+Jsn)pEC֚3z'D@2 Kc SHǝRdKSAQ8Cb"ɵZi8R@@94pi8$5lkQ)9qYKSpzԋuVČRJ6F(j$*!'5_'<դp0;3H&՗\maV,գTtⰉ5+ W,xխD5[ҨqY-*@=j0J#bj{c|SHsV*mcxor;La8$W#\Z}ԣ1"n_ThBSk3YPY4hs}+bI/"rss+giN t=y⦰#I1y\z_.KtruFiszhoZ] 9ߖirc ,3,{$ՁM)LnDsҥ:S2X⒑cR* jFմ3DM+_F(6R Mʹitd㨦G^M9!\R`Eni(E z80kH|C.EтU,P-Ode1~i%i7usrZM1i:f}7{FޮB׵xF}xWpk'Ls.k98x~Rk.IQ߭t6P3bDar+X)Xָ2T)7 jNۇP(Qj[ eD?#vW-/,kRy'J-Qxjn8<J&wpGX׾vf#RXx \KwܶJ\.q=sҺhéU䎕oKI=n<ÔY73&s.;Ix!ڞXwUv2 ʏ!\ј3ıQ >ҵpⰥUm8ـ95Idrkd9UCfUܲa* +sv*(_'8;Dž#+.+H{eHb&(Ijxu=wɦsǎ~VYRJɑJ4rGzUwfW<ŷϔaRXSZGJ/JH6_Sɦ5n^˷N!y('lMԠePFATȔfT*@ҧ'ڢ вP g48I{'J(1HG^kq#6R ⥏jPm4yLاJ8RLMԻ0i`YB VP4wrkE39;MQ 嬉8 xNe=TB &lgN 8x`HӼj2+3h~*OsUZS&emȪʒ^հ5emynJG5$Y]DֱJ0k&k本ZFK!g;쯜b:ԨOo.ӂknMsT9MƳ;[MB[y)[漪;QZ0\5RFst[Lm-gCq |Zӵ{6pOJh{:O(Q3uqZ6 =SF*LṛJiU!ON_ uXB*7bR/`f'ӾX9NFHaI *(cy#5*w|ƌ{?v$aTYx-SZ$˯##g]ڲ$TqI0\n*eLʸxei0HZypc>V'V]^GVOTfq)E]:as/\7}#֕@*8[()#.P8P9+yU#!Nz֦(TXKF#~?5wU{a.PQ6uVw*v@cEObV:8iYpo$s' ~Rg;tӰh;>\_xT!|޵0yϭ=._ǽaa9ao-$S. S;'SN%9 xQ)G}-V]ݪL^"Aڛ$fv;V edK/N#I%NVLw +\q!*PٜjxyHazFbfxEE6d= B"!Y6qiǒ޵d"`c: rǡS(VS [[J2{㐯;HXiYB`lkÉnЮn[(rOz[ G͘74|ҘO?(`HHI9Sڛ5p &:yC,,;v0cisN+\׵hŧ,: k< q]lqZR}'"t+kO7knA%Udg(Ozzbc%ӓȪW'@* jF(EɱLG֪Nœc2!nep3an&mo%*|Q*G+;X`݉LQZugd'fۜIV֢hvlqҩdzQFITqY"r)"$e6&hbn7jR8%.Yr85yqT?Ur2>ӚPwuεUWDsHL fό;ADz4k@B6(OyDL1*.U(rj,orFCJWu#VAG(4L8sOW (8)c݃2pX㠭R%MOڮS9rW S5`CNĞb1V†8&BDZ :TQ>c<9lR'^ZRe[wDiMB񫌊pxT̪$KMYr[08u@&2y51[v`[䚻s:DeaqR8qyfqֳr7$iĪh^@x5HJW5sI BMDzph:LcQd)';JPOިJJI^*WCMRM#qK1*6y#E3925'<Ԙ3Kҙњ]TsO֔ T U&Zqҁ֞@LIv塩I 3QBl\ddJW9uUbԼ&yŤQ_Jh7GQSȦI'9AHZPiSAԸ&[cHQGFr2YR lXNZI#KLO&!k45YGk>FEqVq:,#gzը5.FN*a&x65V#CݪCuz3% jp+ig97c5wgBLLEBpW8 do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 cvmat_rect <- function(ptr, x = 0L, y = 0L, width = 0L, height = 0L) { .Call('_opencv_cvmat_rect', PACKAGE = 'opencv', ptr, x, y, width, height) } cvmat_bbox <- function(ptr) { .Call('_opencv_cvmat_bbox', PACKAGE = 'opencv', ptr) } cvpoints_bbox <- function(ptr, pts) { .Call('_opencv_cvpoints_bbox', PACKAGE = 'opencv', ptr, pts) } cvpoints_chull <- function(pts) { .Call('_opencv_cvpoints_chull', PACKAGE = 'opencv', pts) } cvmat_polygon <- function(ptr, pts, convex = FALSE, crop = FALSE, color = 255L) { .Call('_opencv_cvmat_polygon', PACKAGE = 'opencv', ptr, pts, convex, crop, color) } cvmat_destroy <- function(image) { invisible(.Call('_opencv_cvmat_destroy', PACKAGE = 'opencv', image)) } cvmat_dead <- function(image) { .Call('_opencv_cvmat_dead', PACKAGE = 'opencv', image) } cvmat_size <- function(image) { .Call('_opencv_cvmat_size', PACKAGE = 'opencv', image) } cvmat_new <- function() { .Call('_opencv_cvmat_new', PACKAGE = 'opencv') } cvmat_dupe <- function(image) { .Call('_opencv_cvmat_dupe', PACKAGE = 'opencv', image) } cvmat_read <- function(path) { .Call('_opencv_cvmat_read', PACKAGE = 'opencv', path) } cvmat_camera <- function() { .Call('_opencv_cvmat_camera', PACKAGE = 'opencv') } cvmat_write <- function(image, path) { .Call('_opencv_cvmat_write', PACKAGE = 'opencv', image, path) } cvmat_resize <- function(ptr, width = 0L, height = 0L) { .Call('_opencv_cvmat_resize', PACKAGE = 'opencv', ptr, width, height) } cvmat_raw_bgr <- function(image, width = 0L, height = 0L) { .Call('_opencv_cvmat_raw_bgr', PACKAGE = 'opencv', image, width, height) } cvmat_raw_bw <- function(image, width = 0L, height = 0L) { .Call('_opencv_cvmat_raw_bw', PACKAGE = 'opencv', image, width, height) } cvmat_bitmap <- function(ptr) { .Call('_opencv_cvmat_bitmap', PACKAGE = 'opencv', ptr) } cvmat_copyto <- function(from, to, mask) { .Call('_opencv_cvmat_copyto', PACKAGE = 'opencv', from, to, mask) } cvmat_info <- function(image) { .Call('_opencv_cvmat_info', PACKAGE = 'opencv', image) } cvmat_display <- function(ptr) { invisible(.Call('_opencv_cvmat_display', PACKAGE = 'opencv', ptr)) } livestream <- function(filter, stop_on_result = FALSE) { .Call('_opencv_livestream', PACKAGE = 'opencv', filter, stop_on_result) } data_prefix <- function() { .Call('_opencv_data_prefix', PACKAGE = 'opencv') } set_num_threads <- function(n = 0L) { .Call('_opencv_set_num_threads', PACKAGE = 'opencv', n) } cvmat_grayscale <- function(src) { .Call('_opencv_cvmat_grayscale', PACKAGE = 'opencv', src) } cvmat_blur <- function(ptr, ksize) { .Call('_opencv_cvmat_blur', PACKAGE = 'opencv', ptr, ksize) } cvmat_sketch <- function(ptr, color) { .Call('_opencv_cvmat_sketch', PACKAGE = 'opencv', ptr, color) } cvmat_stylize <- function(ptr) { .Call('_opencv_cvmat_stylize', PACKAGE = 'opencv', ptr) } enums_types <- function(maximum = 4L) { .Call('_opencv_enums_types', PACKAGE = 'opencv', maximum) } enums_depth <- function() { .Call('_opencv_enums_depth', PACKAGE = 'opencv') } cvmat_face <- function(ptr, facedata, eyedata) { .Call('_opencv_cvmat_face', PACKAGE = 'opencv', ptr, facedata, eyedata) } cvmat_facemask <- function(ptr, facedata) { .Call('_opencv_cvmat_facemask', PACKAGE = 'opencv', ptr, facedata) } cvmat_mog2 <- function(ptr) { .Call('_opencv_cvmat_mog2', PACKAGE = 'opencv', ptr) } cvmat_knn <- function(ptr) { .Call('_opencv_cvmat_knn', PACKAGE = 'opencv', ptr) } cvmat_edges <- function(ptr) { .Call('_opencv_cvmat_edges', PACKAGE = 'opencv', ptr) } cvkeypoints_fast <- function(ptr, threshold = 0L, nonmaxSuppression = TRUE, type = 2L) { .Call('_opencv_cvkeypoints_fast', PACKAGE = 'opencv', ptr, threshold, nonmaxSuppression, type) } cvkeypoints_harris <- function(ptr, numOctaves = 6L, corn_thresh = 0.01, DOG_thresh = 0.01, maxCorners = 5000L, num_layers = 4L) { .Call('_opencv_cvkeypoints_harris', PACKAGE = 'opencv', ptr, numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers) } cvmat_hog <- function(ptr) { .Call('_opencv_cvmat_hog', PACKAGE = 'opencv', ptr) } cvmat_markers <- function(ptr) { .Call('_opencv_cvmat_markers', PACKAGE = 'opencv', ptr) } cvmat_qr_detect <- function(ptr, return_image = FALSE, use_wechat = TRUE) { .Call('_opencv_cvmat_qr_detect', PACKAGE = 'opencv', ptr, return_image, use_wechat) } cvversion <- function() { .Call('_opencv_cvversion', PACKAGE = 'opencv') } opencv/R/keypoints.R0000644000176200001440000000500414435124332014115 0ustar liggesusers#' OpenCV keypoints #' #' Find key points in images #' @param image an ocv grayscale image object #' @param method the type of keypoint detection algorithm #' @param control a list of arguments passed on to the algorithm #' @param ... further arguments passed on to ocv_keypoints_options #' @section FAST algorithm arguments: #' \itemize{ #' \item threshold threshold on difference between intensity of the central pixel and pixels of a circle around this pixel. #' \item nonmaxSuppression if true, non-maximum suppression is applied to detected corners (keypoints). #' \item type one of the three neighborhoods as defined in the paper: TYPE_9_16, TYPE_7_12, TYPE_5_8 #' } #' @section Harris algorithm arguments: #' \itemize{ #' \item numOctaves the number of octaves in the scale-space pyramid #' \item corn_thresh the threshold for the Harris cornerness measure #' \item DOG_thresh the threshold for the Difference-of-Gaussians scale selection #' \item maxCorners the maximum number of corners to consider #' \item num_layers the number of intermediate scales per octave #' } #' @export #' @examples #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') #' mona <- ocv_resize(mona, width = 320, height = 477) #' #' # FAST-9 #' pts <- ocv_keypoints(mona, method = "FAST", type = "TYPE_9_16", threshold = 40) #' # Harris #' pts <- ocv_keypoints(mona, method = "Harris", maxCorners = 50) #' #' # Convex Hull of points #' pts <- ocv_chull(pts) #' #' \dontshow{ #' ocv_destroy(mona) #' } ocv_keypoints <- function(image, method = c("FAST", "Harris"), control = ocv_keypoints_options(method, ...), ...){ method <- match.arg(method) params <- control if(method == "FAST"){ cvkeypoints_fast(image, params$threshold, params$nonmaxSuppression, params$type) }else if(method == "Harris"){ cvkeypoints_harris(image, params$numOctaves, params$corn_thresh, params$DOG_thresh, params$maxCorners, params$num_layers) } } ocv_keypoints_options <- function(method = c("FAST", "Harris"), ...){ method <- match.arg(method) ldots <- list(...) if(method == "FAST"){ params <- list(threshold = 0, nonmaxSuppression = TRUE, type = c("TYPE_9_16", "TYPE_7_12", "TYPE_5_8")) }else if(method == "Harris"){ params <- list(numOctaves = 6, corn_thresh = 0.01, DOG_thresh = 0.01, maxCorners = 5000, num_layers = 4) } for(i in intersect(names(params), names(ldots))){ params[[i]] <- ldots[[i]] } if(is.character(params$type)){ params$type <- switch(params$type, "TYPE_5_8" = 0L, "TYPE_7_12" = 1L, "TYPE_9_16" = 2L) } params } opencv/R/xmldata.R0000644000176200001440000000073414576572451013546 0ustar liggesusersfind_data_dir <- function(){ datapath <- c("/share/opencv", "/share/opencv4", "/share/OpenCV") paths <- c( system.file('share/opencv4', package = 'opencv'), system.file('share', package = 'opencv'), paste0(data_prefix(), datapath) ) for(x in paths){ if(file.exists(x)) return(x) } stop("Failed to find opencv 'share' directory") } find_data_xml <- function(filename){ normalizePath(file.path(find_data_dir(), filename), mustWork = TRUE) } opencv/R/face.R0000644000176200001440000000065614435124332012776 0ustar liggesusers#' @export #' @rdname opencv ocv_face <- function(image){ facedata <- find_data_xml('haarcascades/haarcascade_frontalface_alt.xml') eyedata <- find_data_xml('haarcascades/haarcascade_eye_tree_eyeglasses.xml') cvmat_face(image, facedata, eyedata) } #' @export #' @rdname opencv ocv_facemask <- function(image){ facedata <- find_data_xml('haarcascades/haarcascade_frontalface_alt.xml') cvmat_facemask(image, facedata) } opencv/R/qr.R0000644000176200001440000000366314576572451012542 0ustar liggesusers#' Detect and Decode a QR code #' #' Detect and decode a QR code from an image or camera. By default it returns #' the text value from the QR code if detected, or NULL if no QR was found. If #' `draw = TRUE` then it returns an annotated image with the position and #' value of the QR drawn into the image, and qr text value as an attribute. #' The `qr_scanner` function opens the camera device (if available on your #' computer) and repeats [ocv_qr_detect] until it a QR is detected. #' #' OpenCV has two separate QR decoders. The 'wechat' decoder was added in #' libopencv 4.5.2 and generally has better performance and fault-tolerance. #' The old 'quirc' decoder is available on some older versions of libopencv as #' a plug-in, but many Linux distros did not include it. If you get an error #' *Library QUIRC is not linked. No decoding is performed.* this sadly means #' your Linux distribution is too old and does not support QR decoding. #' #' @export #' @rdname qrcode #' @inheritParams ocv_write #' @param draw if TRUE, the function returns an annotated image showing #' the position and value of the QR code. #' @param decoder which decoder implementation to use, see details. #' @returns if a QR code is detected, this returns either the text value of the QR, #' or if `draw` it returns the annotated image, with the value as an attribute. #' Returns NULL if no QR was found in the image. #' @examples #' png("test.png") #' plot(qrcode::qr_code("This is a test")) #' dev.off() #' ocv_qr_detect(ocv_read('test.png')) #' unlink("test.png") ocv_qr_detect <- function(image, draw = FALSE, decoder = c("wechat", "quirc")){ draw <- as.logical(draw) use_wechat <- match.arg(decoder) == 'wechat' cvmat_qr_detect(image, draw, use_wechat) } #' @export #' @rdname qrcode qr_scanner <- function(draw = FALSE, decoder = c("wechat", "quirc")){ ocv_video(function(image) { ocv_qr_detect(image = image, draw = draw, decoder = decoder) }, stop_on_result = TRUE) } opencv/R/init.R0000644000176200001440000000151214435124332013033 0ustar liggesusersenums <- new.env() .onAttach <- function(libname, pkgname){ enums$type <- enums_types() enums$depth <- enums_depth() } enum_label <- function(type, id){ kv <- enums[[type]] recoder(id, from = kv$key, to = kv$value) } enum_id <- function(type, label){ kv <- enums[[type]] recoder(label, from = kv$value, to = kv$key) } .onLoad <- function(libname, pkgname){ if(is_check()){ set_num_threads(2) } } is_macos <- function(){ grepl("darwin", R.Version()$platform) } is_iterm2 <- function(){ identical(Sys.getenv('TERM_PROGRAM'), 'iTerm.app') } is_check <- function(){ grepl('opencv.Rcheck', getwd(), fixed = TRUE) } is_mojave <- function(){ ver <- utils::tail(strsplit(utils::sessionInfo()$running, ' ')[[1]], 1) as.numeric_version(ver) >= "10.14" } is_rstudio <- function(){ Sys.getenv('RSTUDIO') == "1" } opencv/R/utils.R0000644000176200001440000000054014435124332013230 0ustar liggesusersrecoder <- function(x, from = c(), to = c()){ if(length(x) == 0){ return(x) } stopifnot(length(from) == length(to)) nongiven <- unique(x[!is.na(x)]) nongiven <- setdiff(nongiven, from) if(length(nongiven) > 0) { from <- append(x = from, values = nongiven) to <- append(x = to, values = nongiven) } to[match(x, from)] } opencv/R/areas.R0000644000176200001440000000440614435124332013170 0ustar liggesusers#' OpenCV area manipulation #' #' Manipulate image regions #' @name opencv-area #' @rdname opencv-area #' @param image an ocv image object #' @param x horizontal location #' @param y vertical location #' @param width width of the area #' @param height height of the area #' @export #' @examples #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') #' #' # Rectangular area #' ocv_rectangle(mona, x = 400, y = 300, height = 300, width = 350) #' ocv_rectangle(mona, x = 0, y = 100, height = 200) #' ocv_rectangle(mona, x = 500, y = 0, width = 75) #' #' # Polygon area #' img <- ocv_resize(mona, width = 320, height = 477) #' pts <- list(x = c(184, 172, 146, 114, 90, 76, 92, 163, 258), #' y = c(72, 68, 70, 90, 110, 398, 412, 385, 210)) #' ocv_polygon(img, pts) #' ocv_polygon(img, pts, crop = TRUE) #' ocv_polygon(img, pts, convex = TRUE, crop = TRUE) #' #' # Bounding box based on points #' ocv_bbox(img, pts) #' #' # Bounding box of non-zero pixel area #' area <- ocv_polygon(img, pts, color = 0, crop = FALSE) #' area #' area <- ocv_bbox(area) #' area #' #' \dontshow{ #' ocv_destroy(mona) #' ocv_destroy(img) #' ocv_destroy(area) #' } ocv_rectangle <- function(image, x = 0L, y = 0L, width, height){ size <- ocv_info(image) if(missing(width)){ width <- size$width } if(missing(height)){ height <- size$height } cvmat_rect(image, x, y, width, height) } #' @export #' @rdname opencv-area #' @param pts a list of points with elements x and y #' @param convex are the points convex #' @param crop crop the resulting area to its bounding box #' @param color color for the non-polygon area ocv_polygon <- function(image, pts, convex = FALSE, crop = FALSE, color = 255){ stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) cvmat_polygon(image, pts, convex, crop, color) } #' @export #' @rdname opencv-area #' @param pts a list of points with elements x and y ocv_bbox <- function(image, pts){ if(missing(pts)){ cvmat_bbox(image) }else{ stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) cvpoints_bbox(image, pts) } } #' @export #' @rdname opencv-area #' @param pts a list of points with elements x and y ocv_chull <- function(pts){ stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) cvpoints_chull(pts) } opencv/R/opencv.R0000644000176200001440000000753314576572451013412 0ustar liggesusers#' OpenCV Computer Vision #' #' Tools to experiment with computer vision algorithms. Use [ocv_read] and #' [ocv_write] to load/save images on disk, or use [ocv_picture] / [ocv_video] #' to use your webcam. In RSudio IDE the image objects will automatically be #' displayed in the viewer pane. #' #' @export #' @rdname opencv #' @importFrom Rcpp sourceCpp #' @useDynLib opencv #' @param path image file such as png or jpeg #' @examples # Silly example #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') #' #' # Edge detection #' ocv_edges(mona) #' ocv_markers(mona) #' #' # Find face #' faces <- ocv_face(mona) #' #' # To show locations of faces #' facemask <- ocv_facemask(mona) #' attr(facemask, 'faces') #' #' # This is not strictly needed #' ocv_destroy(mona) ocv_read <- function(path){ if(grepl("https?://", path)){ base <- basename(path) tmp <- file.path(tempdir(), base) utils::download.file(path, tmp, mode = 'wb') path <- tmp } path <- normalizePath(path, mustWork = TRUE) cvmat_read(path) } #' @export #' @rdname opencv #' @param image an ocv image object created from e.g. [ocv_read()] ocv_write <- function(image, path){ path <- normalizePath(path, mustWork = FALSE) cvmat_write(image, path) } #' @export #' @rdname opencv ocv_destroy <- function(image){ cvmat_destroy(image) } #' @export #' @rdname opencv ocv_bitmap <- function(image){ cvmat_bitmap(image) } #' @export #' @rdname opencv ocv_edges <- function(image){ cvmat_edges(image) } #' @export #' @rdname opencv ocv_picture <- function(){ cvmat_camera() } #' @export `print.opencv-image` <- function(x, ...){ viewer <- getOption("viewer") is_knit_image <- isTRUE(getOption('knitr.in.progress')) if(!is_knit_image && is.function(viewer) && !cvmat_dead(x)){ tmp <- file.path(tempdir(), paste0("preview.png")) ocv_write(x, path = tmp) viewer(tmp) } base::print.default(x) #TODO: copy from magick } #' @export #' @rdname opencv #' @param width output width in pixels #' @param height output height in pixels ocv_resize <- function(image, width = 0, height = 0){ cvmat_resize(image, as.integer(width), as.integer(height)) } #' @export #' @rdname opencv ocv_mog2 <- function(image){ cvmat_mog2(image) } #' @export #' @rdname opencv ocv_knn <- function(image){ cvmat_knn(image) } #' @export #' @rdname opencv ocv_hog <- function(image){ cvmat_hog(image) } #' @export #' @rdname opencv #' @param ksize size of blurring matrix ocv_blur <- function(image, ksize = 5){ cvmat_blur(image, ksize) } #' @export #' @rdname opencv #' @param color true or false ocv_sketch <- function(image, color = TRUE){ cvmat_sketch(image, color) } #' @export #' @rdname opencv ocv_stylize <- function(image){ cvmat_stylize(image) } #' @export #' @rdname opencv ocv_markers <- function(image){ cvmat_markers(image) } #' @export #' @rdname opencv ocv_info <- function(image){ info <- cvmat_info(image) info$type <- enum_label("type", info$type) info$depth <- enum_label("depth", info$depth) info } #' @export #' @rdname opencv #' @param target the output image #' @param mask only copy pixels from the mask ocv_copyto <- function(image, target, mask){ cvmat_copyto(image, target, mask) } #' @export #' @rdname opencv ocv_display <- function(image){ cvmat_display(image) } #' @export #' @rdname opencv #' @param filter an R function that takes and returns an opecv image #' @param stop_on_result stop if an object is detected ocv_video <- function(filter, stop_on_result = FALSE){ if(!is.function(filter)) stop("Filter must be a function") message("Starting video window (could be behind this window)") livestream(filter, stop_on_result) } #' @export #' @rdname opencv ocv_grayscale <- function(image){ cvmat_grayscale(image) } #' @export #' @rdname opencv ocv_version <- function(){ cvversion() } #' @importFrom magrittr %>% #' @export magrittr::`%>%` opencv/cleanup0000755000176200001440000000006414772474025013135 0ustar liggesusers#!/bin/sh rm -f src/Makevars configure.log autobrew opencv/NEWS0000644000176200001440000000111014766132417012247 0ustar liggesusers0.5.0 - Windows: use opencv from Rtools when available (R >= 4.5) 0.4.0 - Add QR code detector - Windows: update to libopencv 4.8.1 0.3.0 - Windows: update to libopencv 4.8.0 0.2.3 - Compile with CXX17 when available to fix compiler warnings 0.2.2 - MacOS: update binaries to opencv 4.5.5 0.2 - Windows / MacOS: upgrade binary packages to OpenCV 4.4.0 - Add ocv_rectangle - Add ocv_polygon - Add ocv_bbox - Add ocv_chull - Add ocv_keypoints for keypoint detection using FAST, Harris - Add ocv_grayscale - Add ocv_version 0.1 - Initial CRAN release opencv/src/0000755000176200001440000000000014772462135012346 5ustar liggesusersopencv/src/RcppExports.cpp0000644000176200001440000004757014576572451015365 0ustar liggesusers// Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 #include "opencv_types.h" #include using namespace Rcpp; #ifdef RCPP_USE_GLOBAL_ROSTREAM Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); #endif // cvmat_rect XPtrMat cvmat_rect(XPtrMat ptr, int x, int y, int width, int height); RcppExport SEXP _opencv_cvmat_rect(SEXP ptrSEXP, SEXP xSEXP, SEXP ySEXP, SEXP widthSEXP, SEXP heightSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< int >::type x(xSEXP); Rcpp::traits::input_parameter< int >::type y(ySEXP); Rcpp::traits::input_parameter< int >::type width(widthSEXP); Rcpp::traits::input_parameter< int >::type height(heightSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_rect(ptr, x, y, width, height)); return rcpp_result_gen; END_RCPP } // cvmat_bbox XPtrMat cvmat_bbox(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_bbox(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_bbox(ptr)); return rcpp_result_gen; END_RCPP } // cvpoints_bbox XPtrMat cvpoints_bbox(XPtrMat ptr, Rcpp::List pts); RcppExport SEXP _opencv_cvpoints_bbox(SEXP ptrSEXP, SEXP ptsSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); rcpp_result_gen = Rcpp::wrap(cvpoints_bbox(ptr, pts)); return rcpp_result_gen; END_RCPP } // cvpoints_chull Rcpp::List cvpoints_chull(Rcpp::List pts); RcppExport SEXP _opencv_cvpoints_chull(SEXP ptsSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); rcpp_result_gen = Rcpp::wrap(cvpoints_chull(pts)); return rcpp_result_gen; END_RCPP } // cvmat_polygon XPtrMat cvmat_polygon(XPtrMat ptr, Rcpp::List pts, bool convex, bool crop, int color); RcppExport SEXP _opencv_cvmat_polygon(SEXP ptrSEXP, SEXP ptsSEXP, SEXP convexSEXP, SEXP cropSEXP, SEXP colorSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); Rcpp::traits::input_parameter< bool >::type convex(convexSEXP); Rcpp::traits::input_parameter< bool >::type crop(cropSEXP); Rcpp::traits::input_parameter< int >::type color(colorSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_polygon(ptr, pts, convex, crop, color)); return rcpp_result_gen; END_RCPP } // cvmat_destroy void cvmat_destroy(XPtrMat image); RcppExport SEXP _opencv_cvmat_destroy(SEXP imageSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); cvmat_destroy(image); return R_NilValue; END_RCPP } // cvmat_dead bool cvmat_dead(XPtrMat image); RcppExport SEXP _opencv_cvmat_dead(SEXP imageSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_dead(image)); return rcpp_result_gen; END_RCPP } // cvmat_size int cvmat_size(XPtrMat image); RcppExport SEXP _opencv_cvmat_size(SEXP imageSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_size(image)); return rcpp_result_gen; END_RCPP } // cvmat_new XPtrMat cvmat_new(); RcppExport SEXP _opencv_cvmat_new() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(cvmat_new()); return rcpp_result_gen; END_RCPP } // cvmat_dupe XPtrMat cvmat_dupe(XPtrMat image); RcppExport SEXP _opencv_cvmat_dupe(SEXP imageSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_dupe(image)); return rcpp_result_gen; END_RCPP } // cvmat_read XPtrMat cvmat_read(Rcpp::String path); RcppExport SEXP _opencv_cvmat_read(SEXP pathSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< Rcpp::String >::type path(pathSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_read(path)); return rcpp_result_gen; END_RCPP } // cvmat_camera XPtrMat cvmat_camera(); RcppExport SEXP _opencv_cvmat_camera() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(cvmat_camera()); return rcpp_result_gen; END_RCPP } // cvmat_write std::string cvmat_write(XPtrMat image, std::string path); RcppExport SEXP _opencv_cvmat_write(SEXP imageSEXP, SEXP pathSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); Rcpp::traits::input_parameter< std::string >::type path(pathSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_write(image, path)); return rcpp_result_gen; END_RCPP } // cvmat_resize XPtrMat cvmat_resize(XPtrMat ptr, int width, int height); RcppExport SEXP _opencv_cvmat_resize(SEXP ptrSEXP, SEXP widthSEXP, SEXP heightSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< int >::type width(widthSEXP); Rcpp::traits::input_parameter< int >::type height(heightSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_resize(ptr, width, height)); return rcpp_result_gen; END_RCPP } // cvmat_raw_bgr XPtrMat cvmat_raw_bgr(Rcpp::RawVector image, int width, int height); RcppExport SEXP _opencv_cvmat_raw_bgr(SEXP imageSEXP, SEXP widthSEXP, SEXP heightSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< Rcpp::RawVector >::type image(imageSEXP); Rcpp::traits::input_parameter< int >::type width(widthSEXP); Rcpp::traits::input_parameter< int >::type height(heightSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_raw_bgr(image, width, height)); return rcpp_result_gen; END_RCPP } // cvmat_raw_bw XPtrMat cvmat_raw_bw(Rcpp::RawVector image, int width, int height); RcppExport SEXP _opencv_cvmat_raw_bw(SEXP imageSEXP, SEXP widthSEXP, SEXP heightSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< Rcpp::RawVector >::type image(imageSEXP); Rcpp::traits::input_parameter< int >::type width(widthSEXP); Rcpp::traits::input_parameter< int >::type height(heightSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_raw_bw(image, width, height)); return rcpp_result_gen; END_RCPP } // cvmat_bitmap Rcpp::RawVector cvmat_bitmap(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_bitmap(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_bitmap(ptr)); return rcpp_result_gen; END_RCPP } // cvmat_copyto XPtrMat cvmat_copyto(XPtrMat from, XPtrMat to, XPtrMat mask); RcppExport SEXP _opencv_cvmat_copyto(SEXP fromSEXP, SEXP toSEXP, SEXP maskSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type from(fromSEXP); Rcpp::traits::input_parameter< XPtrMat >::type to(toSEXP); Rcpp::traits::input_parameter< XPtrMat >::type mask(maskSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_copyto(from, to, mask)); return rcpp_result_gen; END_RCPP } // cvmat_info Rcpp::List cvmat_info(XPtrMat image); RcppExport SEXP _opencv_cvmat_info(SEXP imageSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_info(image)); return rcpp_result_gen; END_RCPP } // cvmat_display void cvmat_display(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_display(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); cvmat_display(ptr); return R_NilValue; END_RCPP } // livestream Rcpp::RObject livestream(Rcpp::Function filter, bool stop_on_result); RcppExport SEXP _opencv_livestream(SEXP filterSEXP, SEXP stop_on_resultSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< Rcpp::Function >::type filter(filterSEXP); Rcpp::traits::input_parameter< bool >::type stop_on_result(stop_on_resultSEXP); rcpp_result_gen = Rcpp::wrap(livestream(filter, stop_on_result)); return rcpp_result_gen; END_RCPP } // data_prefix Rcpp::String data_prefix(); RcppExport SEXP _opencv_data_prefix() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(data_prefix()); return rcpp_result_gen; END_RCPP } // set_num_threads int set_num_threads(int n); RcppExport SEXP _opencv_set_num_threads(SEXP nSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< int >::type n(nSEXP); rcpp_result_gen = Rcpp::wrap(set_num_threads(n)); return rcpp_result_gen; END_RCPP } // cvmat_grayscale XPtrMat cvmat_grayscale(XPtrMat src); RcppExport SEXP _opencv_cvmat_grayscale(SEXP srcSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type src(srcSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_grayscale(src)); return rcpp_result_gen; END_RCPP } // cvmat_blur XPtrMat cvmat_blur(XPtrMat ptr, size_t ksize); RcppExport SEXP _opencv_cvmat_blur(SEXP ptrSEXP, SEXP ksizeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< size_t >::type ksize(ksizeSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_blur(ptr, ksize)); return rcpp_result_gen; END_RCPP } // cvmat_sketch XPtrMat cvmat_sketch(XPtrMat ptr, bool color); RcppExport SEXP _opencv_cvmat_sketch(SEXP ptrSEXP, SEXP colorSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< bool >::type color(colorSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_sketch(ptr, color)); return rcpp_result_gen; END_RCPP } // cvmat_stylize XPtrMat cvmat_stylize(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_stylize(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_stylize(ptr)); return rcpp_result_gen; END_RCPP } // enums_types Rcpp::List enums_types(int maximum); RcppExport SEXP _opencv_enums_types(SEXP maximumSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< int >::type maximum(maximumSEXP); rcpp_result_gen = Rcpp::wrap(enums_types(maximum)); return rcpp_result_gen; END_RCPP } // enums_depth Rcpp::List enums_depth(); RcppExport SEXP _opencv_enums_depth() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(enums_depth()); return rcpp_result_gen; END_RCPP } // cvmat_face XPtrMat cvmat_face(XPtrMat ptr, const char * facedata, const char * eyedata); RcppExport SEXP _opencv_cvmat_face(SEXP ptrSEXP, SEXP facedataSEXP, SEXP eyedataSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< const char * >::type facedata(facedataSEXP); Rcpp::traits::input_parameter< const char * >::type eyedata(eyedataSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_face(ptr, facedata, eyedata)); return rcpp_result_gen; END_RCPP } // cvmat_facemask XPtrMat cvmat_facemask(XPtrMat ptr, const char * facedata); RcppExport SEXP _opencv_cvmat_facemask(SEXP ptrSEXP, SEXP facedataSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< const char * >::type facedata(facedataSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_facemask(ptr, facedata)); return rcpp_result_gen; END_RCPP } // cvmat_mog2 XPtrMat cvmat_mog2(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_mog2(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_mog2(ptr)); return rcpp_result_gen; END_RCPP } // cvmat_knn XPtrMat cvmat_knn(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_knn(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_knn(ptr)); return rcpp_result_gen; END_RCPP } // cvmat_edges XPtrMat cvmat_edges(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_edges(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_edges(ptr)); return rcpp_result_gen; END_RCPP } // cvkeypoints_fast Rcpp::List cvkeypoints_fast(XPtrMat ptr, int threshold, bool nonmaxSuppression, int type); RcppExport SEXP _opencv_cvkeypoints_fast(SEXP ptrSEXP, SEXP thresholdSEXP, SEXP nonmaxSuppressionSEXP, SEXP typeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< int >::type threshold(thresholdSEXP); Rcpp::traits::input_parameter< bool >::type nonmaxSuppression(nonmaxSuppressionSEXP); Rcpp::traits::input_parameter< int >::type type(typeSEXP); rcpp_result_gen = Rcpp::wrap(cvkeypoints_fast(ptr, threshold, nonmaxSuppression, type)); return rcpp_result_gen; END_RCPP } // cvkeypoints_harris Rcpp::List cvkeypoints_harris(XPtrMat ptr, int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners, int num_layers); RcppExport SEXP _opencv_cvkeypoints_harris(SEXP ptrSEXP, SEXP numOctavesSEXP, SEXP corn_threshSEXP, SEXP DOG_threshSEXP, SEXP maxCornersSEXP, SEXP num_layersSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< int >::type numOctaves(numOctavesSEXP); Rcpp::traits::input_parameter< float >::type corn_thresh(corn_threshSEXP); Rcpp::traits::input_parameter< float >::type DOG_thresh(DOG_threshSEXP); Rcpp::traits::input_parameter< int >::type maxCorners(maxCornersSEXP); Rcpp::traits::input_parameter< int >::type num_layers(num_layersSEXP); rcpp_result_gen = Rcpp::wrap(cvkeypoints_harris(ptr, numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers)); return rcpp_result_gen; END_RCPP } // cvmat_hog XPtrMat cvmat_hog(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_hog(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_hog(ptr)); return rcpp_result_gen; END_RCPP } // cvmat_markers XPtrMat cvmat_markers(XPtrMat ptr); RcppExport SEXP _opencv_cvmat_markers(SEXP ptrSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_markers(ptr)); return rcpp_result_gen; END_RCPP } // cvmat_qr_detect SEXP cvmat_qr_detect(XPtrMat ptr, bool return_image, bool use_wechat); RcppExport SEXP _opencv_cvmat_qr_detect(SEXP ptrSEXP, SEXP return_imageSEXP, SEXP use_wechatSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); Rcpp::traits::input_parameter< bool >::type return_image(return_imageSEXP); Rcpp::traits::input_parameter< bool >::type use_wechat(use_wechatSEXP); rcpp_result_gen = Rcpp::wrap(cvmat_qr_detect(ptr, return_image, use_wechat)); return rcpp_result_gen; END_RCPP } // cvversion std::string cvversion(); RcppExport SEXP _opencv_cvversion() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(cvversion()); return rcpp_result_gen; END_RCPP } static const R_CallMethodDef CallEntries[] = { {"_opencv_cvmat_rect", (DL_FUNC) &_opencv_cvmat_rect, 5}, {"_opencv_cvmat_bbox", (DL_FUNC) &_opencv_cvmat_bbox, 1}, {"_opencv_cvpoints_bbox", (DL_FUNC) &_opencv_cvpoints_bbox, 2}, {"_opencv_cvpoints_chull", (DL_FUNC) &_opencv_cvpoints_chull, 1}, {"_opencv_cvmat_polygon", (DL_FUNC) &_opencv_cvmat_polygon, 5}, {"_opencv_cvmat_destroy", (DL_FUNC) &_opencv_cvmat_destroy, 1}, {"_opencv_cvmat_dead", (DL_FUNC) &_opencv_cvmat_dead, 1}, {"_opencv_cvmat_size", (DL_FUNC) &_opencv_cvmat_size, 1}, {"_opencv_cvmat_new", (DL_FUNC) &_opencv_cvmat_new, 0}, {"_opencv_cvmat_dupe", (DL_FUNC) &_opencv_cvmat_dupe, 1}, {"_opencv_cvmat_read", (DL_FUNC) &_opencv_cvmat_read, 1}, {"_opencv_cvmat_camera", (DL_FUNC) &_opencv_cvmat_camera, 0}, {"_opencv_cvmat_write", (DL_FUNC) &_opencv_cvmat_write, 2}, {"_opencv_cvmat_resize", (DL_FUNC) &_opencv_cvmat_resize, 3}, {"_opencv_cvmat_raw_bgr", (DL_FUNC) &_opencv_cvmat_raw_bgr, 3}, {"_opencv_cvmat_raw_bw", (DL_FUNC) &_opencv_cvmat_raw_bw, 3}, {"_opencv_cvmat_bitmap", (DL_FUNC) &_opencv_cvmat_bitmap, 1}, {"_opencv_cvmat_copyto", (DL_FUNC) &_opencv_cvmat_copyto, 3}, {"_opencv_cvmat_info", (DL_FUNC) &_opencv_cvmat_info, 1}, {"_opencv_cvmat_display", (DL_FUNC) &_opencv_cvmat_display, 1}, {"_opencv_livestream", (DL_FUNC) &_opencv_livestream, 2}, {"_opencv_data_prefix", (DL_FUNC) &_opencv_data_prefix, 0}, {"_opencv_set_num_threads", (DL_FUNC) &_opencv_set_num_threads, 1}, {"_opencv_cvmat_grayscale", (DL_FUNC) &_opencv_cvmat_grayscale, 1}, {"_opencv_cvmat_blur", (DL_FUNC) &_opencv_cvmat_blur, 2}, {"_opencv_cvmat_sketch", (DL_FUNC) &_opencv_cvmat_sketch, 2}, {"_opencv_cvmat_stylize", (DL_FUNC) &_opencv_cvmat_stylize, 1}, {"_opencv_enums_types", (DL_FUNC) &_opencv_enums_types, 1}, {"_opencv_enums_depth", (DL_FUNC) &_opencv_enums_depth, 0}, {"_opencv_cvmat_face", (DL_FUNC) &_opencv_cvmat_face, 3}, {"_opencv_cvmat_facemask", (DL_FUNC) &_opencv_cvmat_facemask, 2}, {"_opencv_cvmat_mog2", (DL_FUNC) &_opencv_cvmat_mog2, 1}, {"_opencv_cvmat_knn", (DL_FUNC) &_opencv_cvmat_knn, 1}, {"_opencv_cvmat_edges", (DL_FUNC) &_opencv_cvmat_edges, 1}, {"_opencv_cvkeypoints_fast", (DL_FUNC) &_opencv_cvkeypoints_fast, 4}, {"_opencv_cvkeypoints_harris", (DL_FUNC) &_opencv_cvkeypoints_harris, 6}, {"_opencv_cvmat_hog", (DL_FUNC) &_opencv_cvmat_hog, 1}, {"_opencv_cvmat_markers", (DL_FUNC) &_opencv_cvmat_markers, 1}, {"_opencv_cvmat_qr_detect", (DL_FUNC) &_opencv_cvmat_qr_detect, 3}, {"_opencv_cvversion", (DL_FUNC) &_opencv_cvversion, 0}, {NULL, NULL, 0} }; RcppExport void R_init_opencv(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } opencv/src/effects.cpp0000644000176200001440000000133714435124332014463 0ustar liggesusers#include "util.hpp" using namespace cv; // [[Rcpp::export]] XPtrMat cvmat_blur(XPtrMat ptr, size_t ksize){ Mat out; cv::blur(get_mat(ptr), out, Size(ksize, ksize)); return cvmat_xptr(out); } // [[Rcpp::export]] XPtrMat cvmat_sketch(XPtrMat ptr, bool color){ Mat out1; Mat out2; #ifndef HAVE_OPENCV_3 throw std::runtime_error("pencilSketch requires OpenCV 3 or newer"); #else pencilSketch(get_mat(ptr),out1, out2, 10 , 0.1f, 0.03f); #endif return cvmat_xptr(color ? out2 : out1); } // [[Rcpp::export]] XPtrMat cvmat_stylize(XPtrMat ptr){ Mat out; #ifndef HAVE_OPENCV_3 throw std::runtime_error("stylization requires OpenCV 3 or newer"); #else stylization(get_mat(ptr), out); #endif return cvmat_xptr(out); } opencv/src/util.cpp0000644000176200001440000000631514435124332014022 0ustar liggesusers#include "util.hpp" using namespace cv; using namespace std; void detectAndDraw( Mat img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip ) { double t = 0; std::vector faces, faces2; const static Scalar colors[] = { Scalar(255,0,0), Scalar(255,128,0), Scalar(255,255,0), Scalar(0,255,0), Scalar(0,128,255), Scalar(0,255,255), Scalar(0,0,255), Scalar(255,0,255) }; Mat gray, smallImg; cvtColor( img, gray, COLOR_BGR2GRAY ); double fx = 1 / scale; resize( gray, smallImg, Size(), fx, fx); equalizeHist( smallImg, smallImg ); t = (double)getTickCount(); cascade.detectMultiScale( smallImg, faces, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { flip(smallImg, smallImg, 1); cascade.detectMultiScale( smallImg, faces2, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( std::vector::const_iterator r = faces2.begin(); r != faces2.end(); ++r ) { faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height)); } } t = (double)getTickCount() - t; //printf( "detection time = %g ms\n", t*1000/getTickFrequency()); for ( size_t i = 0; i < faces.size(); i++ ) { Rect r = faces[i]; Mat smallImgROI; std::vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { center.x = cvRound((r.x + r.width*0.5)*scale); center.y = cvRound((r.y + r.height*0.5)*scale); radius = cvRound((r.width + r.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } else rectangle( img, cv::Point(cvRound(r.x*scale), cvRound(r.y*scale)), cv::Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); if( nestedCascade.empty() ) continue; smallImgROI = smallImg( r ); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING |CASCADE_SCALE_IMAGE, Size(30, 30) ); for ( size_t j = 0; j < nestedObjects.size(); j++ ) { Rect nr = nestedObjects[j]; center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); radius = cvRound((nr.width + nr.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } } //imshow( "result", img ); } opencv/src/Makevars.win0000644000176200001440000000254714772464233014647 0ustar liggesusersPKG_CONFIG_NAME = opencv4 PKG_CONFIG ?= $(BINPREF)pkg-config PKG_LIBS := $(shell $(PKG_CONFIG) --libs $(PKG_CONFIG_NAME)) STATIC_CFLAGS = -DHAVE_XFEATURES2D ifneq ($(findstring xfeatures2d,$(PKG_LIBS)),) $(info using $(PKG_CONFIG_NAME) from Rtools) PKG_CPPFLAGS := $(shell $(PKG_CONFIG) --cflags $(PKG_CONFIG_NAME)) $(STATIC_CFLAGS) OPENCVDATA := $(shell $(PKG_CONFIG) --variable=prefix $(PKG_CONFIG_NAME))/share/opencv4 else RWINLIB = ../.deps/opencv PKG_CPPFLAGS = -I$(RWINLIB)/include/opencv4 $(STATIC_CFLAGS) OLDLIBDIR = lib${subst gcc,,${COMPILED_BY}}${R_ARCH} PKG_LIBS = \ -L$(RWINLIB)/$(OLDLIBDIR) \ -L$(RWINLIB)/lib \ -lopencv_ml481 -lopencv_objdetect481 -lopencv_photo481 -lopencv_stitching481 -lopencv_wechat_qrcode481 -lopencv_dnn481 \ -lopencv_video481 -lopencv_calib3d481 -lopencv_xfeatures2d481 -lopencv_features2d481 -lopencv_highgui481 -lopencv_flann481 \ -lopencv_videoio481 -lopencv_imgcodecs481 -lopencv_imgproc481 -lopencv_core481 -llibopenjp2 -lquirc \ -ljpeg -lwebp -lsharpyuv -lpng -lz -ltiff -lpthread -lgdi32 -lole32 -lopengl32 -lcomdlg32 -lOleAut32 -luuid OPENCVDATA = $(RWINLIB)/share endif all: copydata $(OBJECTS): | $(RWINLIB) $(RWINLIB): "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" copydata: | $(RWINLIB) rm -Rf ../inst/share && mkdir -p ../inst cp -Rf $(OPENCVDATA) ../inst/share cleanup: $(SHLIB) @rm -Rf $(RWINLIB) opencv/src/hog.cpp0000644000176200001440000000276114435124332013623 0ustar liggesusers#include "util.hpp" using namespace cv; using namespace std; // [[Rcpp::export]] XPtrMat cvmat_hog(XPtrMat ptr){ HOGDescriptor hog; hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); vector found, found_filtered; double t = (double) getTickCount(); // Run the detector with default parameters. to get a higher hit-rate // (and more false alarms, respectively), decrease the hitThreshold and // groupThreshold (set groupThreshold to 0 to turn off the grouping completely). hog.detectMultiScale(get_mat(ptr), found, 0, Size(8,8), Size(32,32), 1.05, 2); t = (double) getTickCount() - t; //cout << "detection time = " << (t*1000./cv::getTickFrequency()) << " ms" << endl; for(size_t i = 0; i < found.size(); i++ ) { Rect r = found[i]; size_t j; // Do not add small detections inside a bigger detection. for ( j = 0; j < found.size(); j++ ){ if ( j != i && (r & found[j]) == r ) break; if ( j == found.size() ) found_filtered.push_back(r); } } for (size_t i = 0; i < found_filtered.size(); i++) { Rect r = found_filtered[i]; // The HOG detector returns slightly larger rectangles than the real objects, // so we slightly shrink the rectangles to get a nicer output. r.x += cvRound(r.width*0.1); r.width = cvRound(r.width*0.8); r.y += cvRound(r.height*0.07); r.height = cvRound(r.height*0.8); Mat img = get_mat(ptr); rectangle(img, r.tl(), r.br(), cv::Scalar(0,255,0), 3); } return ptr; } opencv/src/features.cpp0000644000176200001440000000474314435124332014666 0ustar liggesusers#include #include "util.hpp" #include #include #ifdef HAVE_XFEATURES2D #include #endif Rcpp::List keypoints_coords(const std::vector& pts){ std::vector x; std::vector y; for (size_t i = 0; i < pts.size(); ++i){ x.push_back(pts[i].pt.x); y.push_back(pts[i].pt.y); } Rcpp::List out = Rcpp::List::create(Rcpp::Named("x") = x, Rcpp::Named("y") = y); return out; } // [[Rcpp::export]] Rcpp::List cvkeypoints_fast(XPtrMat ptr, int threshold = 0, bool nonmaxSuppression = true, int type = 2){ cv::Mat img; cv::cvtColor(get_mat(ptr), img, cv::COLOR_BGR2GRAY); std::vector keypoints; #ifndef HAVE_XFEATURES2D Rcpp::Rcout << "Keypoint detection disabled as module xfeatures2d from opencv_contrib is not present." << std::endl; return keypoints_coords(keypoints); #else // versions < 4 had CV_VERSION_EPOCH instead of CV_VERSION_MAJOR and cv::FastFeatureDetector::DetectorType did not exist (was just an integer) #ifndef HAVE_OPENCV_4 int neighbourhood; #else cv::FastFeatureDetector::DetectorType neighbourhood; #endif switch(type){ case cv::FastFeatureDetector::TYPE_9_16: neighbourhood = cv::FastFeatureDetector::TYPE_9_16; break; case cv::FastFeatureDetector::TYPE_7_12: neighbourhood = cv::FastFeatureDetector::TYPE_7_12; break; case cv::FastFeatureDetector::TYPE_5_8: neighbourhood = cv::FastFeatureDetector::TYPE_5_8; break; default: neighbourhood = cv::FastFeatureDetector::TYPE_9_16; break; } cv::xfeatures2d::FASTForPointSet(img, keypoints, threshold, nonmaxSuppression, neighbourhood); return keypoints_coords(keypoints); #endif } // [[Rcpp::export]] Rcpp::List cvkeypoints_harris(XPtrMat ptr, int numOctaves = 6, float corn_thresh = 0.01, float DOG_thresh = 0.01, int maxCorners = 5000, int num_layers = 4){ cv::Mat img; cv::cvtColor(get_mat(ptr), img, cv::COLOR_BGR2GRAY); std::vector keypoints; #ifndef HAVE_XFEATURES2D Rcpp::Rcout << "Keypoint detection disabled as module xfeatures2d from opencv_contrib is not present." << std::endl; return keypoints_coords(keypoints); #else auto featureDetector = cv::xfeatures2d::HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers); featureDetector->detect(img, keypoints); return keypoints_coords(keypoints); #endif } opencv/src/util.hpp0000644000176200001440000000045514435124332014026 0ustar liggesusers#include "opencv_types.h" void detectAndDraw( cv::Mat img, cv::CascadeClassifier& cascade, cv::CascadeClassifier& nestedCascade, double scale, bool tryflip ); cv::Mat get_mat(XPtrMat image); XPtrMat cvmat_xptr(cv::Mat *frame); XPtrMat cvmat_xptr(cv::Mat orig); opencv/src/qrdetect.cpp0000644000176200001440000000366614576574353014710 0ustar liggesusers#include "util.hpp" using namespace cv; #ifdef HAVE_WECHATQR #include static std::string qr_scan_wechat(XPtrMat ptr, Mat &points){ static wechat_qrcode::WeChatQRCode qrDet = wechat_qrcode::WeChatQRCode(); std::vector pointsvec; std::vector data = qrDet.detectAndDecode(get_mat(ptr), pointsvec); if(data.size() > 0){ points = pointsvec.at(0); return data.at(0); } return std::string(); } #endif static std::string qr_scan_opencv(XPtrMat ptr, Mat &points){ #ifdef HAVE_QUIRC static QRCodeDetector qrDet = QRCodeDetector(); return qrDet.detectAndDecode(get_mat(ptr), points); #else throw std::runtime_error("QR scanner requires OpenCV 3.4.4 or newer"); #endif } // [[Rcpp::export]] SEXP cvmat_qr_detect(XPtrMat ptr, bool return_image = false, bool use_wechat = true){ Mat points; #ifdef HAVE_WECHATQR std::string data = use_wechat ? qr_scan_wechat(ptr, points) : qr_scan_opencv(ptr, points); #else std::string data = qr_scan_opencv(ptr, points); #endif if(!data.length()) return R_NilValue; if(!use_wechat) points = points.reshape(1, 4); int len = points.size().height; Rcpp::IntegerMatrix corners(len, 2); for (int i = 0; i < len; i++) { Point pt = cv::Point(points.row(i)); corners[i] = pt.x; corners[i+len] = pt.y; } if(!return_image){ Rcpp::CharacterVector out(data); out.attr("points") = corners; return out; } cv::Mat img = get_mat(ptr); for (int i = 0; i < len; i++) { Point pt1 = cv::Point(points.row(i)); Point pt2 = cv::Point(points.row((i + 1) % 4)); line(img, pt1, pt2, Scalar(255, 0, 0), 3); } cv::putText(img, data, cv::Point(10, img.rows / 2), //left-middle position cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(118, 185, 0), //font color 2); ptr.attr("value") = Rcpp::CharacterVector::create(data); ptr.attr("points") = corners; return ptr; } opencv/src/enums.cpp0000644000176200001440000000543514435124332014176 0ustar liggesusers#include #include // [[Rcpp::export]] Rcpp::List enums_types(int maximum = 4){ std::vector key; std::vector value; #ifdef CV_8U key.push_back(CV_8U); value.push_back("CV_8U"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_8U, i)); value.push_back("CV_8U" + std::to_string(i)); } #endif #ifdef CV_8S key.push_back(CV_8S); value.push_back("CV_8S"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_8S, i)); value.push_back("CV_8S" + std::to_string(i)); } #endif #ifdef CV_16U key.push_back(CV_16U); value.push_back("CV_16U"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_16U, i)); value.push_back("CV_16U" + std::to_string(i)); } #endif #ifdef CV_16S key.push_back(CV_16S); value.push_back("CV_16S"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_16S, i)); value.push_back("CV_16S" + std::to_string(i)); } #endif #ifdef CV_16F key.push_back(CV_16F); value.push_back("CV_16F"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_16F, i)); value.push_back("CV_16F" + std::to_string(i)); } #endif #ifdef CV_32S key.push_back(CV_32S); value.push_back("CV_32S"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_32S, i)); value.push_back("CV_32S" + std::to_string(i)); } #endif #ifdef CV_32F key.push_back(CV_32F); value.push_back("CV_32F"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_32F, i)); value.push_back("CV_32F" + std::to_string(i)); } #endif #ifdef CV_64F key.push_back(CV_64F); value.push_back("CV_64F"); for(int i = 1; i <= maximum; i++){ key.push_back(CV_MAKETYPE(CV_64F, i)); value.push_back("CV_64F" + std::to_string(i)); } #endif Rcpp::List out = Rcpp::List::create(Rcpp::Named("key") = key, Rcpp::Named("value") = value); return out; } // [[Rcpp::export]] Rcpp::List enums_depth(){ std::vector key; std::vector value; #ifdef CV_8U key.push_back(CV_8U); value.push_back("CV_8U"); #endif #ifdef CV_8S key.push_back(CV_8S); value.push_back("CV_8S"); #endif #ifdef CV_16U key.push_back(CV_16U); value.push_back("CV_16U"); #endif #ifdef CV_16S key.push_back(CV_16S); value.push_back("CV_16S"); #endif #ifdef CV_16F key.push_back(CV_16F); value.push_back("CV_16F"); #endif #ifdef CV_32S key.push_back(CV_32S); value.push_back("CV_32S"); #endif #ifdef CV_32F key.push_back(CV_32F); value.push_back("CV_32F"); #endif #ifdef CV_64F key.push_back(CV_64F); value.push_back("CV_64F"); #endif Rcpp::List out = Rcpp::List::create(Rcpp::Named("key") = key, Rcpp::Named("value") = value); return out; } opencv/src/version.cpp0000644000176200001440000000017314435124332014526 0ustar liggesusers#include #include // [[Rcpp::export]] std::string cvversion(){ return CV_VERSION; } opencv/src/points.cpp0000644000176200001440000000104014435124332014347 0ustar liggesusers#include "util.hpp" using namespace cv; using namespace std; // [[Rcpp::export]] XPtrMat cvmat_markers(XPtrMat ptr){ Mat gray; Mat image = get_mat(ptr); cvtColor(image, gray, COLOR_BGR2GRAY); vector points; goodFeaturesToTrack(gray, points, 500, 0.01, 10); TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,20,0.03); cornerSubPix(gray, points, Size(10,10), Size(-1,-1), termcrit); for(size_t i = 0; i < points.size(); i++ ) { circle( image, points[i], 3, Scalar(0,255,0), -1, 8); } return ptr; } opencv/src/Makevars.in0000644000176200001440000000013114772462425014444 0ustar liggesusersPKG_CPPFLAGS=@cflags@ PKG_LIBS=@libs@ all: cleanup cleanup: $(SHLIB) @rm -Rf ../.deps opencv/src/areas.cpp0000644000176200001440000000537714435124332014147 0ustar liggesusers#include "util.hpp" #include #include std::vector as_points(Rcpp::List pts){ std::vector points; std::vector x = Rcpp::as>(pts["x"]); std::vector y = Rcpp::as>(pts["y"]); for (size_t i = 0; i < x.size(); ++i){ cv::Point2i pt(x[i], y[i]); points.push_back(pt); } return points; } Rcpp::List points_coords(const std::vector& pts){ std::vector x; std::vector y; for (size_t i = 0; i < pts.size(); ++i){ x.push_back(pts[i].x); y.push_back(pts[i].y); } Rcpp::List out = Rcpp::List::create(Rcpp::Named("x") = x, Rcpp::Named("y") = y); return out; } // [[Rcpp::export]] XPtrMat cvmat_rect(XPtrMat ptr, int x = 0, int y = 0, int width = 0, int height = 0){ cv::Mat img = get_mat(ptr); cv::Rect roi = cv::Rect(x, y, width, height); cv::Mat output = img(roi); return cvmat_xptr(output); } // [[Rcpp::export]] XPtrMat cvmat_bbox(XPtrMat ptr){ #ifndef HAVE_OPENCV_3 Rcpp::Rcout << "ocv_bbox works only if you provide points in your version of opencv, returning original image" << std::endl; return ptr; #else cv::Mat img = get_mat(ptr); cv::Mat output; cv::Rect roi; if(img.channels() > 1){ cv::Mat img_gray; cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); roi = cv::boundingRect(img_gray); }else{ roi = cv::boundingRect(img); } output = img(roi); return cvmat_xptr(output); #endif } // [[Rcpp::export]] XPtrMat cvpoints_bbox(XPtrMat ptr, Rcpp::List pts){ cv::Mat img = get_mat(ptr); auto points = as_points(pts); cv::Rect roi = cv::boundingRect(points); cv::Mat output = img(roi); return cvmat_xptr(output); } // [[Rcpp::export]] Rcpp::List cvpoints_chull(Rcpp::List pts){ std::vector points = as_points(pts); if(points.size() == 0){ return points_coords(points); } std::vector points_chull; cv::convexHull(points, points_chull); return points_coords(points_chull); } // [[Rcpp::export]] XPtrMat cvmat_polygon(XPtrMat ptr, Rcpp::List pts, bool convex = false, bool crop = false, int color = 255){ auto points = as_points(pts); cv::Mat img = get_mat(ptr); cv::Mat mask = cv::Mat::zeros(img.rows, img.cols, CV_8U); if(convex){ cv::fillConvexPoly(mask, points, cv::Scalar(255, 255, 255)); }else{ std::vector> polygons; polygons.push_back(points); cv::fillPoly(mask, polygons, cv::Scalar(255, 255, 255)); } cv::Mat area(img.rows, img.cols, img.type()); area.setTo(cv::Scalar(color, color, color)); img.copyTo(area, mask); if(crop){ cv::Rect roi = cv::boundingRect(points); return cvmat_xptr(area(roi)); } return cvmat_xptr(area); } opencv/src/opencv_types.h0000644000176200001440000000116614576574353015251 0ustar liggesusers#define R_NO_REMAP #define STRICT_R_HEADERS #include #include #if CV_VERSION_EPOCH >= 3 || (!defined(CV_VERSION_EPOCH) && CV_VERSION_MAJOR >= 3) #define HAVE_OPENCV_3 #endif #if !defined(CV_VERSION_EPOCH) && CV_VERSION_MAJOR >= 4 #define HAVE_OPENCV_4 #endif #if (CV_VERSION_MAJOR * 100 + CV_VERSION_MINOR * 10 + CV_VERSION_REVISION >= 452) #define HAVE_WECHATQR #endif #if (CV_VERSION_MAJOR * 100 + CV_VERSION_MINOR * 10 + CV_VERSION_REVISION >= 344) #define HAVE_QUIRC #endif void finalize_mat(cv::Mat * frame); typedef Rcpp::XPtr XPtrMat; opencv/src/color.cpp0000644000176200001440000000027214435124332014157 0ustar liggesusers#include "util.hpp" // [[Rcpp::export]] XPtrMat cvmat_grayscale(XPtrMat src){ cv::Mat output; cv::cvtColor(get_mat(src), output, cv::COLOR_BGR2GRAY); return cvmat_xptr(output); } opencv/src/base.cpp0000644000176200001440000001373714576572451014004 0ustar liggesusers#include "util.hpp" #define xstr(s) str(s) #define str(s) #s using namespace cv; void finalize_mat( cv::Mat * frame ){ delete frame; frame = NULL; } //assume ownership XPtrMat cvmat_xptr(cv::Mat *frame){ XPtrMat ptr(frame); ptr.attr("class") = Rcpp::CharacterVector::create("opencv-image"); return ptr; } //copy from stack to heap XPtrMat cvmat_xptr(cv::Mat orig){ cv::Mat * frame = new cv::Mat(); orig.copyTo(*frame); return cvmat_xptr(frame); } //opencv has internal refcount system cv::Mat get_mat(XPtrMat image){ if(!image.inherits("opencv-image")) throw std::runtime_error("Image is not a opencv-image object"); if(image.get() == NULL) throw std::runtime_error("Image has been destroyed"); return * image.get(); } // [[Rcpp::export]] void cvmat_destroy(XPtrMat image){ if(!image.inherits("opencv-image")) throw std::runtime_error("Image is not a opencv-image object"); image.release(); } // [[Rcpp::export]] bool cvmat_dead(XPtrMat image){ return image.get() == NULL; } // [[Rcpp::export]] int cvmat_size(XPtrMat image){ return image->channels(); } // [[Rcpp::export]] XPtrMat cvmat_new(){ cv::Mat * frame = new cv::Mat(); return cvmat_xptr(frame); } // [[Rcpp::export]] XPtrMat cvmat_dupe(XPtrMat image){ return cvmat_xptr(get_mat(image)); } // [[Rcpp::export]] XPtrMat cvmat_read(Rcpp::String path){ const cv::String filename(path); cv::Mat frame = imread(filename); if(frame.empty()) throw std::runtime_error("Failed to read file"); return cvmat_xptr(frame); } // [[Rcpp::export]] XPtrMat cvmat_camera(){ VideoCapture cap(0); if(!cap.isOpened()) throw std::runtime_error("Failed to start Camera"); Mat frame; cap >> frame; cap >> frame; cap.release(); return cvmat_xptr(frame); } // [[Rcpp::export]] std::string cvmat_write(XPtrMat image, std::string path){ const cv::String filename(path); imwrite(filename, get_mat(image)); return path; } // [[Rcpp::export]] XPtrMat cvmat_resize(XPtrMat ptr, int width = 0, int height = 0){ cv::Mat input = get_mat(ptr); if(!width && !height){ width = input.cols; height = input.rows; } else if(width && !height){ height = round(input.rows * (width / double(input.cols))); } else if(!width && height){ width = round(input.cols * (height / double(input.rows))); } cv::Mat output; cv::resize(input, output, cv::Size(width, height)); return cvmat_xptr(output); } // [[Rcpp::export]] XPtrMat cvmat_raw_bgr(Rcpp::RawVector image, int width = 0, int height = 0){ // 8bit Blue Green Red if(image.length() != width * height * 3){ throw std::runtime_error("cvmat_raw_bgr requires data with 3 channels"); } std::vector x = Rcpp::as>(image); cv::Mat output(height, width, CV_8UC3, x.data()); return cvmat_xptr(output); } // [[Rcpp::export]] XPtrMat cvmat_raw_bw(Rcpp::RawVector image, int width = 0, int height = 0){ // 8bit 1 channel (e.g. Black/White or Greyscale) if(image.length() != width * height * 1){ throw std::runtime_error("cvmat_raw_bw requires data with 1 channel (e.g. grey or just black/white)"); } std::vector x = Rcpp::as>(image); cv::Mat output(height, width, CV_8U, x.data()); return cvmat_xptr(output); } // [[Rcpp::export]] Rcpp::RawVector cvmat_bitmap(XPtrMat ptr){ cv::Mat output; cv::Mat input = get_mat(ptr); cvtColor(input, output, COLOR_BGR2RGB); size_t size = output.total(); size_t channels = output.channels(); Rcpp::RawVector res(size * channels); std::memcpy(res.begin(), output.datastart, size * channels); res.attr("dim") = Rcpp::NumericVector::create(channels, output.cols, output.rows); return res; } // [[Rcpp::export]] XPtrMat cvmat_copyto(XPtrMat from, XPtrMat to, XPtrMat mask) { XPtrMat out = cvmat_xptr(get_mat(to)); get_mat(from).copyTo(get_mat(out), get_mat(mask)); return out; } // [[Rcpp::export]] Rcpp::List cvmat_info(XPtrMat image){ return Rcpp::List::create( Rcpp::_["width"] = get_mat(image).cols, Rcpp::_["height"] = get_mat(image).rows, Rcpp::_["channels"] = get_mat(image).channels(), Rcpp::_["depth"] = get_mat(image).depth(), Rcpp::_["type"] = get_mat(image).type() ); } // [[Rcpp::export]] void cvmat_display(XPtrMat ptr){ namedWindow("mywindow", 1); imshow("mywindow", get_mat(ptr)); try { while(true) { if(waitKey(30) >= 0 || cv::getWindowProperty("mywindow", 0) < 0) break; Rcpp::checkUserInterrupt(); } } catch(Rcpp::internal::InterruptedException e) { } cv::destroyWindow("mywindow"); cv::waitKey(1); } static void stop_video(VideoCapture &cap){ cap.release(); cv::destroyWindow("mywindow"); cv::waitKey(1); } // [[Rcpp::export]] Rcpp::RObject livestream(Rcpp::Function filter, bool stop_on_result = false){ VideoCapture cap(0); if(!cap.isOpened()) throw std::runtime_error("Failed to open Camera"); Mat image; namedWindow("mywindow", 1); Rcpp::RObject out = R_NilValue; try { for(int i = 0;;i++) { cap >> image; Rcpp::RObject val = filter(cvmat_xptr(image)); if(stop_on_result){ if(val != R_NilValue){ out = val; stop_video(cap); break; } imshow("mywindow", image); } else { if(val.inherits("opencv-image")){ imshow("mywindow", get_mat(XPtrMat(val))); } else { REprintf("\rFilter function did not return opencv-image object. Showing input image. (%d)", i); imshow("mywindow", image); } } if(waitKey(30) >= 0 || cv::getWindowProperty("mywindow", 0) < 0) break; Rcpp::checkUserInterrupt(); } } catch(Rcpp::internal::InterruptedException e) { stop_video(cap); } catch(std::exception& e) { stop_video(cap); throw e; } return out; } // [[Rcpp::export]] Rcpp::String data_prefix(){ #ifdef _DATA_PREFIX return Rcpp::String(xstr(_DATA_PREFIX)); #endif return Rcpp::String("/usr"); } // [[Rcpp::export]] int set_num_threads(int n = 0){ if(n > 0) setNumThreads(n); return getNumThreads(); } opencv/src/face.cpp0000644000176200001440000000557414435124332013751 0ustar liggesusers#include "util.hpp" using namespace cv; // [[Rcpp::export]] XPtrMat cvmat_face(XPtrMat ptr, const char * facedata, const char * eyedata){ /* load training data */ CascadeClassifier face, eyes; if(!face.load( facedata )) throw std::runtime_error(std::string("Failed to load: ") + facedata); if(!eyes.load( eyedata )) throw std::runtime_error(std::string("Failed to load: ") + eyedata); //modify in place detectAndDraw(get_mat(ptr), face, eyes, 1, 0); return ptr; } // [[Rcpp::export]] XPtrMat cvmat_facemask(XPtrMat ptr, const char * facedata){ /* load training data */ CascadeClassifier face; if(!face.load( facedata )) throw std::runtime_error(std::string("Failed to load: ") + facedata); Mat gray; Mat input = get_mat(ptr); cvtColor( input, gray, COLOR_BGR2GRAY ); equalizeHist(gray, gray); std::vector faces; face.detectMultiScale( gray, faces, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH |CASCADE_SCALE_IMAGE, Size(30, 30) ); Mat mask(gray.size(), gray.type(), Scalar::all(0)); Rcpp::IntegerVector rvec(faces.size()); Rcpp::IntegerVector xvec(faces.size()); Rcpp::IntegerVector yvec(faces.size()); for ( size_t i = 0; i < faces.size(); i++ ) { Point center; Rect r = faces.at(i); center.x = cvRound((r.x + r.width*0.5)); center.y = cvRound((r.y + r.height*0.5)); int radius = cvRound((r.width + r.height)*0.25); circle( mask, center, radius, Scalar::all(255), -1); rvec.at(i) = radius; xvec.at(i) = center.x; yvec.at(i) = center.y; } XPtrMat out = cvmat_xptr(mask); out.attr("faces") = Rcpp::DataFrame::create( Rcpp::_["radius"] = rvec, Rcpp::_["x"] = xvec, Rcpp::_["y"] = yvec ); return out; } // [[Rcpp::export]] XPtrMat cvmat_mog2(XPtrMat ptr) { #ifndef HAVE_OPENCV_3 throw std::runtime_error("createBackgroundSubtractorMOG2 requires OpenCV 3 or newer"); #else static Ptr model = createBackgroundSubtractorMOG2(); model->setVarThreshold(10); cv::Mat frame = get_mat(ptr); cv::Mat mask, out_frame; model->apply(frame, mask); //refineSegments(frame, mask, out_frame); return cvmat_xptr(mask); #endif } // [[Rcpp::export]] XPtrMat cvmat_knn(XPtrMat ptr) { #ifndef HAVE_OPENCV_3 throw std::runtime_error("createBackgroundSubtractorKNN requires OpenCV 3 or newer"); #else static Ptr model = createBackgroundSubtractorKNN(); cv::Mat frame = get_mat(ptr); cv::Mat mask, out_frame; model->apply(frame, mask); return cvmat_xptr(mask); #endif } // [[Rcpp::export]] XPtrMat cvmat_edges(XPtrMat ptr) { cv::Mat edges; cv::Mat frame = get_mat(ptr); cvtColor(frame, edges, COLOR_BGR2GRAY); GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); Canny(edges, edges, 0, 30, 3); return cvmat_xptr(edges); } opencv/NAMESPACE0000644000176200001440000000131114576572451012777 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(print,"opencv-image") export("%>%") export(ocv_bbox) export(ocv_bitmap) export(ocv_blur) export(ocv_chull) export(ocv_copyto) export(ocv_destroy) export(ocv_display) export(ocv_edges) export(ocv_face) export(ocv_facemask) export(ocv_grayscale) export(ocv_hog) export(ocv_info) export(ocv_keypoints) export(ocv_knn) export(ocv_markers) export(ocv_mog2) export(ocv_picture) export(ocv_polygon) export(ocv_qr_detect) export(ocv_read) export(ocv_rectangle) export(ocv_resize) export(ocv_sketch) export(ocv_stylize) export(ocv_version) export(ocv_video) export(ocv_write) export(qr_scanner) importFrom(Rcpp,sourceCpp) importFrom(magrittr,"%>%") useDynLib(opencv) opencv/LICENSE0000644000176200001440000000005114435124332012546 0ustar liggesusersYEAR: 2022 COPYRIGHT HOLDER: Jeroen Ooms opencv/tools/0000755000176200001440000000000014576572451012724 5ustar liggesusersopencv/tools/winlibs.R0000644000176200001440000000161214772464170014512 0ustar liggesusersif(!file.exists("../.deps/opencv/include/opencv4/opencv2/opencv.hpp")){ unlink("../.deps", recursive = TRUE) url <- if(grepl("aarch", R.version$platform)){ "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-clang-aarch64.tar.xz" } else if(grepl("clang", Sys.getenv('R_COMPILED_BY'))){ "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-clang-x86_64.tar.xz" } else if(getRversion() >= "4.3") { "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-ucrt-x86_64.tar.xz" } else { "https://github.com/rwinlib/opencv/archive/refs/tags/v4.8.1.tar.gz" } download.file(url, basename(url), quiet = TRUE) dir.create("../.deps", showWarnings = FALSE) untar(basename(url), exdir = "../.deps", tar = 'internal') unlink(basename(url)) setwd("../.deps") file.rename(list.files(), 'opencv') } opencv/configure0000755000176200001440000000750214772474025013473 0ustar liggesusers#!/bin/sh # Anticonf (tm) script by Jeroen Ooms (2020) PKG_CONFIG_NAME="opencv4" PKG_CONFIG_NAME_ALT="opencv" PKG_DEB_NAME="libopencv-dev" PKG_RPM_NAME="opencv-devel" PKG_BREW_NAME="opencv" PKG_TEST_HEADER="" PKG_TEST_HEADER_XFEATURES2D="" PKG_LIBS="-lopencv_{stitching,superres,videostab,aruco,bgsegm,bioinspired,ccalib,dnn_objdetect,\ dpm,face,photo,fuzzy,hfs,img_hash,line_descriptor,optflow,reg,rgbd,saliency,stereo,structured_light,\ phase_unwrapping,surface_matching,tracking,datasets,dnn,plot,xfeatures2d,shape,video,ml,ximgproc,\ calib3d,features2d,highgui,videoio,flann,xobjdetect,imgcodecs,objdetect,xphoto,imgproc,core}" # For debugging opencv3 in macos: #export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig" # Use pkg-config if available PCVERSION=`pkg-config --version 2>/dev/null` if [ $? -eq 0 ]; then echo "This is pkg-config $PCVERSION" if pkg-config --exists ${PKG_CONFIG_NAME} ; then PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME}` PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME}` PKGCONFIG_PREFIX=`pkg-config --variable=prefix ${PKG_CONFIG_NAME}` elif pkg-config --exists ${PKG_CONFIG_NAME_ALT}; then PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME_ALT}` PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME_ALT}` PKGCONFIG_PREFIX=`pkg-config --variable=prefix ${PKG_CONFIG_NAME_ALT}` fi fi # Note that cflags may be empty in case of success if [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then echo "Found pkg-config cflags and libs!" PKG_CFLAGS=${PKGCONFIG_CFLAGS} PKG_LIBS=${PKGCONFIG_LIBS} if [ "$PKGCONFIG_PREFIX" ]; then PKG_CFLAGS="$PKG_CFLAGS -D_DATA_PREFIX=${PKGCONFIG_PREFIX}" fi elif [ `uname` = "Darwin" ]; then test ! "$CI" && brew --version 2>/dev/null if [ $? -eq 0 ]; then BREWDIR=`brew --prefix` PKG_CFLAGS="-I$BREWDIR/opt/opencv/include" PKG_LIBS="-L$BREWDIR/opt/opencv/lib $PKG_LIBS" else curl -sfL "https://autobrew.github.io/scripts/opencv" > autobrew . ./autobrew fi fi # For debugging echo "Using PKG_CFLAGS=$PKG_CFLAGS" echo "Using PKG_LIBS=$PKG_LIBS" # Use CXX17 if available (preferred for recent opencv) CXX17=`${R_HOME}/bin/R CMD config CXX17` || unset CXX17 if [ "$CXX17" ]; then echo "Found C++17 compiler: $CXX17" CXXVER=CXX17 else echo "Using C++11 compiler" CXXVER=CXX11 fi CXX=$($R_HOME/bin/R CMD config ${CXXVER}) CXXSTD=$($R_HOME/bin/R CMD config ${CXXVER}STD) CXXFLAGS="$($R_HOME/bin/R CMD config ${CXXVER}FLAGS)" CPPFLAGS="$($R_HOME/bin/R CMD config CPPFLAGS)" CXXCPP="$CXX $CXXSTD -E" # Test configuration echo "#include $PKG_TEST_HEADER" | ${CXXCPP} ${CPPFLAGS} ${PKG_CFLAGS} ${CXXFLAGS} -xc++ - >/dev/null 2>configure.log if [ $? -ne 0 ]; then echo "-----------------------------[ ANTICONF ]-------------------------------" echo "Configuration failed to find $PKG_CONFIG_NAME library. Try installing:" echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)" echo " * rpm: $PKG_RPM_NAME (Fedora, CentOS, RHEL)" echo " * brew: $PKG_BREW_NAME (Mac OSX)" echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your" echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file." echo "---------------------------[ ERROR MESSAGE ]----------------------------" cat configure.log echo "------------------------------------------------------------------------" exit 1 fi echo "#include $PKG_TEST_HEADER_XFEATURES2D" | ${CXXCPP} ${CPPFLAGS} ${PKG_CFLAGS} ${CXXFLAGS} -xc++ - >/dev/null 2>>configure.log if [ $? -ne 0 ]; then echo "Module $PKG_TEST_HEADER_XFEATURES2D has not been found on your system, disabling keypoint detection." else PKG_CFLAGS="$PKG_CFLAGS -DHAVE_XFEATURES2D" fi # Write to Makevars sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" -e "s|CXX11|${CXXVER}|" src/Makevars.in > src/Makevars # Success exit 0 opencv/man/0000755000176200001440000000000014576572451012337 5ustar liggesusersopencv/man/opencv-area.Rd0000644000176200001440000000312614435124332015011 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/areas.R \name{opencv-area} \alias{opencv-area} \alias{ocv_rectangle} \alias{ocv_polygon} \alias{ocv_bbox} \alias{ocv_chull} \title{OpenCV area manipulation} \usage{ ocv_rectangle(image, x = 0L, y = 0L, width, height) ocv_polygon(image, pts, convex = FALSE, crop = FALSE, color = 255) ocv_bbox(image, pts) ocv_chull(pts) } \arguments{ \item{image}{an ocv image object} \item{x}{horizontal location} \item{y}{vertical location} \item{width}{width of the area} \item{height}{height of the area} \item{pts}{a list of points with elements x and y} \item{convex}{are the points convex} \item{crop}{crop the resulting area to its bounding box} \item{color}{color for the non-polygon area} } \description{ Manipulate image regions } \examples{ mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') # Rectangular area ocv_rectangle(mona, x = 400, y = 300, height = 300, width = 350) ocv_rectangle(mona, x = 0, y = 100, height = 200) ocv_rectangle(mona, x = 500, y = 0, width = 75) # Polygon area img <- ocv_resize(mona, width = 320, height = 477) pts <- list(x = c(184, 172, 146, 114, 90, 76, 92, 163, 258), y = c(72, 68, 70, 90, 110, 398, 412, 385, 210)) ocv_polygon(img, pts) ocv_polygon(img, pts, crop = TRUE) ocv_polygon(img, pts, convex = TRUE, crop = TRUE) # Bounding box based on points ocv_bbox(img, pts) # Bounding box of non-zero pixel area area <- ocv_polygon(img, pts, color = 0, crop = FALSE) area area <- ocv_bbox(area) area \dontshow{ ocv_destroy(mona) ocv_destroy(img) ocv_destroy(area) } } opencv/man/qrcode.Rd0000644000176200001440000000350114576572451014102 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/qr.R \name{ocv_qr_detect} \alias{ocv_qr_detect} \alias{qr_scanner} \title{Detect and Decode a QR code} \usage{ ocv_qr_detect(image, draw = FALSE, decoder = c("wechat", "quirc")) qr_scanner(draw = FALSE, decoder = c("wechat", "quirc")) } \arguments{ \item{image}{an ocv image object created from e.g. \code{\link[=ocv_read]{ocv_read()}}} \item{draw}{if TRUE, the function returns an annotated image showing the position and value of the QR code.} \item{decoder}{which decoder implementation to use, see details.} } \value{ if a QR code is detected, this returns either the text value of the QR, or if \code{draw} it returns the annotated image, with the value as an attribute. Returns NULL if no QR was found in the image. } \description{ Detect and decode a QR code from an image or camera. By default it returns the text value from the QR code if detected, or NULL if no QR was found. If \code{draw = TRUE} then it returns an annotated image with the position and value of the QR drawn into the image, and qr text value as an attribute. The \code{qr_scanner} function opens the camera device (if available on your computer) and repeats \link{ocv_qr_detect} until it a QR is detected. } \details{ OpenCV has two separate QR decoders. The 'wechat' decoder was added in libopencv 4.5.2 and generally has better performance and fault-tolerance. The old 'quirc' decoder is available on some older versions of libopencv as a plug-in, but many Linux distros did not include it. If you get an error \emph{Library QUIRC is not linked. No decoding is performed.} this sadly means your Linux distribution is too old and does not support QR decoding. } \examples{ png("test.png") plot(qrcode::qr_code("This is a test")) dev.off() ocv_qr_detect(ocv_read('test.png')) unlink("test.png") } opencv/man/reexports.Rd0000644000176200001440000000062014435124332014640 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/opencv.R \docType{import} \name{reexports} \alias{reexports} \alias{\%>\%} \title{Objects exported from other packages} \keyword{internal} \description{ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} }} opencv/man/opencv.Rd0000644000176200001440000000415114576572451014121 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/face.R, R/opencv.R \name{ocv_face} \alias{ocv_face} \alias{ocv_facemask} \alias{ocv_read} \alias{ocv_write} \alias{ocv_destroy} \alias{ocv_bitmap} \alias{ocv_edges} \alias{ocv_picture} \alias{ocv_resize} \alias{ocv_mog2} \alias{ocv_knn} \alias{ocv_hog} \alias{ocv_blur} \alias{ocv_sketch} \alias{ocv_stylize} \alias{ocv_markers} \alias{ocv_info} \alias{ocv_copyto} \alias{ocv_display} \alias{ocv_video} \alias{ocv_grayscale} \alias{ocv_version} \title{OpenCV Computer Vision} \usage{ ocv_face(image) ocv_facemask(image) ocv_read(path) ocv_write(image, path) ocv_destroy(image) ocv_bitmap(image) ocv_edges(image) ocv_picture() ocv_resize(image, width = 0, height = 0) ocv_mog2(image) ocv_knn(image) ocv_hog(image) ocv_blur(image, ksize = 5) ocv_sketch(image, color = TRUE) ocv_stylize(image) ocv_markers(image) ocv_info(image) ocv_copyto(image, target, mask) ocv_display(image) ocv_video(filter, stop_on_result = FALSE) ocv_grayscale(image) ocv_version() } \arguments{ \item{image}{an ocv image object created from e.g. \code{\link[=ocv_read]{ocv_read()}}} \item{path}{image file such as png or jpeg} \item{width}{output width in pixels} \item{height}{output height in pixels} \item{ksize}{size of blurring matrix} \item{color}{true or false} \item{target}{the output image} \item{mask}{only copy pixels from the mask} \item{filter}{an R function that takes and returns an opecv image} \item{stop_on_result}{stop if an object is detected} } \description{ Tools to experiment with computer vision algorithms. Use \link{ocv_read} and \link{ocv_write} to load/save images on disk, or use \link{ocv_picture} / \link{ocv_video} to use your webcam. In RSudio IDE the image objects will automatically be displayed in the viewer pane. } \examples{ # Silly example mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') # Edge detection ocv_edges(mona) ocv_markers(mona) # Find face faces <- ocv_face(mona) # To show locations of faces facemask <- ocv_facemask(mona) attr(facemask, 'faces') # This is not strictly needed ocv_destroy(mona) } opencv/man/ocv_keypoints.Rd0000644000176200001440000000324014435124332015502 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/keypoints.R \name{ocv_keypoints} \alias{ocv_keypoints} \title{OpenCV keypoints} \usage{ ocv_keypoints( image, method = c("FAST", "Harris"), control = ocv_keypoints_options(method, ...), ... ) } \arguments{ \item{image}{an ocv grayscale image object} \item{method}{the type of keypoint detection algorithm} \item{control}{a list of arguments passed on to the algorithm} \item{...}{further arguments passed on to ocv_keypoints_options} } \description{ Find key points in images } \section{FAST algorithm arguments}{ \itemize{ \item threshold threshold on difference between intensity of the central pixel and pixels of a circle around this pixel. \item nonmaxSuppression if true, non-maximum suppression is applied to detected corners (keypoints). \item type one of the three neighborhoods as defined in the paper: TYPE_9_16, TYPE_7_12, TYPE_5_8 } } \section{Harris algorithm arguments}{ \itemize{ \item numOctaves the number of octaves in the scale-space pyramid \item corn_thresh the threshold for the Harris cornerness measure \item DOG_thresh the threshold for the Difference-of-Gaussians scale selection \item maxCorners the maximum number of corners to consider \item num_layers the number of intermediate scales per octave } } \examples{ mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') mona <- ocv_resize(mona, width = 320, height = 477) # FAST-9 pts <- ocv_keypoints(mona, method = "FAST", type = "TYPE_9_16", threshold = 40) # Harris pts <- ocv_keypoints(mona, method = "Harris", maxCorners = 50) # Convex Hull of points pts <- ocv_chull(pts) \dontshow{ ocv_destroy(mona) } } opencv/man/figures/0000755000176200001440000000000014435124332013764 5ustar liggesusersopencv/man/figures/logo.png0000644000176200001440000003330714435124332015440 0ustar liggesusersPNG  IHDRH/ pHYs%%IR$sRGBgAMA a6\IDATxrǝ./A:mَ8;#ftfB&l.̆X+4W-v PȚ&KG5俺[n::3E@;V}Ke)@uqyj O8PBgR}?TA[ڽ)-H?̟b! -17z]9€$kE {yj*F°, M50?a`"T38/(&0oo@dIsy\JaIvbpfPDe2&;oC^Qk揽8EjU%€lIzbI4lpD`@42RĀlISzXBQQ*^ Ȗ(_|&}}%Gwnr0}-ygѾo2blNO杋&!EI?5豂x2j2v #RLy9}AQb@Fh k!(EM|nvN-ܱa@~0b9 8<lbJ?*GzG?ePXAGN'd`S/ZAsdXADmBJ2P @0ǐ 2_Bǐ s ۛ 0 =yRWVQۇR9wꚦ]9ϼ( "Vā71 =S,ta};څ6b@zbl};>Lg seYn/6!6 rFlZ6 r8jM3|mo\iMtz1$ 4[_p%rRz Z,+expxHg< q +G"s# 4 ȦqZ`_Ai=^>,$q T=2ȥa ×ZݼV7EE'ك?V8<~uU -~W[-SbԈ-Pꞩ)9ee8/tF 13Mr3 !/Jc;. m|M5Ǿ ˢٚ>uy| ׶>bWs02Y*As44b6[MǷMcオӌbo%x(V zpFG+W|@(jԇҗ F֢ GiE_FWuE]M&+=Pcu˓EҤ˞Iyb!qu!dݴ^CTLV̎-BRdΜQE2ax ɼ@YaG σH/}QHF')ˠ `@dc$y4E!9L#. q=DyA%c@'~"53c$~' !M]AMm}~ L6RmǺ` F?c3f :P=W7Ǹ QQK["dFw[=>D®"Nub@Aށy/R% kƀBA[}|_d/0dT}C6D~*KAa@:6<7"Ņ4UԈu/ ~1 ]S:#zVU_I 󀷷0 ] އ%9PS'k(#醙e<qjÀtM%aRt껠0 ] Rop$ҵ< R!,o4>B%0+HMS+$ H"9DDs0 iB? J=f H"`G˧gՌ tH_ z >]$Wa^@SPm`/W]X ;f~%y߁6[>f H]p=0/:k@OY /}u φ0  *b*XAֈY`j Z?E־5ՆY r$חV^dA :(bW߯R!Tuc@" {vTu,jŀè3@42tUdQ=jCVd$;!7Z'^= ^&v Ⱥt]GЫGy-A֌Y$ix7~F0 =@nTMEuojǀʡ#f D@E|JT;dM`?~ _7 `_K}DA dAPCR?e屉x @`@IHp!YcbcC5*CdѬ-EP#uSx񑐼Q Og^܈Y=&hn6ⴆd[H)_elǀlH1ݜHU'xDTB?a@6ӎ;^ۛQꃖ٠Hz} hF@tϜYdâ"kr6Mb/`@.CU dI1`J7Ɛ2T% Ces^=Π^xgB\r54nD_Ah8rL&T4o}}\EG|BhB=_F %*h_T #R %+/KE}n7F>(XvǍb;A^a@z76=ĀMXl|rMk?1 =T7qN5TjʪH+7@^b@n<yWeU x0Gb@zY 6 ZnqQCNcv, f>%vi,%1 =5y*um9++qP& H;jr]d vŷߍs3U\b1b}k<#8j̏`ffX^uX(vRg[p 2a.ZRcxɅլs&. .~m3he8d`,n\j܎ӝ> ؘowz2Py ϓ43@8YXWŷ/r:| Ȁ$gTl-{SVd| ;4rI<3dAH~"90_L]X*l5)s%Dm8-VWtƯe%/#(rōddф~vf ( 0Zy?V{3f/w/aj$~^TIk]>ȉ_]MRt'J?RH)ϳ7ת5Ϳ4G$wo\Die@? ɳ3pI<,Wk AD^jE@j~Vk&Vò04?HAa`#ʀػ=rY5p2`KϺQNk4 ǣ9ԎZӜ^ьRڶz骐pLQ7&//<9;ah4lN(50S1W n o/aHƇWu>9G(2-rI'sibdi Ap`&L8lƾtn\R.YZA2GwXE ]G5j@;uN- {uc}fښ۵$ñ206șIcZoy20cu Һ$$ñFf`գ;dLfRTq :hF6AqZ[EO7mմ2O?U0Uñ>r:k:,BjLr9I@"q^ҘLa j|9im󭱬3LUzփ #&D?`sb!ܥ0Mɪ<)qsR,W6smZr2(բ-Le_ Q^?R@߱6 z3n,`LHcY)*_ : i3e5Ҹ́MJ@$NH6%3?{}|lZϰ̋Rh H6pXDeK_ iK֋>[և*ۆ 19x­zv- .]Au+W#ifhlJ!hϦasN|yjÅpݘCxy!L*itd`/I6˵PlZ6eXpg~d/aǩn(6!vcPbOξkz,HtEp vVyj@ji=:)o@D;m1`2 YYwN 5:q!\wbI{ϳB_Zҵ~9w$=O!d7#$n<ѹN_9u[Es\P UЫ{ce[ƵO\PM8EGm(DkהΩ7~zx?&HMG >!haUS9ޜ8BMEfnfٶ4uƝ:Ft%yl`Zy@Nl)"6V_9Ϭ 9$M`|o~;@&w)=HXf&ÜIJS'~f@xINԕqs/#bJQSo 8/8!g<2/Qا?;^]B8[=>`8}V^̑7E"NYO ֗cUkO1cmτPpqU5G/}iK+,tgH98wAfϮLa")N؆𐼮O~.6ƕNYP@Fټ6#ƟFFצ>}WU?~v.P4עj^s:Mk^)B' z̊ffC~0QgZNh8a%PW)M"2 7x邈+~!`EHġ}]_LG8sa(GXɄu {D eQ[(,#$78 ԇUlZ\suus+ -ĤL4yx t%m]Iמu'S9:sp?㦂ԏ#L ǖ Mw{ loM(SMy>AdZj$I zt IQyj@'  R@$i='t`'ε~gOvm!!l@\iM!UTf HҴ]e|ƀ aSQ H iPS"D tL8Fz+) Gt"E&E~]x_5d xtow%EŪPv`0UoCU}B:CKj@iW`'eD_oudTMlػ#s]dJ={*~-~WLG^#VuG{!wO/me?($ӬG:\Q:/kr(VxJr&sIK1&e/# Vr_~v5m *nyM92 y\` AYtEn^C9NM0j5U9"ۭh`J֦jS3= L9I3DB֖сqqs9u=|)Iȗ/>xETGusZȠG*H%J]Hz ֩/ثЫGaRmeuCo~F߄c!zƅͅe$aχ]3‹H^=QX@ÐjH#ڇz St2wF,mJ) z" o\6u{[ ugzߣp%˨ʈco訚ڦ*^E>gdZ2k'}t_DԞ47]'8l E,dR@$}|ZH6:u_%Mb`"#uԅU@|z?T;Z LGV !M4<;n&hQi* c釜Jz K~!ќ:['(fv^5vB bP&iK&Mu/_WaRHJheLl{;vd>d,$$Cjnc2ǝ<>+_{HHOrܬNORj!#~ I3}HJ7*bzP@ 2'y{;?r5t}.~d4x{^$q_!ESҏfߣ}}D~)2qˀqu5F E>j>K>+} GD s`zH@qfϐ2Qjj^OI3;YKj:3aTX2'7mgxß y2խ_khiҢi7g̮Hh:%2 ?Ny?高\/es'~dtTB5DHZtzMUs7. vp]TBьJ6ʬ_H3hiX& ջes\%~~4KL0ՖTW4k2T0DKKFxW`[f;>2c{rgªW߭y]src=<8\^O.{Sj<5a1 giz2UdCH͒鮘NǷj$7:*qU$U1opf*9r3)?TNS~ *˴:5 3ktJ)džǙH'S }*J[R8*J+Q=3U$qU$aF_;3-zbI%l=#T@J zC8%U$T𗆥f HFKrSȲM(j7gR8O9HzHͺBP/LW מ?ЪtyJq=><\ MUiUX1@g֍Sdt*KYd1`(ﴜM>dSL:Tu@ YFS)Iv{ +.W) +ONZEA޴>-f9j}R#ijsy$!4O*rGt؎ZP@;J.ZA}nKviӥbVP@Ⲟ=5q9I Z8 ūO,t2(sIGR9G$ ūOgN.vE( ʄ8 u%p3m8'pw>~E]G jcF SPPX,o}S. c5- C2)s.k4\*D snu9`NryϚgd{mrmJywMPԖ@jBm6!wG:_.T44657 e{,ֵQˠ&prI h]ðma8K43#MQSN:JOr䟎`?>BZ R|9?s/2OdJ1ޯYd}J~'7Ip=?)_`=s{ Ljه.c?e]\T5 JIA"S^ucz$c|pt=7Dq}ꚹ}>f>al_*j:g:"}?m;xdgǗ8}cNh R+7)fƞc`y{[pd򉛺(LO1e3^gbvs lbH'۬ҼVَм*A OHѲH~4uDl?{XP yJ "Y=]=V]`/cRY>o; l_{fvhg7oP&0>SF>O.8 6zpC6Oz]}ӽq.%Mަ)f!`{8yۂQ@|i}J>բS3&mJvmY>%bR,1e Kշg24.̈rۆ;r:v D~YdZ֜Y`YC״vU(~mTn)٧Ճ{~{M[X@ɦY䑋,=O-v2g;Gsglr@v*eLT%>un5zLbMQ iD~ݧF+۶|AT%IVeڂRؽ:[sk\AMOaM4&]\v'cz ˝ܾ:Ʉ1{U}!xz'O'_J,TY6Ғ`[SNʗ9@3N Lm{9(+tS1D 7} Asj~'IZwGલO-^Y56{[wgt&7%k;/3*{PE|{%w0؁{}CUGi;pSvbv_펽u%?O]mn-kI|l*Դ8=Գ0B3/>you/2,/u%gkƿm"p}.C%-NcP96cm_uven~?w2Yx:bv=ؿK-gW"~K,sz_Y5ޟMw,͚YW1=W_hBHQ}i/yWCӉC<L~Gmt'o) NJQMvSkzZ=حŐnfq_''`KѬ 1; w֑*!CnUy"UxS/k?&UN?pPs;M s]='[fǛuۂg!s^ Ť_i{ciGpVYHOyMClާhӬ|iBhbW>s`nW`^2G˰3yb|:fY2󕛼nO ?*&sſ-;@m : qQnN ö9чqռ 5.k INeGJ*`qgJv#cv-ﲺb\/NP=@ jz#e4J-Tg* #,WAVѢlFGu6gYGpK\Y4jgm&g/z* C}mOӖ fv "i9eeNzm:&436j;*e;߁;. a'ۦڄBgϰ!S~n~.},BHAGVGfq0\+ ќWGO m?-,fnCc`{"Z52"=(y_ Ӵ}X* C1O1@;1 ]6 mv M {C%D^ >mYYݤvЌ 4D; a/El_Xм ,|2DXZTEGl|edyض_(Ԣl?+ݦJё"|-SAf(3 Hguօ}L+ +n | >Cر#ft&il/0/ m5>kTC/Ƒy1Q0He[yۃtӭiLNÜk'a(ۙ{Bs2 mCHFpk{cL>0@@PLٜ 9[e@JU9w3Lagxl*6NU6 YX6߃#A¾Q,gQKsgUEKI33ÃibPq!T"v6À^2,/l*Y]h)ʷp贀2EUNC56v+n \DZ Uƪgs E ۨ ?Ӿ!s=Pݶa/C!iS=O!Uɵduu^u-SVJ咏ruVӒ>%-3xbH2P҃{;(z(plK߁TU_RNi6ܤV >p p4)]됖D6uTRtOO`FkQ)p|gmZ8^/r (ۧ3K'?'n'݃)r=e%NnarSUez;>'q~{(#2;awPkpwY>gݷܾN/S, ݁J$|^í숫ge~N=O|Oܽ-xNFvܗ2Z3½quO-zϟ㠬kķtLE5QyeЗ algorithms, such as a QR code scanner, and edge, body or face detection. These can either be applied to analyze static images, or to filter live video footage from a camera device. License: MIT + file LICENSE SystemRequirements: OpenCV 3 or newer: libopencv-dev (Debian, Ubuntu) or opencv-devel (Fedora). The QR code detector requires at least libopencv 4.5.2. URL: https://docs.ropensci.org/opencv/ https://ropensci.r-universe.dev/opencv BugReports: https://github.com/ropensci/opencv/issues LinkingTo: Rcpp Imports: Rcpp, magrittr Suggests: grDevices, qrcode, testthat (>= 3.0.0) Encoding: UTF-8 RoxygenNote: 7.2.3 Config/testthat/edition: 3 NeedsCompilation: yes Packaged: 2025-03-31 11:10:13 UTC; jeroen Author: Jeroen Ooms [aut, cre] (), Jan Wijffels [aut] Maintainer: Jeroen Ooms Repository: CRAN Date/Publication: 2025-03-31 11:40:02 UTC