From 3243fd8baa336c0ab1a2bafd151c078465eb7e3e Mon Sep 17 00:00:00 2001 From: stephon Date: Fri, 3 Sep 2021 07:13:51 +0000 Subject: [PATCH] rm origin file; and add resnet5_vd paddleserving examples --- deploy/paddleserving/README.md | 19 + deploy/paddleserving/README_CN.md | 147 +++ deploy/paddleserving/__init__.py | 0 deploy/paddleserving/config.yml | 33 + deploy/paddleserving/cpu_utilization.py | 4 + deploy/paddleserving/daisy.jpg | Bin 0 -> 39696 bytes deploy/paddleserving/image_http_client.py | 46 - deploy/paddleserving/image_service_cpu.py | 60 -- deploy/paddleserving/image_service_gpu.py | 62 -- deploy/paddleserving/imagenet.label | 1000 ++++++++++++++++++ deploy/paddleserving/pipeline_http_client.py | 19 + deploy/paddleserving/pipeline_rpc_client.py | 38 + deploy/paddleserving/resnet50_web_service.py | 73 ++ deploy/paddleserving/utils.py | 84 -- 14 files changed, 1333 insertions(+), 252 deletions(-) create mode 100644 deploy/paddleserving/README.md create mode 100644 deploy/paddleserving/README_CN.md create mode 100644 deploy/paddleserving/__init__.py create mode 100644 deploy/paddleserving/config.yml create mode 100644 deploy/paddleserving/cpu_utilization.py create mode 100644 deploy/paddleserving/daisy.jpg delete mode 100644 deploy/paddleserving/image_http_client.py delete mode 100644 deploy/paddleserving/image_service_cpu.py delete mode 100644 deploy/paddleserving/image_service_gpu.py create mode 100644 deploy/paddleserving/imagenet.label create mode 100644 deploy/paddleserving/pipeline_http_client.py create mode 100644 deploy/paddleserving/pipeline_rpc_client.py create mode 100644 deploy/paddleserving/resnet50_web_service.py delete mode 100644 deploy/paddleserving/utils.py diff --git a/deploy/paddleserving/README.md b/deploy/paddleserving/README.md new file mode 100644 index 00000000..d0fa99e6 --- /dev/null +++ b/deploy/paddleserving/README.md @@ -0,0 +1,19 @@ +# Imagenet Pipeline WebService + +This document will takes Imagenet service as an example to introduce how to use Pipeline WebService. + +## Get model +``` +sh get_model.sh +``` + +## Start server + +``` +python resnet50_web_service.py &>log.txt & +``` + +## RPC test +``` +python pipeline_rpc_client.py +``` diff --git a/deploy/paddleserving/README_CN.md b/deploy/paddleserving/README_CN.md new file mode 100644 index 00000000..5e2b0104 --- /dev/null +++ b/deploy/paddleserving/README_CN.md @@ -0,0 +1,147 @@ +# PaddleClas 服务化部署 + +([English](./README.md)|简体中文) + +PaddleClas提供2种服务部署方式: +- 基于PaddleHub Serving的部署:代码路径为"`./deploy/hubserving`",使用方法参考[文档](../../deploy/hubserving/readme.md); +- 基于PaddleServing的部署:代码路径为"`./deploy/paddleserving`",按照本教程使用。 + +# 基于PaddleServing的服务部署 + +本文档以经典的ResNet50_vd模型为例,介绍如何使用[PaddleServing](https://github.com/PaddlePaddle/Serving/blob/develop/README_CN.md)工具部署PaddleClas +动态图模型的pipeline在线服务。 + +相比较于hubserving部署,PaddleServing具备以下优点: +- 支持客户端和服务端之间高并发和高效通信 +- 支持 工业级的服务能力 例如模型管理,在线加载,在线A/B测试等 +- 支持 多种编程语言 开发客户端,例如C++, Python和Java + +更多有关PaddleServing服务化部署框架介绍和使用教程参考[文档](https://github.com/PaddlePaddle/Serving/blob/develop/README_CN.md)。 + +## 目录 +- [环境准备](#环境准备) +- [模型转换](#模型转换) +- [Paddle Serving pipeline部署](#部署) +- [FAQ](#FAQ) + + +## 环境准备 + +需要准备PaddleClas的运行环境和Paddle Serving的运行环境。 + +- 准备PaddleOCR的运行环境[链接](../../doc/doc_ch/installation.md) + 根据环境下载对应的paddle whl包,推荐安装2.0.1版本 + +- 准备PaddleServing的运行环境,步骤如下 + +1. 安装serving,用于启动服务 + ``` + pip3 install paddle-serving-server==0.6.1 # for CPU + pip3 install paddle-serving-server-gpu==0.6.1 # for GPU + # 其他GPU环境需要确认环境再选择执行如下命令 + pip3 install paddle-serving-server-gpu==0.6.1.post101 # GPU with CUDA10.1 + TensorRT6 + pip3 install paddle-serving-server-gpu==0.6.1.post11 # GPU with CUDA11 + TensorRT7 + ``` + +2. 安装client,用于向服务发送请求 + 在[下载链接](https://github.com/PaddlePaddle/Serving/blob/develop/doc/LATEST_PACKAGES.md)中找到对应python版本的client安装包,这里推荐python3.7版本: + + ``` + wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_client-0.0.0-cp37-none-any.whl + pip3 install paddle_serving_client-0.0.0-cp37-none-any.whl + ``` + +3. 安装serving-app + ``` + pip3 install paddle-serving-app==0.6.1 + ``` + **Note:** 如果要安装最新版本的PaddleServing参考[链接](https://github.com/PaddlePaddle/Serving/blob/develop/doc/LATEST_PACKAGES.md)。 + + +## 模型转换 + +使用PaddleServing做服务化部署时,需要将保存的inference模型转换为serving易于部署的模型。 + +首先,下载ResNet50_vd的[inference模型](https://github.com/PaddlePaddle/PaddleOCR#pp-ocr-20-series-model-listupdate-on-dec-15) +``` +# 下载并解压ResNet50_vd模型 +wget "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/inference/ResNet50_vd_infer.tar" && tar xf ResNet50_vd_infer.tar +``` + +接下来,用安装的paddle_serving_client把下载的inference模型转换成易于server部署的模型格式。 + +``` +# 转换ResNet50_vd模型 +python3 -m paddle_serving_client.convert --dirname ./inference/ \ + --model_filename inference.pdmodel \ \ + --params_filename inference.pdiparams \ \ + --serving_server ./ResNet50_vd_serving/ \ + --serving_client ./ResNet50_vd_client/ +``` +检测模型转换完成后,会在当前文件夹多出`ResNet50_vd_serving` 和`ResNet50_vd_client`的文件夹,具备如下格式: +``` +|- ResNet50_vd_client/ + |- __model__ + |- __params__ + |- serving_server_conf.prototxt + |- serving_server_conf.stream.prototxt + +|- ResNet50_vd_client + |- serving_client_conf.prototxt + |- serving_client_conf.stream.prototxt + +``` + + +## Paddle Serving pipeline部署 + +1. 下载PaddleClas代码,若已下载可跳过此步骤 + ``` + git clone https://github.com/PaddlePaddle/PaddleClas + + # 进入到工作目录 + cd PaddleOCR/deploy/paddleserving/ + ``` + pdserver目录包含启动pipeline服务和发送预测请求的代码,包括: + ``` + __init__.py + config.yml # 启动服务的配置文件 + pipeline_http_client.py # http方式发送pipeline预测请求的脚本 + pipeline_rpc_client.py # rpc方式发送pipeline预测请求的脚本 + resnet50_web_service.py # 启动pipeline服务端的脚本 + ``` + +2. 启动服务可运行如下命令: + ``` + # 启动服务,运行日志保存在log.txt + python3 resnet50_web_service.py &>log.txt & + ``` + 成功启动服务后,log.txt中会打印类似如下日志 + ![](./imgs/start_server.png) + +3. 发送服务请求: + ``` + python3 pipeline_http_client.py + ``` + 成功运行后,模型预测的结果会打印在cmd窗口中,结果示例为: + ![](./imgs/results.png) + + 调整 config.yml 中的并发个数获得最大的QPS, 一般检测和识别的并发数为2:1 + ``` + op: + #并发数,is_thread_op=True时,为线程并发;否则为进程并发 + concurrency: 8 + ... + 有需要的话可以同时发送多个服务请求 + + 预测性能数据会被自动写入 `PipelineServingLogs/pipeline.tracer` 文件中。 + + +## FAQ +**Q1**: 发送请求后没有结果返回或者提示输出解码报错 + +**A1**: 启动服务和发送请求时不要设置代理,可以在启动服务前和发送请求前关闭代理,关闭代理的命令是: +``` +unset https_proxy +unset http_proxy +``` diff --git a/deploy/paddleserving/__init__.py b/deploy/paddleserving/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/deploy/paddleserving/config.yml b/deploy/paddleserving/config.yml new file mode 100644 index 00000000..104504f4 --- /dev/null +++ b/deploy/paddleserving/config.yml @@ -0,0 +1,33 @@ +#worker_num, 最大并发数。当build_dag_each_worker=True时, 框架会创建worker_num个进程,每个进程内构建grpcSever和DAG +##当build_dag_each_worker=False时,框架会设置主线程grpc线程池的max_workers=worker_num +worker_num: 1 + +#http端口, rpc_port和http_port不允许同时为空。当rpc_port可用且http_port为空时,不自动生成http_port +http_port: 18080 +rpc_port: 9993 + +dag: + #op资源类型, True, 为线程模型;False,为进程模型 + is_thread_op: False +op: + imagenet: + #并发数,is_thread_op=True时,为线程并发;否则为进程并发 + concurrency: 1 + + #当op配置没有server_endpoints时,从local_service_conf读取本地服务配置 + local_service_conf: + + #uci模型路径 + model_config: ResNet50_vd/ppcls_model/ + + #计算硬件类型: 空缺时由devices决定(CPU/GPU),0=cpu, 1=gpu, 2=tensorRT, 3=arm cpu, 4=kunlun xpu + device_type: 1 + + #计算硬件ID,当devices为""或不写时为CPU预测;当devices为"0", "0,1,2"时为GPU预测,表示使用的GPU卡 + devices: "0" # "0,1" + + #client类型,包括brpc, grpc和local_predictor.local_predictor不启动Serving服务,进程内预测 + client_type: local_predictor + + #Fetch结果列表,以client_config中fetch_var的alias_name为准 + fetch_list: ["prediction"] diff --git a/deploy/paddleserving/cpu_utilization.py b/deploy/paddleserving/cpu_utilization.py new file mode 100644 index 00000000..984c7237 --- /dev/null +++ b/deploy/paddleserving/cpu_utilization.py @@ -0,0 +1,4 @@ +import psutil +cpu_utilization=psutil.cpu_percent(1,False) +print('CPU_UTILIZATION:', cpu_utilization) + diff --git a/deploy/paddleserving/daisy.jpg b/deploy/paddleserving/daisy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7edeca63e5f32e68550ef720d81f59df58a8eabc GIT binary patch literal 39696 zcmb4qRa9I}(Cy$u&>=vO!3US%FgU^8T>`;mHi?MmxWj zgyCK9G#`)@BD2NFuj3JRE+88YFSwA?t$P+k`Ai1J{}|@~3BtsBt`qe zQWKgje+xzTlNXedwxj@_CrJ@Xq5DZm0Rds$Nud!|aA1!VEsz$pMQ07{Ba=_sWB^(M z2<@c{Wq?c{f#3VMiGa^-82V5#LHQA=Z~iO&q&zHu-+`8N*8CRqyQxHAGI?koD*v?g zvnX^+Oyb^o7TPeG6jV)FP{i~wKjv_s7%godzcd93U_Uj6LYkN;Oi>w#fx-dVV)0b7 zhuQZ*DlPdvEF<#ZL@OaDQK=wHGASrAsJ&Ot2!e!`tGpuMy{fq%U4xKv@XhHjogis0qv_xssmL8TSlL7XqpbVq( zbH{l|L2-aR(qxK8cz_V#_Z|;)OI+G?jHEv9kBnOapXg{&#b`r3o(W=v5GG+OS^`2C zWPlKGEI4_KP+5%-pb!Cy2>Y*3hzxqUV9o?Xl=0ijq=^ zUc3wY53{PKJP6%i&7L(1S{x6@;_qOJ&}8XTQ~@V}Gc8%mSY4gkulB4!n6rRC6kXLd~SjY>_Z*qiLke% zkVbvBG73N$7@~|q8^RzLkrz^jZtpGs3@M%zlpi`01&WZSCIW}cgDfeWfcDc2QY_r5 zL~k@tLgdgL=vW{iX)+~cDIXaXY!nuz29Pu-EhGB(T}@>S2zn(g_!ICP4lRxdPgYV> zqGUuT^TmRPk^KhJat?|2J==pboPh3`;T{FlVeT+spDRWZ0}3uJD&4T34A2r6LTd?# zd-lCyfDG`C0fly#Hl7T4y~hs)kjp4*lF4Igl5Pnrggiq`@*q@rc1-l}q?&k&XY1mk zqw=(AIy(Kw6AJqq3Rp-T5jWwp&)`c(fbx=dds0CRKno}V(DK>mJqY*XpKS_!HmFz; zl$!yZ1pNMN9CWEdApY=s?PLbEo;pArEuoZ;9C{u+%n)C$5SxyLR+Ju*`r_G>ap>XC z4o&%}V~j7?JW;b>eY#+)5l+j@>LUS$H`FP#Gf*_L;9;;Z$qE4kF}hDnEqD?r+v#>*{xDadqNCU=CG{UQd8y zsZG%kL=>}xe2phFPV3zHx>!8zAi=cl8JOTzEF`AQEc*nRn5^dUk#XmCD{J)wf&8(4 z21+g*$3ek9os6PyEqRHyT-<8PX1+K&_;sNDDL7TDB;3Smi_ zij06LBGNY~&z}`LkOx~HbR>`Z27oO^kGHOpUy##Qz!u<_%Reio0Cpz#TvG>NR~6Ou zrMLkTP?XOn`NG=YzIX!EUj*?g4g5}wAF|)fPqJzE^!#{mC}^U8PqCTkZ6jK_+gddg zztf?(vzFvvITln!m`-X`X7I61<#qVjH)I|C{JQYx$K0b0%95?oKZ6%7#g!t6UsC71 z5_#3)fwiU_BwzDewN+HKC&oSSty&oD2sA4ley6>?kqCaV5>L|L$=GWYVP$PiOHxp7 zX~ohbO(8vO!9Gd7d4E9Mxjp5AD613>3df6&uJ!MkLJ9<)v@ic`S=oX74%lg!0qt}m zG3~w#xQGj`<%G|Dm7mt0SuM*iCu{LT^Y2G{LO+C#L_P@I_@^a;Pm zx|iH2sjy=IdC2PU$y>xQCave6=6cs{U;a+F&7wLsYSHk@PtT9`S)*v z&j7)8?3i~+>WG_F_*P}9pLGCLi-XwO)^Laj{;_pVk6(T~V_H+jRx8?o-&~;U#=OhF zwm7C;%YRYVD=VIOEawd!YA5#}Ta-zsyz*w%Pdof_AaT?K2@3o52>06kN&{ zY-W>z1@tX4`50mBP_kzR0rFwk`KTyl(zJPf+%Xg=!+uhl}sVRbUN?5 z2bsJOONcxQYhjWlJ1a|{^qW5Z5bZFO;hJKT!ix%eTfUSLS<0%{z-d9HfyuS-=7Ojr zmvHMjxk*Q6xvif(+%-po>*-xl5j`Z{@u$`<_=EaUtYoPBl_}0gv@O)uGNsu218W|t zF)P_b3CFZy%09`%EIQgkZ0@PPs>A02B_j!m)^q?$0HL~w)QcBg`>KBZK)fXRSH(Hb zq=YCG*f_L(07i5_MWdGym2?q=q*94M^yl>qk{9(nSBC$$9HLkYMlQS$F`}#97HQ9( zn17H!*|JLtiimpzNP3U-^q3VsesQGSdAm9FSx&U)dMs?}(!)uEDV~NnWloN-`2{Att=J+G){>h;AU+L|Br!C9lVnwp@RfQdXMHx8?lZ2SZj5=?j9oNN|72;i6Ihwkl4bjDtzlLak}qR=Xgm<} zkiX8x2U^}rGvEdAwSDgzL-RcYi)heaWAQr)R#&#yW* zrYuvDIP2_^P$<=X*<9s$!3N5ZX9Si6;nm0ZOiC;3)ip69&n9R=;O}-UuX)`}OR6Th z8VGT%G_1gjgs{%f#vwuR2k&C|IB40waOE|YXt;2cvSRqUjPOO7`B?y8yVBWg^B6{e z{%0lvO@9vNrgqvkm{SE}ZNfQK7j3a$!r?^;>#q%;Tz~)5=#siWMt2eiX zf5=7$}8#tLzQ+*qY%J}Nq3A;);mVkDXUElYZr z^;ZS_8u!s^P-!BURad5-0O>J8J4o?dbkFCwU5ApIyY5c~#5HEX^Ojxr=c=ELi5KVz z;4qG=sl&x@i;!vJ*5#RSlshw$S55iU54JZpr>G>J5vX3`IKi9Sb5IBNzMx##3meR8 z=hy8Aaq-;;Z~m3LXo&`CZoqUh%=1w&IH*nWa+Ba@sDfW(5bFi z#tWZ@=$nqRJnuGgNDq0jrJp7{YTMZux)DR~*t2jTT6y9tHR;OQ53|nwBoRxlKU7BF z`};s^9m8b%02UTLYyCNSuY)!%!q7a`zdY$VF6@y82$F&dpMxm!=P(ZxlJurej1drr zj+RXO93)^nyJ|YKS~CqISDk%vCKTFD?917i27`o+N<-IfuzlK{GnDU)$y8(;d7GG^ zYoW~K>~m}Ey*D`|MHU75$dYm|HS5cv>`?`6^@q!P@0H(3Q;+4U{EL6xoac$W1~8$Q zCOf=y=f7u|@Ll=$dOqCj*^9@Re~7r3N{H1q%tgoQEmN{*$QIHDhGMxI zVP#Cnm5-^YxObn${xTpbNmpKh%ZW*~DH+dr;qT&yx5)|Ea4v+2lq>C&M(H10CksQX zselacNO>BPt~Cf|&bf8q$|E?RA(lO*$t{k9?u*t(675X8!Vql3i9(B^vJs)de@amGX#zHu0_8ha3}n*eadKOBg)$EsIOqpu0PKE61uM5W4*n zkD-G7#2YvC>-U2<`xA-B{k$^oVQqHzVk>F_0(U!FINRB3RMZ&_jpH-x>JC^ikFB~R zb^pE629IUYmjl*G0Cy;}bNk#M_BT%ecANRO-3+Gp)NI5{m7h4!8gWCzhf8dHHG$yd z*={X5>>A3hgMvwZ;01V!GVrAGH!fQnLv@}gICSqupK%$OFEJqg561K5j>*v+$9>8x zpeMtFo7iE^98++k4KI>j7N0&l*F2VFC9PS7b1<~uphHK6lxI9WJGe}1K87}(i+oI%W8uGu*x^kDXu!kIN(9{1YUbL3KrneLA%D?w8Q~U9T#8ScpYAhCX zI(9_uL3}JnQdiPdoZ8@ZIj1YORVzDlAbRw;=vsAyXPve+=PMe?&eLvIqA?d)w^a>l zI8S@szUqMJ+j@AOVd1&QzBjvh^`pHChoA0WMowJ1#<$np8(bduH=OR z-zTUB(>{;>%``rY_V`ga$APvQ))@_PNlS=7#kcBpLiiKD2Vu$u!PryrsL$kNM zKdbSfyIkgf?HoFi?GjacMRlS^fHy$KA9|zjwLrE56T#H$1gqguVhGD)*+kmZ+3vE( z$_44~3$)Cd(1BF3s+b7}$rqVFX&k zN8sCLXiZ8+7Za+j3y6^s2qDx`2E3@C>NAA9-$=?j(V&dfPkkiO6KM#!RISNX|I1ls z7FJcZx2&V%T4}LcYFOv6FvbHNq|io~WgoNgE6YGJj4EH2h=Cu1j8BZ7#+b@42+MkUrR8c9Mh@2KB8Y0*!>7=mN()a}MT8jw1L*C<2&bQYt3vL7K@AAM( z%$Y-6Bdw+$1gqGE(OE?T0|24>;@;gMF4H-~VuH9kBEHLINf0yTX*0xwUM}jJjBS{k z$47-3a+`W#_TttmqTC1-Bm**JWYN+fMsc-K_ znHpNz0KPOU63_F#h~ovb2Z~~%gdI(RqeI6Ff7{^RcrIn6=NBc)FZG|KS*(Rg@sTLU z9kt&YIjgrt8)bZ*(>z+NnhGTAu0N2N8}+XVz*^h4V_)V`e--6_KWuKAJSo}&-?^YM zudo|1$Y9N)*8kQhRkPKWtfA97cx$FS;cn^VYwAcYM$QLE{l5CTt~Z`&*N1JtS@mF) z{ZN1nv@*G_^cG})RTlg(nShh3<8FeO-WC%u)^WFjPGmzRysYIyhHQ5KQO}_G^ARb@ce8pu@xA;f0O36{uS1~6zgus_@o#|< zglWtdammAr^C47y zbB5sE@=+Q~RX%kfBj=WGcLoQNqPS|KHaVk@(&I}Rn{N4Z zfx?_Q$33T=e3N1UM$T{uJ10z!QKz9o+2@W$_hgWyn9rXry0{9D2=A`7g=%Rs>|1K_5+YZ$fix-T(S^S;zjCVvY#j^a(HtmA%V zk`lSXpv;|-Pfawe`vyRmzCc&R3>a2p)FN6aZu}_F&Hs}ua~VSaDl)BTD;UsyVL{L| z{h>cRT!&|x^gY4bg0$WrlhqIQrVb4=TFrL)sP1W>b#TIT(Ur%y7e8n6Gv_zn+D6EnflK050@vv?2WC3Fg6YO)A>65T(Poene)-+9^Nwn2cPn@iKq3RA;r`>(xz_~<@eze50 zXhP|M#rn9_tthzXAnv41)cU*cZtd%@vpH*fl>A1=aw=pN38pTo%^|RW5@rim@DBwq zt#R<0hj?r>WM^ylG`E0Rh+}vaJZncj1?e<5K=qF!p0-elRxPq_ATBK;k|i*;D4^Y0 ztd(Msq3ZT}FlmYNRBdeE6Q!QQM){PHtT8KjYiB+8Il^nzn?aO5q(2bnBg!|VXS42X z&P@l;PLQ(#eeQ;N?lK?uJgoyI!0fV*L(w`r1EP3B)#j4w=8gxk6H9dfd%~e7pOX(g zzI1`r7nDS@efC;M)6g@0Ffk?NFzI(RvV-Ja4{$^oe5sl7yq4qU7ww<*OM^ETHb3e; ze4P>Z$H>^KFDUi()HrE~mw+ria6HZ>TWgzsqSnVua8;lKVB$*?!XU%`LKewiWZkY5 z7+^B(lBQZZ1hEEjiAOZ|FTBE0lF>pikE@05_m;+<09>HZ>nA{YhS^&Ur~I;(`R@L( z96pW&aSF`fLoP#eBB*b(I)lR>F6zjK?rkLCkxbI_#`I&{m5!SMB7vb(&-9pYM{m@W ze7qr;6lD<&#ZA~?X=3shj-%^k+cH{|38B5$*>BpDjq0DsvVJ9H9Y5%*mAGD2FU(U& z_Ju;&))<}Jubffggjo}aZUe8WL+H3?Zr+uA?b}wg}(-zh8NR+d~;2x4r zggi7t-4!+6T`9RwEx*+!sU~EbSoM$gn2(k@e|!3tfZ6_y< z4=`^;soxS|n$p7wXVhkVRRlc>7hHvi=r(Pt%M=f@461$C=n(=}kjuvjP^Zmg2LmWm zElYd)cv7Pw0HP2U%q?LG#M0lqOwlSV45RI?3%%-9VNCJ^YFcKBOcZw-Q%fyCwV(dw z59)1Em*svPRy+J8D+!tU?l&6K(!pjPt3PmvAtm*f0oB0m1X4L1N=h>Bg$4_hRcwo+ z{emGr@PZm~d=M``G|^$0HZH6v8Vlbk_F(OVyEF0_-BnO+Oaok)POy*7#pTM^UH-gB zA-_?FYe?pgNDRuT&p(JLWiKpU5@nN060<1(v+@ANZ8$@#j$`V$Coud&^R;QlERRrs zc8K4yPd*xNT#%LT@%k5C?X)ty49KAwT59u6BrGlX(WRjtE1)YMi>*V$M_sI7kM zU34pPKsJAC3_c|Ju3E1}qs>ilcPV;!9hgWcAipDr(eEI5V`j^uaUOC286RbPSwUtN zyZ2EeK<}ZkrX!xQtzXUDLWl84H$=R)VuE_0YtkoLVAA!*JySV~ZPg|4o|$6Pa53eJ zQdTqi9sSb$GTz3ENYU7w{afk2a6SQ0U3{IcSZ@h}XZ*{ocQt3Br~0=8)p7>oD z$@@vEg~rx1ojR0zw8T#Fb&79A@q;V^G%>4{fAHnXzWVT$^>7k=V|l2gDThOJPIPYY zT>Wv=@b~mt%d(AOe@?y^rDUgE>yq$N#`nn2W@gn&gd=z@VwqRyIFa~JjDPRmlM<|~ z&vf0tRqDAB^qVI-Dy!=4x3UciJ;-}d*nK4rx7E^8(xSbrZ5Qgc{H<%sXqO;TUJ;&E z9uT8CGwkbCM_qJ>3xEQM=a$OTPpo5C)|1_*(1S5Z&bPer8e5b++?O$4df# z@9QtMpnOMP-F0>u`>3^AU3*Wo6g7}gX5@_I7}*OW83YaJgJ@N@MR7O4qrRilts|_@ z2?7gTlp0{2hd_`5(z>^Abu5p?B4|`RYRCgYg6FkQ8rOoG?WL#)OVpiL6Vub3>E)Bz zPL51)AV&vY+Ea6`mSp**TGB1;FU0Pi1n}U^7`wAwde3)^DC<+by!n_kdd=-Zf#mc2}xt~ zniECBsHtGM@Cd&4DL=h~d`;6$g$z}Z{SvG5+?^TTSJg_>EM+dx#cI3aXj6EoSBN>^ zlBE{~B|BzH5xbVu4`Y9hd$G8GD)WEuW)AoG&Q(JGnP4sJF2K@E$pb0xxYjsN7<@`+ zm#vb(4Ho%t;qViki*u*Ka1{k{)_+z!$Klk{X0Chvgiz$I^oHEWPS`n;%hQUJ`U`2K z@$mAp@&sixOL2l86Ew{oKl09OLU_biAIvL5$!*l+b!Dd)pW(G*D?Vp}ofa9L0Jr8+fb4b@DGDJ0H;L=HhidsKqAkNFWHQY5{Vdl>FIA)pZO&0NKwvVr? za=x=o{XtT%#y1}3=KOyntq%3=@)`KOJlll)Eq3#`A5)Bob>t5u-$6y|4*rM?QS@(9 zn_&5xsH9dur(7hXb8ii^3`at-&^`MSWNS=G1>3e*|M&wpHktEJD!2WuuG`^5HrLUj znf3K;jSegoa^Bp*A2QdoGeyy3GaK5ing89quftaHl8`9>8>b~Y$tTM=eFpucSwEYJ6L)t0MedB2M!UmgD~y8 zTBTA~u`d1N@OZo>p#Ntv@)r@zVd=IKX(z>*uB+XHN#Ft*>1NLYVSUT z`}@D#vZ(6TLzHJ8(p>>3%@V4g00phZv7#=N46B;tqE~E)5kRy+eRfLqk zB`n>tgf^(^VS``i51Qeoa3Q?0_tO8}(WA1ftQww^zcWCg=CZ-Otywl!%Xr zQ4TMPJC`sXTGlmMo9%&Te%-W^k%^es+zEM5q9oGeJ?77-i-U%MYL>vm(g$M`bC}_2 zQR(jwwl{9;#;znv z%;a0An^eS_NSm2Q#%nIW%&EIIvOS_$6-2KR<%+hmxXi{^NnieHyvQ%SS)FK6iEn{^ zP}jdGjZ6tt5`e@PGsq_)qfk+i#T8g+!uq)7_Qy4qwjB&Z=;`$(L=UuYWWDjkbqeH@ zYt^da(+#YZj#i|}i~{!>zdBr2c~xWRu93~mUK%*%kQ=*?d=rKzt~>H#j^@KTp8&*0 zREA)~*`#{+^YNDTNH1bXi_N-mr-sXo>w@AsW{S%y4g66|uhN;74SXf67jN|mO890F z^nWvt;pXaxMe*aJ5!u(H0Sx|sNWRXar-D$joV0e@^a=4sXL(`F%9_AIC?kMq7)G{a zS9hIQpYW=AnL|@UjWFF|X|d~_*d!!)EaZF-?n>LCvzqVpF}Y`0VasCQpt#i0vSH?% zJhnwlejarQE(Z;d50A0!Moe+X6h=k%$rGR?>42}|d3UE38`JP67hzcSFhL_1=Ca8E zvAAMIS`OJEI}90@8Xy#gQ&|a|kD7!FV4+p2K2ujb9~BgNhCr-LYhQ&Be+ZGT#}HTV zH)O2>qeN{N-v&I)qzGA95eUE<7bUI>jS>)p4F279;D8P4lNK;*kKcIO3!9PG53vj` zpX8fzq^50V@TuI1x6|B}G$vo9<1(k+gR)EB1*MOMipjQdsXLrhRf|dLxy{`)jJ@)S z9~x&{J0|=2b3}FlJA?6rgd@;IOo791xDO%aMCFr9n_#3bD2X|_J0J;2&c`d-FN!rj=POE0d|=EGJk zMCsByt@JN7nl>kPx7lLr_Z!|RlvEfWsQ}(x@q9e@=!q4su&h_j-T*+fXpN2j91hd?3&ceo&~3_Sg=< zG2?fu@{g>W9Q8@L&4F#S3hQoUPIng@)=BVdh!bVwCtqr_T7h~QhSyGrZS`ayKhlO5 zg|90i>VT~3V6dSOT1BFqfXFe2QN%2IKI7mEm4<4#?JS>%5bXCM$+wd5wE}W9tt;VD z{aCCq*2>cLDIb&Md3(cge*F71+v40(7x?ORTwHcev7Q-Q+-zVRIfP~(GlRLNx}==E4IbR` z<517kWu?F?D$d;~)o3(0Pjgy(&SUDdEaxuz;bmybG9_i9XM1u8nP|$q0-{v@7hcE+ z>u&Gt!7}MN#_*n;s@KU_ozh=pXv-bTIMS=`MQrDq1TdQE13WtlOW+^-Fx={Io6vWr zGl2`^qg=58=-*2|;n(6}G%W^TdVS9+*RfZF=5x+#oZH&9eO=pLeF*|X=AYQN6vCi2Ck`BK{=)=!aqEJD-^p3hcACoYh#`_K6r1cw$``5 zEhP?Is)RXA0%^m$eEMdQT4rNjtPs2euH5YdQUohwK;nNXwsB-6t=XPTI}fss73tJEOCB#FJnXGlaZ25LWC$j zv(T1_*)MRj*B&8NW>T3bhc?t-MmnxBQ%of@RAlsInA28Pa-zB=48mS~Rx_hg;a7?)ns9WE*6}fH`76kG z2_?>d_>v||yYiYyBwRwauiL!PoC#MEF73P}=iFx=;O^{gXqpiib!`2TH=T++F5U zSNY`AlGG;v$MZsP=^yYRvb@cBv#n3D--ZU~3D7+9&hc(+IyJ$D}SOTb=+f+Sa|wqjD74j7l4h;s<^u>YmCCG@H7MIf$(%JhWHsPPj^)W6~UAY^nH<0kzSJ=g03$vW3jW>>=x?`ywpQgNgWQLpw zDh8wD0n)>Knc>^N7EPSip*D5b4k}^NxdRl9q(@@yr5PqJjQjD|&A{-jK*SDpC93h} z{+ZA|>IZ2^c=4&*`(`C!T&~q%BXF9H*Q~Zi@-h2TknYRvU4YWj)V$(_w^&Qdk&}LhFP#%Y&z{enXfmkiiaJEx#i9|{L4N|?0*7GE3fn0jmdQutV3o# z$D5lmG{=Eje#`l_k%p_ODkYs92qE)+tJWQe)!aA7niLo6T>rWpt!XyiDsi&&!%vE9 zp7y=NdvDzG0saK|kRmcHtinfcbYhzwIH8Dg;M4G5CaoPXa`-(_$p^f3Nd>=7=t$4D zOaPhdjP263^elHyf8lUl0=O!vY3PBeb=s$x@NM{4{2kTH!;7;A)czga{v}WJ0hPX& zY0z=r_{REgo={dFS{|GpQA0Z|XFBJy-ncXi{ zJ)99dir)G0)OI!^E18+xgK%A+*_81|CG9eoS>0?I$}h+3(d&R(wQ~0d5d{yOs?6Vv zMl-PXjc~CEw?f{XKcegb!PEuO=(RJ{zdQmy4nge7%8uEx#hAdsRyC#@D+<^m^X9AB zTH6%JcV-NuBchK6{x%${0D*XbmooQ&dj|jnZgOUKYCt#@wu1 zkAeoju3C+(Y%Ud}SoIc*pQB1|mI+{Je zyWjNW3p>4@{o{!IP522{yh9;q5T8^hI?q|v0^r_G*0HSQTG!Xq%EI5Q7(RUqA5y z?LN>wA9{+be%L~lc|NaY!I+FqXL^n#);<5``*CeVg>InM_cwKUp)&p47<+uOdxmV< zGTUx3^^~;n&!gA6s#VRZ%M5;#L$E;V(d~pL`;MWV3_*EsHt6|sg3JU@OJVj;d9U>&V-y*1c5khh_J=hbEw#AO(yxGJMXyh)^8GS^!c zt)pD-6fT6{m!Y9+%&q=rY9tV?s?@ENHTYa%U|pK=yw0+mA$+NHZz^&Lrb5s74jPOF z2qcci;{KI<{L-9(T5yUsOj?l)92lJc^t(4n9Y|Ih($f z&~JTD^F5)$le<}Oc0`L^y(F%6d_VY${=4cU3>J>~T2ebj=wIAU}Jgu^Z)A z%~8f*zOku>8-%hrjP#pL8D5`gga0l~gCisq&{{@T^VOtOk`7vUKNBQjH-zmUt>qT* z&>`s9CE;fK9K$2GH(J)8K_X23kVzj3Df_jYuGofAON8wldFImEf*?v);i|X?G7enW zE5^Fk^6UPFpHPpdi!8ov(wEjwa!Yvu*D^FgM7~Puk~*h6$}ywQ{2)|z{qq4CmgKdL ziGjL&dglquwEz=8e=V<>@h@FnqL<<9g6z@&H1)v8aVj&dpk^_;V^;jsb8t62n|dts zK9@*)gVM;kJj_@mW8V?_Zp?CN?*s;Y?Y@>60chf%_aVHTT2(V#kh>!byu9L_&sDq2BZuZNxjC%r%`>j2Mg=&bG$LB!c(?r@x0hi#TtyyB*s5suKJtH8-K-9KE+FpShf zsVBgIuVmg~DchNcu5imM@r|r+@=jE&V=qH26Nd0YWP%8zV>FO!~$i`C~d`Yoz>kkpG^9o=;|DqpVP)V z=etF=4wPgky`_)0oU$;1cswf^W2itOir7-LMUf_h4{_?k3;P7wV20@Jq~k{@yKpID zy6XwBtkmN+>{e$##xQlcwC3xpyBp=|mOnVS5FZ6PrV_fP#Z<^bm3agEUbnME7d}5w zvY|U1_3%i{dX_NB0AM;(6gA;Uz_Q4KmyFGGyi0h_|Bi zZpbthFQdiM=5@dx`*O8qG7MT&`ORwh)wc#l7D+8zfyT6NQgem zGc7yav}=)@gyC)^>|JZ6;vS#&NcCAqwJZpXu>Wl3S_v9)K17&)|1M-iY4v`tvB<;3 zi4U=fKgy{AnS&_`F5B2SmlpIgye)+{@}J;S$Ly$rNxjOn{W%90VnsxB@Oi5k{06yG z?<}C`OL1XwRv|)g9hgpNC)_e3+eXRRP@`vXus-CoC%gn^0o9uqI7z&)loL$ZO~+x$ zOLG&{*-MffuKNeh08RKy4&-d&yqB;2yo| zwDZzxLW6ah_PTe!!<1{=OGAVskUuVnOYR z@PWBQ&cgJ%F11*J#`QkG514Jr`Ynzz%h#%w7bo%rhKS|=vH}ZarcbRO^}i8|wMy3~(+$S0I@ep3Ie1RU zuR*KU6h(FxaS$6tG(HK4Tgj@d@&QB+J54tVK&i>lD-&a1L}6jGBCV5K6&rdGjK%uI<4WRDTHNr%UU^OUx(yv7RL@5Nt9@#|f8k@PLd$q`o)q{mEAAb`VO z)=z+c8WORE(UlD@<>|4VC)G{EXj=(L{PVZjo1%c+CxGL_^q34mxMS#V;<+aPE?1J1 z{Xucjmm!N*wf9M*T6+(H6q4H8rh)LXpM~vFU8zHqnY>_moB#(p!9R`3BUCE=whn_b z%~TD4Ua(faQd*?~#j-A^@O|=X4KIaZm(0nbF(a#xFNeoFx|mXur0t~{Zln+d}KrbKLuPIoVD;Xbq2c&6^VexHTji^nG2 z=rq}XNTc-jk4Oxb7Cwm7W3Q?++1S=sf=F$xWK+N-3BFD!Bs7T{!nJquCmj-$%&BTA zaet#ti|elRodgt*xIY18@4CI*{VF(e$UbBqNLtK(X_~xe&M*Bq(`HD%t+@X;ypOWA zwPzn;-CC0FS0+22wR}!3y#UP!@LEbEEjhFc?c#BP_FP%FOCK)sdnxH}05m;zcJ2>@ z;Ux(HUoP5Y0>zVd%d?{k?4a-Rpx~3ndr#gxndD;xfFqAzj&kf4r zq+liF6xhnM^adLiIYw&k4+wU|>pLK!o$W}W)@r`b31u_dOCsE$y*~J(`HexQJ~Zcu zIr&)lq@bdpv{l`a%`D?f2pA!XfnPG%GyAyE+-DC?H7?;6AQ8k&fu4F}g*`T{8yb~A zfCYxUPWP&~7&}SC1m3U)l8D|F$hO$M$*;z@*LN<($6;`;Mi+Q1qd)V#tZBB_l76@Y zG(sEIQkqbOR;m`epQApC((8teB76WSFRaEM(nnp7g<>wy?{GWezZf*#{qoD*Rngcn znp`>lOjR@)Ubb$M^{$mA)1T6$bW;?_`KdIkVoO^3PVQ22!7isEzxXxKGQhnjW+qXY zn00EuGl@HOS=(*iEju#FZIr?o0nVY<`8cwhC^ebf zdLqPLYuNeedmkm^cC|9{ibrnO?v~x%WvfCUoqL7dTa4Bl6t?r*DE(GZ;bUdS&x@;| zvG7T+2dH1AYk8nvP}SLzS>n9WY#`ruKp&5@7wzxlp4YM&$>$CEWd|v!NJ&nsdu_SW zzblJt%e`AS3VZ~Q#m4)8tT{H$beF`_jTk&l&E9Sc!7iWegfRfOq2=uG0fJp|Ug0*gxya?O3da2_* zY#AxN#2UhUZ;U`q&Bkh>S(X;Ifb&hsF{%y{Dv7m*)xR_@D9ascZgV8Jo-8vS=MSF( z{1#tmyJxHuc{e&bj99#tvF;fWC-wh&0bX&m+8P+##75~EQmuaVH}+OXxYslHL-<=c z=BR1iF{*^mOn&5I<4fXGJ_@BH%QEqcpFEk%k;U-p(4JdwJd1?F_kD<))d4=8wQ&!1 zQ-4V`D*iMxy|?~N)6M@T;DLUFaC3?SKCw<8(=d zcy7_6jAkOZE&p=jE0ymd{I-GvpWY!d&~c5Q!hXyee~{bQKa!|=uRq(sOvUBT$JN&e z>CNW;RLox?f$_;2(gBDkfX0K!=4eY9g-xKNlvOschvM_dh8)}1$GV;Kf8sSGPJ;&Mqx=}K_}y>5(`{KKen{JXyN=Vz=3@IUM9|DHakdIn3*am z%BgDb=Yuw-?MHjVJAdjU3Y+=bF_eQyQdg!6}GnS=CyZ?i_z z1(cq{l=43}oSah$8^30Q`xC$Z=_dX8AU3ABWV}H(xbE8fL#lt=Yt%g+37VD|am;92U7rt%X2Q>lZKS8DN0hJaoo*21lA?Qq%hEBus_ zmr9KzUewC&nDWGD9s13R{p#xU_J(Fq_}}8gH5b%zH%^^OjOmTcQHcfWYl93A^qmYZ ztsyP9ikD_=4yCJ1?o|B6mG}%EmkMHR$IC7r%2xw5ZRt&@l;GEy8PL{Yx{Z$q88+^C z-Y#(pjNb*f)O33W>lFhtHE5-m9%gNDVHqDb2-b+Shp3+bQ#Y3VB)FHD#(q&+1}wu~ z@V`}7??2SF@U62l*u|@keF5Y47sp}Qtos}^d#9$|*y(@6So!hO3$AEQMEH(E6jji7 zte_Ja>$eGa!qa`*zwMKcn<( z)S`Xb&EELdBEC=muT7zP3S42l+JSMVF2F^ASR1>su{V*z_q3uUc+9OoTTYFWE-b*| z@C(XJkY#%Nd^P&6+w+CM55SeQCV9h~$H~Caxj7w`CxC5aGSBCzUu$RDDa4B}lxxd# zO30(H#fbmf)k{0Qj zun`s_zy^RNprUw}obcCp5v5Zx6j5RjfEK~`7hgh&NN;v%Vl$`TOSROikRz_Kb1j9W zDV=JSTEmw}XDc2YqJnE=-iJeR5e@%^NEE}1DLy$GXN|>pKM6!Dz$Zu{qxHJYhah&n zD5ucmO(SMY09SpHjDf~KEOpnox+s;%RU=FwDRNgojZu2n_4V}|8sJ;M*%=MKy^cN? zrJDEr8!>n3PaW$wxBLDL6JBQP*z8O*IN48(9t*e3E%ZRx!x)qn( z=G^cXTrJ=D$H#Fkul5Y_&a*VH;5zac{0l+GDoy>$*@G3R;z%|sm~ezXb54U-AM?5r znfX$K>;ghHB-M!}t)$`>nmRYl6K4Uyj01E$_PlC20m~3yO>E8%^DAx(UXNZgLeA&< zmMvkPro3R0YTr@lU719DH@NWVVC_Abz1$)~bI2R<7BeZ@lmVFV4fFzqjHM9(vLVFO zqGxHAqT9nQItxP~e#7|)qB8&3@goMP|Nf=tY`^x*aweF-J^T-L;1l4aaIEvCv6^K} zFmC*><;Sir=KD@LHAn)MPrFHQ{<=g3j{(DB`MU=4mC>dlq!xNjV_~M)t(TeF1cX|J zaZpS^PE7vXDc7mA&??7qiMq<%BW-k31X(tS)iHVh4*-Ece!oZ=F2(^LH6o{n>iAZwDQtIX z>T7CU;mj@$E@QyS$Zs)^M8^?V+G;G4P}*qZe}(*~$rMLSBx6x=>PF{n)N922J4^gN z8%^R7b9|A<6-STaIjwfid$XJjXJV~a891m#JT~){pZ@@U5iD@AyRXSA#ZSfl`En1q zTc&H=B|72KTIURT26q@8Ra@zJ$^1Wbwzi&@qLL{e7reJ2<)?RHgRbNSWyCh>i)HH5 z4F?d^$6Iia)6DEQc)%xS;{$QA^-R{>>-aYFYO&B(d&_SxmClm0CGkoC$sDx<*!I~z zw&c{JqT5+Z82fvF$dlAx?fid#^eEb`wy144J8acA2EgWlM=YK$w!34cr||^r^V40f zU&O3(w%=O;bW+I3NYqazx;|u%c}&5>&h~A5imH%4U(_D+(OS8?j9X9&($6eOmoN`RZWs-`@Pc1WQn&b zK=;87M!zGNM<;h6l0IQcqqkY6q-CJ{%@yV+1`q*cu)K3Q zT&2ujGyV1KTvt%vT^zRBsu*jd4GuLC9aq1HHKKICBby$GgBmYJf2uQ_X?EX7|O@b zv;P316>OjX0AI)c(PK|pT~p<$iLEYkL2x>T+_C7j)@~h!x+gwL$%LnKalKapom!W5MG(=>x8 zCqr7@Upxgi8x1@^1LgX-sZ6hd!y&}|H%_*A-^s)7y#_F^*yiOq`-}^7NBr47=|X}o zrN`z|`rG-N_d{Dp;vaP)j7Dx_ZKQ>~m=Dc3033!sNhYEu^O32S*TUXf+@h}2Xdj*T`6GCpTu`&ZmFh@NseTe zVt?}-eUnBPv|v9Yu>mpJ@I6+&#a!=oQv%4(g3ir5pP5vQk=l+`l(4+>U_PLxeauUc z)Aa0^n|+cbmqQMe2J;zJHQMFaa#zi^U~k?5VBPh7E~5ED>X|cYa@buM+YigPRUh~$+DMBUgLlfmqTL7uXdK~oAC)x z`@4%bOqjI02v>p99*PqwRur~x6y%eHnke~fv=nh*1luOi_(wgFTV`V!vqpQSC85UH zT3F)CcT7}MH+_Pw>aj=erEpwm8GQilfyMF2l$k6lhNR`{;Pns-l<^v zsuS^*KC+AO@)jk^$>?Lpd^kV;UXXw52!|i=&NKXCm;V60dG9099zu`&Dj)eWPw@x; z0Ey^2emddmsr(vyoji{{1F`$7nCl~$0~^}m=vSEV4iEmqv!T4)t=KfR^)Y$}{(kNOZBs@krME z&KI1d;=U)i$RQVM`DBpctclnz`2e*RFJ|@kBHFGbuBj|L`>>hBpZw0w-yoy2NUK@0 zNe{05?+`~{ZO(zuEp22DaOT#$5vni?B@nw&vJOAS0=a$`Wx%=0NT zS2&$487n$gVenjyc`qt&kV4-mE-O7>PyY3jPgzddib1)7!z_2tx_*w+J#>N75*oC$ zv~kl$BV#}Vvae+><%#r6ryBWPoC^N{!#4{r5z)hRr;ON{tiuDfNeds0vn?F~>B%{9 zs=MD^NlU}kKf|s1Tu3}NG$J#n@dd8(m?t|!Mc1DfH3vh!aPUhBAU+^H?J z61WMT%6f*&gBwea;UnrX^;}<<@iL;wO1wPvo|otH&CLd}T$-P;WmQ>K!;}zk^|Ie3 z&b&b9I%#BRV?ie}JmV$Ao`ZD?lFMeK;b&Xh8y$9SKB?n-Jnxaj`Hyy!$oePk*Je@N zpHUR?R(tG`Q~BI{M(hYKINNe|!Yi#kb-wkl{vK&=K*-?i{{X`_A&~OkqkLnpHHj4@ z_H_R2{I&D=M&w|VO|rX&p|V;yYO0p%=G9+dW22~Ji@bKqcV?cr<$^X@&BpjUtC5>lxvcw3mxR~8KN%D;7`VUN{)-+Vk{eCFi;8Kl zQB>4Yx-$flOX4y{JcgDWa_5}%!i~n&RnoqK`FEph?X-llc;f~~L>@=;H|Pk)0+DI9 z*`%@m0K4^ctu?VzcvTR1WI4c$2Lsio?i4;0sS!S28opgmg--nx&YA7gQy1mW;&XXm zsB6Sil38$X_i=w1{`ttC4|DJ59Wu%xTLiDWaD*+CcsZ$xM*jdRq;nd15bSN9T#?e< zto&DNmPsV2j`G(H^tw6eMS*}`Ule3xJbMl@_ zW35)}%yiYZ3!Fl!gtfJF?h-d2mF?tr=F&6I7*WYb?r)E2FX=Du{{Yc7nPvC=`;Jmx zu9k_vhu@hQbxTZfTniqmnKhXl70>thE&jNtR-ozp4b zD-wiKZ@x1Z`Q&ArVHV^&K`qOPX=45(ZVYq}8HXUZ#A(^_yJB0o!P#`a8M{wL+*Cs( zgBpCtf4^0l;RtRMT6{~L18Js)S3>a84xllKG5KAckD&{DVzxn36Wt>+KMR3f-;MG9 zhCMz%9>*`N)T!l2wua$BINuCCp4=${2xJ+J!ynRe6=c?#;ocW`t?WkXHm5}FIhq_h zY`1qc_aiTEe%4(YLOD1em_%t`(@9l~tC75>kbKU6bn|W%Bb2Oo{-*x`gykrMY>_C_ z%0B@6rpywP{+p6pc$vQx3~>IJVJ)|)zve?LKTwt;{l)cs2{iL`iOD9Ga(~iN1>%tI zOUKQn7`ssa0R4s!oV zi0EO8AsJ|R9b7k2s;sp0w1#;d)2LPj?Z)nJ-8TA|m@-~Io1=sz*@VAZC8o%82qbNd z!TBs5Z3&iRskk8XU2^?dO;t_d2A4b>hhrL6BI82W<=|n#8t1j(Q;U)*D5x6X(Tw3; zK|scI37SY8(g59CK~DS(g)HPUF(Js!Ba*JD$lNQcn2Rxxs%tqr2-FFo%XLuCnQ18J z1P$`A2C7J3HWksRI$Mx+y*psEc~Jwgg!)3P5_#F39w zZDyhZnCer@3Ce0hB-~|oF2#eJ^qxe+MUV~?kD|kQD~ei7v}_cYTge&H6*+2oE-f;_ zlA0e3l+w`FS|)$O!lJUvBS!2wQ^xqU%PUV$B={=uj1_h)l4;ywM5?wv5J&|TbX&k3 zGD{>J`XdD-f;ogh9P?8VWO=GoapWk`4b_BgRqmDxG{+)5J(E=fOK_#&0hJDOt11}F zES6Eh2#k`YTP>AWdf4cw;xbJk*balKK8cYTdxKii=M#VjGFNo=alx$N`)H}CV@-76 zI!At9%^ra*P3oxU+!RvhFTmFa`#gfd17wgj^-dmnNXhvQ!D=0Ef-p<6eyVfa0Qo5T z49?#=S3P9h-sy79m@TUdqP^Cbs?U@bH@beF%}Y^Apl6zz1y+2ikw*zu{4^@fcKV{bI*p^eP#UQ%`3>SZ8&TD)W zd#Po2j*YD^m6}U?IK>shp47;15s9noswvp=(;yPn2aFOk%THc_j470LmDO?6@hnhB z;|e!1un8PIxg`0{{{Rr?v=Ms~lHwz54>X<>o*UlmkL90Q?BxXbpS} zacPPDH|AP;9=w#Q`)#7@LHs+wiSN?cLrZsu2jV@w2vyYeOl@2%Q!ZQW=3FLK!N@%aA$_-H$zqlWTY z$$y^E?|0${YoKcw=2pcSBsB8zfb4eEKB_F1+FBc%uXYN?QaY&Xm%;PJAjib;-H!bF z@0AkWZMfa(8BZ>lq?xXUSx!%g*9;uA?UHf0!k=g1TK*oXjnO#7V>+~r+J0k^%Cik8 z4ac{`$4~wWGSx*sxc-bPy87G1bnJB-JSMn!@O)9u-mMuK0Q2Uy_P!0Frl*Rk*a)VO z2QcGyj>pt;`YTI4rr&*N5kkspyk*em0Q$GT?zHwxT~`lC=DH13@_cMNkC;6_y5I5M zGtaHQ#7Jv68o zw%fcRxI-1Rw9I$JGlfxGNC7%puB3SGm~?GwLUO7?t`swkZ15>?x2TiGT`d=5&xj!80N zE2!MlgUM$ujC5^rZb4lRoFW0jA%(K*GywM|sEzDTTDMm*O_-Mb*9PivjhxUxO6 zg0fCac(;D9qK{bnNyjA#p>DzED8!t8q3D~*PK~=Luneh5tN4J?$p6snxv+fc8Ia({Kqs<%+@`5&z!}|qY*sEKaKF24u5`CU<1w~C% z7kh+yAZMB=oHu#=#B^POtqo`ckl7+8HZ}$|xC3C6do0Utm9pI;?RBUuAr5Z0C6T0T zhAfT;LG_lvv454oCzrFff&n&`IPG1AwB{&y(OV`Hw$Do5BKFV@-_KRGDA! zw`PSq;T@7YyjikMrOL~0O72_*iBGT8(+~usX zv6yoP4?VlBO%;q?sC;I%j(ZN0-k_}mI9`>meq7?y$aYSD3>LB~DKnArf_@;ShK?}j z91WJO%cseamxt!1c+5{}8-fSxwI*irCHuDjz51(JE)j>3MF$c47d5+$S zs^?{Evn&nuE&l)tWlqJIGADNaCW#bv)K$kcvuKx@joTl$_*2^V0f!H&$9PVPK;{=Q z?btcH5%ox^zVQXLc(l<&b%=aa(w`1eKcVAdeF*xgAw0Z3#!A0~Zr2A4f{kLV{?s^n zD@ZZCt+iTIi}-D+G*lWMSmyoP+WqSb1M^Azbu6KqCir8cIX) zQ_Scc=rYsuY5v$xHb$ODbi9Nz4pCJt#dOynNa5eX^go-fj0#ea@~K zh}p~s4r%pi+WxBmc8{^*M(sYT6TE9m&og@KZW;QO^3 zche&^y`$B<&&(g9X5Z~vQ-ND-W4FO{5@Uapzsio;#vgOwOOv7&kCI7axY>e%8O+kTTh7&ka_9bD;;!!mg|I+?36vN!36W) zp;lL3Jfjf48+df`5rH9YmN(aZ%EwgP-#o6CX-twk;&J9vXC5*>50c@PBdJPtNbaab zU$5$r>xf|7{;H&>g2ZB9I=D9nQUdhBvz!)IqUVvbzg0zX;sXP>cj~EKso04UOS7Q5 z?#DcN!jlckGt7m_X?T`OnaFFig0(aia>xd9a+MdkjczZadj(r0cFNM7*#NACx}ded zyFXQ;g0N@`*Q%Fd^xH3E(r}JeHO*BlxQ3o#K5k4c#-N@0hzs=c6Il~^X z9m-Z%;wVKnH9g6(o!k(oy)Zi(g2M3y+FD|CxT+d1B$?BIU)Q>z^>T8;MV*mdoz9Br z*MM@ZBCBhLa=FEp>SSYl%Rv>?Gy|*kTC_q^NwS@?NWQMC4Q?{BcWZ$m%^b>?RdQq4 zNpj9yD%$5~R(ma-HC*y$YAskRE=MkDJo2J61myDguiv6b8!d&zOsC9;VmMD30B-6q zb`l>h_*Cq9WxC5NZ49?tgcNanQo9+)!a9}TtX8P47U*dqXbodPT%*}V54~QcsdnNP z29KFtox25@s-M-j;JZY4+#eu=dF3|jzbCSc%D)ik1P29C%aX#0DoH@tB5O;zrrV*L zx!{zS)wh#U$gnVa&-&Y(>)c23NuByEUd1BaiO>)5H2Fp6jgCJ>ZNH63EWSeY8 zLS=U9lAW%oezzPjZs!%HqA{9w7>-$uk8~rJ!zHzFJma#0_ZezH9Tdq90*OjBO81_n zI$e#AM6QX!wh}YG=~+%gSRb|%5_58p?unT>pHPH@5y<%jZrQ;i2W6?p45GRN>;Vi6 zW1;|~$|FjehRJQ8#fv64a~=H^j1$LG7<&)Qc1oHi&lzKe#b<6UxKIbWgtXPi=8cc| zCjNu-<(`KMG_d~w1ODatEvv0;s0H!il759y&rc*SERm#Ry0+oIC86S4Gd(FRmNTMy zc{Y*<^=pUs>a1!hqN;A08V_UHD=O#m7+Zs#@dpY}aSJmuOf^jyWlUgd9*6S}L-be) zKi(b&tP!%NdQju!k_VFvqtG3*=tfs)th7x}m&N?X4#RM&YiMb%RL`ZWg_A)40Ev$u zsO)`Inte>Edt|bKcAZ+cLE)L3H?``xw6g6*9YcD}PIN!#r0jl}T?)s=Hp}#St@VtR zz>F6oxc>mo2ksY1rnoXl*&`m= zqIk<*(~w7SdaT=Oolk7hdb!5Mn3MMEvs^{M_UrDc<7lL;Jf@6n^ZiZh^X9ZHk*^tP z1Qco+MM+_gM;W+UD=f7>?OhIsb7RKrkaub8`-K_p1TM*Pw^H3{UrSdIk~a^lPjGr4 zRm<=8DeN_#1c$_h`7uq8jCMVUOjV??fcP_&KyGxmKOn0eT3F%$10904otu?MR}Ps9 zy`qYIGNsaMlv&bMNh@=xsVsBccO_TboEUI@Wn*ex!OkRbT(-x z89$;sb6Q+7wYKVZmbBn3S=6#>Mtm5`t{9c$$Xuu{Tn$%I@VMuu%e2Qx$B%?18)RgB zAwfMXWHG$jAstsANV8shpZ+p3(s!n8>EKnJ4G zMN&%!>ZOqQZOU6}p23Ffv@6rBaEjBt`;+RbNp3Y^Rm}4DbILc!`93Ek=~p2QsHr)* z4TkQI3Bb%EdvFt^!4xqgv7bdBUQT#7i@xNNWk{E5JxqWtBY1-(bK%cf$#=0vp2IP9R4I(!QW+k z>0I|=o1&VQ8Cm?`3aKTM#9q@T+pM_rJd@cJmuH{Hg+8*w6tWXfkfS$-i%z-c4QSk` z@X2=~7rj1bV=i%09NK$y2Cm~XV1>Jq!Wmx>DV0~TDbDQn@;lwo_ zEo`}H_#$t>&!rYTFnh4Ly>vHy})Wg*QsgG3UB+Q{~5W zrVKDD53=5P3$9Xu-5~Nt*KUx7xi=u>Q;s~7QhX^fAu$~;!jsKI55vb|r7-FVL{bBG z7)FTf?4v~u3>3v(D{5JTvxmZaCxSkyHIXNSk@1Z+cM0(fJV9-7h0`4q05a0?`G-*9 z`h~mUE;6FxnqMX$tc(v9oyT$N-tF~MxPr+A{@Fbg+jxz@em)b>{R-i7GP=QZa1WB2 zwvs~KOgJqgx1s$(S89s7y|3;?Yb5KI?`C=#K(4h#QVZGqxqFUB=Cj-v$FT7OTSr}@ z3yVh~vnKU#ucFtgmRExC0BPUHO8fd2qUo}>Ct=(7M7(86`vbKg_5*O@q%pRbQg1K(p5PqQ>D+p(O;(mvJg#DEQK*f}o*B?~J05DX{b-K$ZI+SX zYsRRYe+$PW{l2R|Z}x*mD#aaSgH8sThWt6~f6CMQ{4z$_qm_?g{6WJ6D#~e+;NsP6 zbaECwrH^SXb5Afv#44JmhdXtl;(C~8zE?{FgQIk$f;k@KeO7vM3)QVV#EN#~pi+<= zK~ltlpNT?@V4*1>Ee5wD2+L`IYpG~{a<&$`i!jlsE^9?pBRDGhhOY8SS zR;G@dO;*AI$Wxg!Tseh+rMjK4{!0Fi5(=F!qw-GO601MDQ~gT2mlCZOQ7S+2|P#fEqHD zc54`Q7hnU?OSH=y%Um}Kjd72umQLjGXlZG(z}#$^tETXdKvwixGy};*x@p1Ed96Gw z6|(YEI;TOvK~~huqEa$~k8q5*nc#CM8KigODH>6RmEGYSp5{8o5(cEblTGZEs|u`_ zB=LL({{V!j`c#n8{eqKEX_j-hB`hSOxfv+AJ__)};Af(}i-(<$Hd6lp-N%8bWe2E- z$W=1XoQnp>Nt!aOWROO77Zt&G(={cpgo$+011Hm89 zXYRcVN^?%kc3iiJsHyDMYU{Ju0i}q_5A|dL`jye_Rcx%a)6BhgE1eNd?)RZ_FXYoaSf@LyFFC{v6)zO6Zl>?Y5U%z?EB%N0r3N!UBHy?U-`EG~uaW5Ew;Ak)p`1fe-S7~s57;0R3_G^#qS3=Y|tm`Xqc#(Fw zDJ-KacD5RAQM?HtkQRbQayu2t@3xm(E)Ilb!tXpp{$Afj-)f*`R4$3*EkB~>d~<4Z zXy2%L>7A?|?c`LNJ6$&8*^Sj!t*<`lz=nb_lkht`6z+^9$kn@Q%vv%lcw?UNq>LOX z%&e8MX=KthgkZIZ| zC+4sv(lmT!J4++M*~jj!M^2g-tZD0NbhjX?@m5G9Ruy$j@@dAht0k$Gj@jF+{Y`jf zm|MXn?D-_mpUM)fw+{|husdZ*Syxdnkn%#?DTZG$>(yf1oF3#{)60CY&ZSRt9uUD% zYil0yol2g9xvpTzPE^!@)4HBFOtCb=WBDez!ow$wf6L`00M z3OfZ{(g5i27euz%m|6*pZ|JR}v_}}(gY2x?t!Z#W4JvOe$k1B-)q$nB!kwf6uve8f z`~!fhr>Asefx7e0;w@F{?MG3ha8OAROL}7|)>FKU=~5`@-s6`7tc5lQCC=!)J=&$} zSlKn2g%^ZUIj&*kRJu3}j>!sRsWNkf*CkjZOnGjLS%6DkmL4h z=N9|@Ws>O)Wfabd>_0ZWqnImU>g7(UKV`!+B=ek}!fU~JM=Y9FH-LDWZYbgSZe}A9 zbBi=PxaYrReJx}BO%G{m=^16rw)4&aP~TIA`5JN5m0eqO5wNv{ z6W^jOhiHx?zvwa2)4OunA(pp6j98pRSfCcWSLo`|Ol{ z3GJ(76Aj}MIR?KPeF_i%08z=8KN<8Y&N(Zh)-#QdE{RVW371Kx5dO*5yIVmUf}~81 zuW&Wl8=`V7>352w`k?d zW>v<;wnR~~P%b!pUtfsk(}cykLYYuUj@I_!N>Aa2JANIiOktP7}YrnHVwS2`z{T23Iewp378`cBt+|K}dfPPO^v$Y^_-fTmdP$BGbuS zS1BY-8n9PM5Mjqu%VCky3=Nd(fCl|i>2aOaYpg`Dr!0(V9U$D4nJ7qSlx1JV0CPbA zCq2wKatV>Ov`Fbl$(l!F;pV1NTV1!8D*2YZZpm&!v8A=(j5P?$>dP0VWu&*iJGCY{ zCq`D_+CgsZ3cj+|V;>5)3x-OgCs_-dp31TD7J^;+txZL}#BLQ`RSSzq#ua;#lN_>) z?AX*u#>y1)crt=Is|wm@!d=-?)x5hT@(Z8VO9`UZo>-ZGL2<(Y&m`?t*UNx%O3qTu zbdB(ye1*==c3CmC?KSM5(~;>UbdD}3bQDu5$_furnfXViSzx5Vl6czp4z3G3#+IR3 zNZ4rL214L62PLMdsdSxi5-22!dV&^cf$i99%C&cG};67h2>W-u|?J#eo|$=b?rj4MO8`JjR#;9HfQq`NWa zQ*n@0EyC+lbCW>Sb!-|pC0}sQ231r@*{X8J9rX8BBM8DDQzLV7m(qI8tN#Yct=gtG>X!jVe|4I)h}O=trO zaE-WC^xC?q?RLp_1~oK6!9jf+T>ZkIETO#AN7S=C!mVzaHg<_&V~PZH&1Xcj7$`DU zyQ)^Eld(z^Mk|CVSlH2tMyPIdaPHrKlgXQsF!FX0?7YNb0pur==k^E=Fcb)@&;21&tLUwJKdn9dsCD?sIe zuuC;kxNhRQ_*Ln_MSBq`CRyAr_yiM`pQyN(lY&y`)c*j9S5JnX$(FoCp0)J_B|&gG zT^oj~J?7T~v-n0=DX6Fo>bAbmF3p~e^saZB7ZHy`xLnqUQMbrAKldYRSw?hPQrsO-KYqK6w36u7phw#`tWKP0ARm$2I zPxhSliv%qvcT_h6?zxEOwDfEIulY0eO?rZ{l&m63YjUh7hC{{z5tkJvDpGgoou_~S zlBY!w4djgN!W1gW2-E3mVet@gg=k|14|fNmgVrVViumGiX~<1KX+iZ?PLD_-R@M;1 zmCt!+^zJOv3_KGAm}bfqMPpcSND3VH4-K0Ym%H8N*W__jBdx`GMwBW{&{bVn=N2`< zkfl*h=?Du04RnTL{GCfjYP!2v2cJ@^y;Piu<61{SqaVuwSjP~@E!8!uq&x!S&1mTK z$&HqsQpzEk6-!PD0}A4vk)RENjT1viI97DTU@7+uNOC$hka>v4vKHa3z)tc- zkfv?E$kN9^cIg@c-y*&dNe9Aq?4-+nsiwhcI8D1tj)PvKJ)LLxqXxml?z3ETd=y+YbEwsV*c{P= z)!Tn{kcW&hv)*#3J*06FpM>UPWXFpmTb%ReR$isJRVVOUgw&r0AE~L-*5rU3=Q#fW zWv2FDOe(mZnd9N6jnbc3+v3fNjFNAC?xMu21Y1Hinfu zV81`pk+#jG&a+FC%&E;73ci)7pks$n!Z?)Pn5ptmOejnSoTCGK&$G8J(_a zXeB|j@g&?ka}_PiqCQy~I*#i4s*}VAWtzF#kC?PBdt0G<)wS^?ZRs^>#n(QWqP}}$ z3}cyXr!q+4jdE<(pYFNy_`dNy+MeSzQ{|Eg1dL(XpJdHNx#8!UOjiE@HtRm?^)|n) zn!0DDqBw+mI^`#|DoXoQl`^!)RMDldleu^JS-WGTshQKtb0m%~arG*K-$d5q%C#2g zbOGqKYL%Dm^?i(seL9qtUgr0NZ(i)tMNsb{{{T#$o{L^39P+tjQwC$vT~YBQ(J(RR z!~<-eVQtqgFk?@%cInxHf{@ujgocsLWq;l{3=Waf2Dp9`u~pTablQ4HGMS{zc{uVO zs%Sz|cu0;@j80?zVFeQgRnGc5KxKy%Sj+$kJo z7#l5PX^u$7#WN+eJ>cPBX)A6!S)&=GjAQ9cF4%MCRI7Z3DTWSJmCB34aRhVpS^3-U z^9Qx%yQ_1fX%oMbq}i&qF}sDbw7)G2l36arg`ko_#!BfHTZ3I2aC$2md3yy*cP6Ym z02L}4fC8?LVD^FtN)O*TQ`wwkd^;|qsZX+YyQ-iyI(nemvJb|x=c|++8ZQ2yddf6< z!@8$ig+Ue3py0VpisIJ}Ye!Fdn#oq$oH%8Stp%qlmg!E{L`FSTlWLmas;oM~Ad*uXxI_vdkTw!<8q!M%r05IC5OA&3dv$hcBeb z$w*;wV8Ox(`D!&t;yGmm#aWu)CvmpYS5^WWPWCsUcFM+=gX-p&T}4J4%r(6}s_K$h z=^_mTmkyX#H1{UIVgnDVev9~DNmtcoWX^`~DQnKo30AscLjz;fP6sknx79|`yTDbl zO6doc;X|IDN3`L~tb z;H<^+vPMSjC0tKcj;k|!t80Pkw5fSzJ2*x{=JMyc&UQ+wWM%HzO09dPo!RcB&{3CQ zk=1O*dtznEJERpQ0dUTcg>ALk4$DPLL<4yvs-+$o1S+=bOEu7Q$>|)~nlaU7eW+BL zdP{W(z%Fr+{JAcdJqtv|*yL9n_Mchf@jKxMEv1Mz9=%o`y8Y1G^2;^TvAG#GPT8I} zadu0w*>;a+w8n>p;Bgo;z0&3)8<{qi&-bUqgGO0dF(6OS+$JNyqGNUp1Pqo-1bxz1* zqSPcg?%}~gs-SDZ*<3`>=JH1+I3tp!WHZ@r6TyPHTLfny1y*U=$1Roem^Ft1W2#?= zk;!ITQcr@W8F!Gxx!3s z1OgP8n~sWSAw>!if-;g>gULyWnt~3ELn#v|j5X=jKRlC8ZV|`LM)@ANBo8urHtF3m z)b@4?wBv%rWH@lKQ%8_k({V?a&A3VPOeysCfkv?se_%A@|WrtkkgO#1XMtP6@6`vwWG#8H`f3xzmHX=sZ7i z@-#St2W5$_xA;yk0~y^*vsKFm2CRUo*#`-5O-%kyzeifq&5Dw0$A7ZM+U_C1dACbygcPc26?r{*H3dTfAZiM(R!b|4c`SJ4 zlw9+uVZU{St*2( zyNKYeXv32iN@%Xsb5hFCCx~sf>m6>Ps1rOhAh78;?u$`qOLAvPGB#HC39%a*?6eT8 z>@v#GBB>uDRrHqP_Uny7w38#0m24Pmw)ra-%-1(!3eL$4&>h-RTUR7|YQlC}8?`e2 zX95XS)zSh=Pw@$HjO9eDoV;u>Rb54U(KS-q#{J|p;1uAm!*QumO;F}J+2)|jb#y0k z6-sE>$t}4wXlpJ3tvigWI-=@;a7O9@xw@tJJe7qzONQ%KsbJ5S)K|9F9Q{NqYDzI4 zHVN3{1EPFkp;(pg0*xsSvNnO)N36h%rm8DMK<=t5uMG?%Q2VMkY7$(Q>!rSk)6Bs+ z1nj)&#P#OB_i(D!w6hRC>$6?1{sdJs>e@J7@6&J9a2ko)emwb$oJz@!zO0@)Le$4% z!D+&jKgDl$`ZhQI^HkQ6o|yr9qF7qz9Uy7x@?LrNJxba5!inT%l(D*F>40(iki7)j zmg56;si2nD*;QA%IT)ImqkJYjEGe!!(@q#$u(u^y)q#QKL&d@75lV5%GD*slX5uaG zCEX0#hUH6p#+64)IcGAYzOw_Gt!*WW?IT`Z9UGTEu6`;=TKmOl@ZGxSS1RJlq2}hP z%T4adC4U9YB$`fD-6W;pZ55zwov$U7$01YJ7i8gGnDw1whC-`Dh)8%PJ|sn zI#W!1Vo!o0gsCIhIT6D^LBUp(i)j_|M0zAOm^f3M(b+N?mt`?bP9EX4n+=gThJlp( zK*DNv3?@o>;0uA5Ow*mz8mUS8AyD%f=Ag}5!VXUBCtDw-lE%#NONygO8>uE;YbyJh zj#HjW(wgMg$DDK&;Xxw+?vo3+rNblVX=9?KAGevE=7PpvJ^ws*9JysTypfRBO@>XzM zh#1N-vKx6ULdIO(D+Ue@eyb66u6T2URn1jP-Vban{aXx#>KW*fIf>eOA(K39m>-1>>e!c$=EDwU)8}aZ`it)09&i37H<7a>11eTa0lIP zJ>8}pV|7go}rt(RKv)AdYL zR=~h>g(JXl(Szb@*HB2@H08$&Hf|D5?aAD&9~VA4r?fN!zIIi1s|7`LfX31r-wB&j zDca?`2!7iiR|TP_Ex-zGvxD?783`&)RiU)a^59`CGI$~ZkT7LKtGKo%?on09TalHY zx=idlbp_LEEtcwvlfxt4xPV62VapR;#O^W?tt$TjJHU1cSh=Nnoa!f<<}RG?n^Jru zq0-S5i`%u_$z-@cUp6*8pXxv0E@@Mc@Bj|jH}18Uhv>02m>tfYkd$nB_~ zuvhdI?1RC9)IB z&i6H&b591O%*@79_yRMxSDy{r^y<0Q_0DX;{f<{lxy9r;>K8oXDsn@)s4rhYQW&AH z*Q8}_tg`BBS2VYWi3dOm=vFdxv$+br8iw8&=L26%H2{@U4#(9uMC^d3Iiby0ayJDe zl!rOOjw39S(OteCgeWsXf=E;~4-B3#${nNu%~PQRQm&;Xyw1vWM1hoQlW0mjli2=2 zJF6i(xZa!3iCfrN%`a*j_n=$bTy+2J9Zg%{wYyyPUiB^IuVyg6ZIeOq+` zsH-6%#{p?&k5*MhTwCQE>QjSEfxJAKy2j}TAvHx*T1zz@)ccDAn0u-{UKFc<)xp(s z!J!A3myeKmV2-K!Q{+@{xM>Y&-CEF1;xH{bE|AYnGF0x%FsZ884n{XB>Qh3=VCu}7rJ7oqnYkONGvOMq8OjCnOyX~da!F_m`OrZbUQ>SmZ@ zXlG<~6^?cMb6 z7(1??X0pXi6F^`C3af-{jisiH7L4O0`mKXNiHl~q@s>I(9gWDwLmxl_%U-J*;$x3@ z9?H)1aq!w&-h6;nRFo!1c#`f)bh#ypDBWwGe4Jw{B}WRreCv4&Y*`dTpinC7po==3 z1{5=`HHJ$WHPOxQKF=8}FL0UQ<87BNy>Qg_%A&`OK%JZyez;!fUmKg_HzT6wTtVSi zP6U2!`Gu3J(8D>0W}cT@DDcij#QBI(Q*>xABh=*o0ARC2%`WGgPwG|o7)W1ysSS6Q zAX+i$vZS{{`Kw}K^A|mg-3lYJvnN$QQr9Q$&e_6{d$pd95w@7de!HziZomOi+VnN7 zjxm7H0LjVZt}Nf~4oTo-mY?7}V6J zwQ5%^qO`jf0ynoUAuX-h8E(pO6n7Z%FtOLF4--2r-E?`*%7(s>JA5H7Rs@VCJ+QJ~ zT~@Ny35~7vLMw3bbER0ao5It8s7f0pl0@=a(VPIRnTIO6Q{@;|4J0Y!JgkRk?0|Mv z^WbMHc{vIVM?4i;=aOh5EN9H7vA{GaTQuY+87@XLlqG}>ypq~-REBg=nJ&rZOb$0p zo#_Rl!Zw1DD8|7E9tu><&gq_}<-ryR`P~p6WTG^t%e=};;?f+)Oj&MKU1d4kt7b?G zcUASWw|>d;o)E^eW$q2q(~-$#tE3`biq_nuYr}vm9a;&Sy5W4DJ!0)q`a}n1z^m&_ z-~bk6z07tAS9YfXn;B&0>H`}UcT0y9Hd4bi9$ybR=Aa6OMCapl;1U>4dvaBUkJfX` zD#fW~5pNo}O{^TM`Zoh9VNz>iaXWHRBV(g}q0LvF85%xl086do}h$O zxuZM!tEnlP$TVSP&Zil3(P}GlId%St$=|Et>NxCXxV4$EZT7R z#^;y;S&Z>s*U<#3d$%I$hWb1(3FJGXt-KjyaBH!$qBJwa%|Wi;Zb|A}b#(jqP6N5> zs`@eQGQ?*timLPDNa9ZUPf@wi#s)~rdbZP3PW?||!VyL^VOnxqa5ib@B6FR|C?)6v zq6ws2oyg)Q-qu7YhY1Q5Dsv%3@O-YaEp$7TcDx~_wR4cg+y=^{3q zxR2R(E*-Kmf|-mA4GkL(%f0YcJw<+^=;C!cH>a_w7IYNinh=p)S)rr@x|J!=(gK0* zhIi_JCDFfxM7~PcsUKH2i1D{ft073%Gm??vwif)9I*RtQV19`u@;f9OjVtA85u7Z= z#@|xVay2c4a`?RVQR|~&Va^b1Ax!1B7(mnr!Sz)wjgjU;Fc=HIfM@$HM-sr@dYO)U ztZn|FQQ52J&NRU6e9qt9RkdwSL-!m$>r?MFwNqzzKl`aXDFLayQs;j;dHO1E6qz!4pcAl@qXgNxW zBn*`@o?N|CQ^}|e)ujw%xD~5RC7w#zFR4yI^-`H0QxvhB1wE1ZeOA3} zb}}PQ0&UL&Wb}g#%7rmg?i$d=Q-LZB(1*7n9c1P_l*Dz7AmpL|qo*4ADKk@z8*@>N z=UB%@Ij37jReOmdhN(QHw1qqklxX3@vZu!pJk?lCmuTBT>Z4S!oT~#C2Fg6~?3DQ> ziYO{-JR(|C5LS8cN_OiI0K2NrKCnYBob_3nokOTiq-sR?83!qFPUkoeRZUA(;tp!o z-qKtNS-+{3lf*`*Xel#*N}52^$wQ_&z*BLYE&V)r6GS;$qdQ~SSWOrKSJe3xrtpTf zk+CK+GODhU7K6T2(Z+ZR6?2*-keni{pG=M&P@_8C^ITT7 zw>Ki)a>BsWwAzott?X2wxDpUFWV5kS?cmaaNJB@fdz4059K4qAYg){0l@0Wu?gD0O zh%VX6!invuiuU!%vx$LcM|gPl@vJZ>SzA*ZtRT~!d!e7i1x##XrMDdh6*0aP{m zNT~0RV1H6LE8O7Yl7fDsBH5fa7(I|#iSTDW&Xa$+c+zQU+tFvGsKMq`N}G{+E-uP~ z>fWT_EIKrsBZJnRsyrgs-aC|^c>wNJE35JGI0BRJrQ76XT3Tj8^$5OgVCRsWZBg5G zo)fsZ4MA8#CaiC`QO=AFSMFwxil@vLw$D2YM(Y7jDbC9B-(Kj5!YU7va!Bl$#&nu_ot;$Yn8#p`HCEE$z<>x zP&i{xAexS)q;pX2HR3qV90KYxjC>8;t__G0l?Iv3nCf=m ze0lXu&$#r_sgbQ~HVZ#7xu4qKj%~00NfR zWGKw?v}HKQqj0zFjt7!CqrHna`-r=orx zu~p$`ntWy77l@ zu{>9EY*ez6?qN{ZSs2wO$0Ts-$dA0qpUi)B6pEJvGmd$jpt*?I!BMVAMfh`?PC?x@ zG_4KBaG=*#7VQ|+QQPhJ3!8&k6N6pcDWgvtncmA$jtH{KT`oyD9FvjMyI(zsSG8Ol zRTM37X)g2%JUlC0@s`GS^isJ;7-fC`0FjvG$jIh5!kxCT zEwvA`x_IFrvwU_;{Uw&Kq9b0m6~0-|I%ZQ4O-&wMCXiL!Fq)&nmq7{#<73)m`H*1lgUK8tS*a#J)7dBRO2V~K!loSIPL z0Ltk!S}OF=+XJ7}YA1BJNPGB;qG3G9R2OTz$tA>w=aSIDL*uiegK*))Gf7vTalu)X zly_QrhCD{+)lO+^@uY&YRd&Zv)H$vj^eROmdqzXtK1B%S@W}FODe2hu;lLcGDr}5- z)Xarf1>#y#1BRj9TETvXP&2Vkz~wBJwN}|-ZbtZAC)+hksyK!!Qh(5bHsi55as9&d zeARHz9yJ4z3LPMP|3K z0vy;{NItu+ZDO@L?Qo~2W=pCjjvu>#UWVgt4>ri0`ay=o19Xm{ZT*!yAnZ-AVU?zq zPIXcXX~G@EfO) zL0V1e8EU#6j>?*{lSWP!-mU;zc3JD4IKew1D*~%1X@glH7(u87hgiz(2%xaI|l8Ws5zPOwtWz zFgD6EYZ+x}*SUgvh846FxoAa6 zPBtZ2#?2vV*CvL_BsWsz@=R1ww;YwgV8&AuMhMD$rJe?DGZWK>${8OMmxo@HTc_)M`^0SsxvqpM+pa^Z|~R}6M?2SrCFFsR~%=5QJoh8t@nglaiBQE6Lz3~7~SCR9|6bt_RpNXXjUDyXeGB@Sui zRirbBx@v3FB5q89 zMF)ab(=IBmA~14QB~K7FfaSvj)n>SdjA^Oicry)M23Iq^@wCs1NU1et!{aBCuXeRU zScu6urODCmym>(Zbbc^0b_)rA;#XWjYY&vHMI5tBBcCaAoOdLZVqdp4kE^!JUL^P{ zs~bcLnu6J!GEhmVZmCH@B$f(|@@j0{3LP*rjPKQSTVD)O(nQkMG!TzSWP?Lhr8s$R z`NG}O>7gHNo4SompSd1uToMch0+SV*o-zKI2jr}w8}63&fK{hdebExOUd&>e2x;B3 z0<&y`NXI2rHA5mkVghn1_=`4p`=J(>0FrN!>Wa9beqV(?gtD*?426upR2fI|-MXE@ zx04*ADT&B9B}E(8sj-b~;NDSNWDwFr$@f<=n`A4gB#2vW z@Gu%FIp74pdWuFJ!i96MXN2sKvqI!dx?2ALu~ACZ5=B#E+)Wg6kmmEspaa7jE6G^u zoM&|wrhtZnq=h9mDLzJ9TS%&N^UXDvH+GySCt+joQUh`^x%mZdaaiE0o5)SLz87W0 z;l5+?8?QF;4P&b=b(K#!GRjFk^5ReKy$O75w3b@>vcd##I|TP51NUBWxCb~BoSjDi z_5oq){{YoUnP*|O_9bi=UOckK=H;xY@!hvZ@BNphIMtE+l+JcKla9?Z8Lz346KE=Z6p$T zm7;>A95sZJdIfJoWK>Ghi^*lHph|SuZ!xl+YT@eI{5kD0xAj^E@LWPKFfMjFtqEL! zt8B+pPpSOYf{EIi3ah)=&9Yr=1PtyJ%Vh1)GF3TR+ruZW7&Me_RxNNLQqs-|*sB&y z0Nkdl3HFMq_zuf8c{&*5=&z@o79G}N`BV&U0H#jf2_q95bE#+!$yw7ebBSr{tt-ci zBZoy!$Ov$q+kKXWIOoU$#}tYZ;7vryYUjPDS*bDtmh9@>Mw}9Czx6&K@JLC zGg%(6*95nKBipj8xV*+1^R_ouLvS12K)*D5xBzah&#aJ5WYqAr;u+y+)-?f)Wosj^ zV@7q4s^L^ud2OgND3!an)3{8Id~`Luv}lpF;f>ZCkbXNbdordAh7q4INA@b8398--a}M(7FIb$Y8ybe}56-|gCRKvXp}%DH4t1`b$W zU)2SnZM#!JBXksM_wZNrj;~1vigjUHFa|dn2{h1naOWKrRmS7)jyjG4>?*P`T$ZMs znQqrG9ONX(;f#W_Lx>s3xlD%c$yd99X6w%2RHeAkhw;ah5ViGY3{eyY@Y67T;&~;945$jdQzhc{_fAYo(xM!*H~8^eJi7U%LLIB>88Y zD0o)xZU&6NcK-mI_;9+f3h*pcF}3oK5>Bpi*+pZ4kJX{M`70=(Y)#lEgn#vm8@eGWr>bA1N#te|N z*NfB?t#ccUgYAT>6-0W1YDXVK;fOab{6~Ho1eN~!ha)UFZ_Rj}Mv^-BMKyle^sHsMP zNLbT5O?u2zG9MtQ}067akEc#!uR3$xTWE1980jXjjYKY zWGkv#U?Hv=ioK`QHn3H)Ugd4pzDZ{+h@O1VYdlCBvDMWbEh&-OoPO$GhUOkyE7F=s zsjbtf)gTB(r!}EUk6M8N-3W%G=UiVUevaBRE{zo%&?RCplMi^|$~W zr9IWlbVgHS=-WwkhCC2*qtw+ls9>!4s_`3vxl*AnXv4@;$5AN_vd57%^ek{Eb)BlF zF~7><2hC_JCeXu&ES=Wo?Pa57JSIo#{FPHe^HyEEv&iLZxPH$iLtD00EwY>5oFpSU zdajeg6qo>!u}^UI8i?qm-bZcxJB>LC^_H&)4=&2~l8vncE!zrf=~*K*hVO-|PLeQ0 z@!+MTqz!PuR=(&Q--IV1r0~u(sbQOLrrj75Mh;yRRkZkw?6Ft6Q0BW(9*d(^#NQ0; zu=mK^=MdGIt+EnWCR%x8CVCrlOk;d~5LYyo*9P z)DT-X^cwpx(K*;~$-pW_4AKd39&ivrK)Xcq=wpfrH1GK?Jz4`U4%4=GC?J(z>d4I1 z_KhWt?(%MVttU4e@5uxfR;S$9@u@kY(v_o6B{n^?gb-LZ9sM6_Ev>}r3r|J6P(fnq zh&80Av7~O$q0J0?`2q+kwRTahk=q*@;ib6wD{EWa*@hfO=peK-&l-qhbzpRL_v=k;f$j7G}Tf zELJl{Nz=Nr$yEZ?FCELr~mts`QOu+&m~1JyrJNMXVV zElB;MW@_|&g<~sRL3R%$5Lp_ZyicMmPIft@xy~{GNkIiBpR`w*aY6x)l3c)J2q3iQ z&}uBL;CN%?kzc${$_Ogf{e+9|GZn1`uGvvb8+=Y(5J6{0v6hWQ(c*Ga<0n=SK`D?| z*>7zblx11Vv$jD69bFMmvJG&{3dr3WGn{Xf5LWB$5KOe;z2kU2mrdbjj{%!?K?Q1$ zxV2YE+|v9brT`%>)*Hqq9Peh&BHJ0a)tb9X<%k2rLa(-i=!R W##>Ru&v$Q>Ac6~0A8IH*&;Qw&gu-k9 literal 0 HcmV?d00001 diff --git a/deploy/paddleserving/image_http_client.py b/deploy/paddleserving/image_http_client.py deleted file mode 100644 index 4e33c4a7..00000000 --- a/deploy/paddleserving/image_http_client.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import requests -import base64 -import json -import sys -import numpy as np - -py_version = sys.version_info[0] - - -def predict(image_path, server): - - with open(image_path, "rb") as f: - image = base64.b64encode(f.read()).decode("utf-8") - req = json.dumps({"feed": [{"image": image}], "fetch": ["prediction"]}) - r = requests.post( - server, data=req, headers={"Content-Type": "application/json"}) - try: - pred = r.json()["result"]["prediction"][0] - cls_id = np.argmax(pred) - score = pred[cls_id] - pred = {"cls_id": cls_id, "score": score} - return pred - except ValueError: - print(r.text) - return r - - -if __name__ == "__main__": - server = "http://127.0.0.1:{}/image/prediction".format(sys.argv[1]) - image_file = sys.argv[2] - res = predict(image_file, server) - print("res:", res) diff --git a/deploy/paddleserving/image_service_cpu.py b/deploy/paddleserving/image_service_cpu.py deleted file mode 100644 index 92f67d32..00000000 --- a/deploy/paddleserving/image_service_cpu.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import base64 -from paddle_serving_server.web_service import WebService -import utils - - -class ImageService(WebService): - def __init__(self, name): - super(ImageService, self).__init__(name=name) - self.operators = self.create_operators() - - def create_operators(self): - size = 224 - img_mean = [0.485, 0.456, 0.406] - img_std = [0.229, 0.224, 0.225] - img_scale = 1.0 / 255.0 - decode_op = utils.DecodeImage() - resize_op = utils.ResizeImage(resize_short=256) - crop_op = utils.CropImage(size=(size, size)) - normalize_op = utils.NormalizeImage( - scale=img_scale, mean=img_mean, std=img_std) - totensor_op = utils.ToTensor() - return [decode_op, resize_op, crop_op, normalize_op, totensor_op] - - def _process_image(self, data, ops): - for op in ops: - data = op(data) - return data - - def preprocess(self, feed={}, fetch=[]): - feed_batch = [] - for ins in feed: - if "image" not in ins: - raise ("feed data error!") - sample = base64.b64decode(ins["image"]) - img = self._process_image(sample, self.operators) - feed_batch.append({"image": img}) - return feed_batch, fetch - - -image_service = ImageService(name="image") -image_service.load_model_config(sys.argv[1]) -image_service.prepare_server( - workdir=sys.argv[2], port=int(sys.argv[3]), device="cpu") -image_service.run_server() -image_service.run_flask() diff --git a/deploy/paddleserving/image_service_gpu.py b/deploy/paddleserving/image_service_gpu.py deleted file mode 100644 index df61cdd6..00000000 --- a/deploy/paddleserving/image_service_gpu.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import base64 -from paddle_serving_server_gpu.web_service import WebService - -import utils - - -class ImageService(WebService): - def __init__(self, name): - super(ImageService, self).__init__(name=name) - self.operators = self.create_operators() - - def create_operators(self): - size = 224 - img_mean = [0.485, 0.456, 0.406] - img_std = [0.229, 0.224, 0.225] - img_scale = 1.0 / 255.0 - decode_op = utils.DecodeImage() - resize_op = utils.ResizeImage(resize_short=256) - crop_op = utils.CropImage(size=(size, size)) - normalize_op = utils.NormalizeImage( - scale=img_scale, mean=img_mean, std=img_std) - totensor_op = utils.ToTensor() - return [decode_op, resize_op, crop_op, normalize_op, totensor_op] - - def _process_image(self, data, ops): - for op in ops: - data = op(data) - return data - - def preprocess(self, feed={}, fetch=[]): - feed_batch = [] - for ins in feed: - if "image" not in ins: - raise ("feed data error!") - sample = base64.b64decode(ins["image"]) - img = self._process_image(sample, self.operators) - feed_batch.append({"image": img}) - return feed_batch, fetch - - -image_service = ImageService(name="image") -image_service.load_model_config(sys.argv[1]) -image_service.set_gpus("0") -image_service.prepare_server( - workdir=sys.argv[2], port=int(sys.argv[3]), device="gpu") -image_service.run_server() -image_service.run_flask() diff --git a/deploy/paddleserving/imagenet.label b/deploy/paddleserving/imagenet.label new file mode 100644 index 00000000..d7146735 --- /dev/null +++ b/deploy/paddleserving/imagenet.label @@ -0,0 +1,1000 @@ +tench, Tinca tinca, +goldfish, Carassius auratus, +great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias, +tiger shark, Galeocerdo cuvieri, +hammerhead, hammerhead shark, +electric ray, crampfish, numbfish, torpedo, +stingray, +cock, +hen, +ostrich, Struthio camelus, +brambling, Fringilla montifringilla, +goldfinch, Carduelis carduelis, +house finch, linnet, Carpodacus mexicanus, +junco, snowbird, +indigo bunting, indigo finch, indigo bird, Passerina cyanea, +robin, American robin, Turdus migratorius, +bulbul, +jay, +magpie, +chickadee, +water ouzel, dipper, +kite, +bald eagle, American eagle, Haliaeetus leucocephalus, +vulture, +great grey owl, great gray owl, Strix nebulosa, +European fire salamander, Salamandra salamandra, +common newt, Triturus vulgaris, +eft, +spotted salamander, Ambystoma maculatum, +axolotl, mud puppy, Ambystoma mexicanum, +bullfrog, Rana catesbeiana, +tree frog, tree-frog, +tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui, +loggerhead, loggerhead turtle, Caretta caretta, +leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea, +mud turtle, +terrapin, +box turtle, box tortoise, +banded gecko, +common iguana, iguana, Iguana iguana, +American chameleon, anole, Anolis carolinensis, +whiptail, whiptail lizard, +agama, +frilled lizard, Chlamydosaurus kingi, +alligator lizard, +Gila monster, Heloderma suspectum, +green lizard, Lacerta viridis, +African chameleon, Chamaeleo chamaeleon, +Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis, +African crocodile, Nile crocodile, Crocodylus niloticus, +American alligator, Alligator mississipiensis, +triceratops, +thunder snake, worm snake, Carphophis amoenus, +ringneck snake, ring-necked snake, ring snake, +hognose snake, puff adder, sand viper, +green snake, grass snake, +king snake, kingsnake, +garter snake, grass snake, +water snake, +vine snake, +night snake, Hypsiglena torquata, +boa constrictor, Constrictor constrictor, +rock python, rock snake, Python sebae, +Indian cobra, Naja naja, +green mamba, +sea snake, +horned viper, cerastes, sand viper, horned asp, Cerastes cornutus, +diamondback, diamondback rattlesnake, Crotalus adamanteus, +sidewinder, horned rattlesnake, Crotalus cerastes, +trilobite, +harvestman, daddy longlegs, Phalangium opilio, +scorpion, +black and gold garden spider, Argiope aurantia, +barn spider, Araneus cavaticus, +garden spider, Aranea diademata, +black widow, Latrodectus mactans, +tarantula, +wolf spider, hunting spider, +tick, +centipede, +black grouse, +ptarmigan, +ruffed grouse, partridge, Bonasa umbellus, +prairie chicken, prairie grouse, prairie fowl, +peacock, +quail, +partridge, +African grey, African gray, Psittacus erithacus, +macaw, +sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita, +lorikeet, +coucal, +bee eater, +hornbill, +hummingbird, +jacamar, +toucan, +drake, +red-breasted merganser, Mergus serrator, +goose, +black swan, Cygnus atratus, +tusker, +echidna, spiny anteater, anteater, +platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus, +wallaby, brush kangaroo, +koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus, +wombat, +jellyfish, +sea anemone, anemone, +brain coral, +flatworm, platyhelminth, +nematode, nematode worm, roundworm, +conch, +snail, +slug, +sea slug, nudibranch, +chiton, coat-of-mail shell, sea cradle, polyplacophore, +chambered nautilus, pearly nautilus, nautilus, +Dungeness crab, Cancer magister, +rock crab, Cancer irroratus, +fiddler crab, +king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica, +American lobster, Northern lobster, Maine lobster, Homarus americanus, +spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish, +crayfish, crawfish, crawdad, crawdaddy, +hermit crab, +isopod, +white stork, Ciconia ciconia, +black stork, Ciconia nigra, +spoonbill, +flamingo, +little blue heron, Egretta caerulea, +American egret, great white heron, Egretta albus, +bittern, +crane, +limpkin, Aramus pictus, +European gallinule, Porphyrio porphyrio, +American coot, marsh hen, mud hen, water hen, Fulica americana, +bustard, +ruddy turnstone, Arenaria interpres, +red-backed sandpiper, dunlin, Erolia alpina, +redshank, Tringa totanus, +dowitcher, +oystercatcher, oyster catcher, +pelican, +king penguin, Aptenodytes patagonica, +albatross, mollymawk, +grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus, +killer whale, killer, orca, grampus, sea wolf, Orcinus orca, +dugong, Dugong dugon, +sea lion, +Chihuahua, +Japanese spaniel, +Maltese dog, Maltese terrier, Maltese, +Pekinese, Pekingese, Peke, +Shih-Tzu, +Blenheim spaniel, +papillon, +toy terrier, +Rhodesian ridgeback, +Afghan hound, Afghan, +basset, basset hound, +beagle, +bloodhound, sleuthhound, +bluetick, +black-and-tan coonhound, +Walker hound, Walker foxhound, +English foxhound, +redbone, +borzoi, Russian wolfhound, +Irish wolfhound, +Italian greyhound, +whippet, +Ibizan hound, Ibizan Podenco, +Norwegian elkhound, elkhound, +otterhound, otter hound, +Saluki, gazelle hound, +Scottish deerhound, deerhound, +Weimaraner, +Staffordshire bullterrier, Staffordshire bull terrier, +American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier, +Bedlington terrier, +Border terrier, +Kerry blue terrier, +Irish terrier, +Norfolk terrier, +Norwich terrier, +Yorkshire terrier, +wire-haired fox terrier, +Lakeland terrier, +Sealyham terrier, Sealyham, +Airedale, Airedale terrier, +cairn, cairn terrier, +Australian terrier, +Dandie Dinmont, Dandie Dinmont terrier, +Boston bull, Boston terrier, +miniature schnauzer, +giant schnauzer, +standard schnauzer, +Scotch terrier, Scottish terrier, Scottie, +Tibetan terrier, chrysanthemum dog, +silky terrier, Sydney silky, +soft-coated wheaten terrier, +West Highland white terrier, +Lhasa, Lhasa apso, +flat-coated retriever, +curly-coated retriever, +golden retriever, +Labrador retriever, +Chesapeake Bay retriever, +German short-haired pointer, +vizsla, Hungarian pointer, +English setter, +Irish setter, red setter, +Gordon setter, +Brittany spaniel, +clumber, clumber spaniel, +English springer, English springer spaniel, +Welsh springer spaniel, +cocker spaniel, English cocker spaniel, cocker, +Sussex spaniel, +Irish water spaniel, +kuvasz, +schipperke, +groenendael, +malinois, +briard, +kelpie, +komondor, +Old English sheepdog, bobtail, +Shetland sheepdog, Shetland sheep dog, Shetland, +collie, +Border collie, +Bouvier des Flandres, Bouviers des Flandres, +Rottweiler, +German shepherd, German shepherd dog, German police dog, alsatian, +Doberman, Doberman pinscher, +miniature pinscher, +Greater Swiss Mountain dog, +Bernese mountain dog, +Appenzeller, +EntleBucher, +boxer, +bull mastiff, +Tibetan mastiff, +French bulldog, +Great Dane, +Saint Bernard, St Bernard, +Eskimo dog, husky, +malamute, malemute, Alaskan malamute, +Siberian husky, +dalmatian, coach dog, carriage dog, +affenpinscher, monkey pinscher, monkey dog, +basenji, +pug, pug-dog, +Leonberg, +Newfoundland, Newfoundland dog, +Great Pyrenees, +Samoyed, Samoyede, +Pomeranian, +chow, chow chow, +keeshond, +Brabancon griffon, +Pembroke, Pembroke Welsh corgi, +Cardigan, Cardigan Welsh corgi, +toy poodle, +miniature poodle, +standard poodle, +Mexican hairless, +timber wolf, grey wolf, gray wolf, Canis lupus, +white wolf, Arctic wolf, Canis lupus tundrarum, +red wolf, maned wolf, Canis rufus, Canis niger, +coyote, prairie wolf, brush wolf, Canis latrans, +dingo, warrigal, warragal, Canis dingo, +dhole, Cuon alpinus, +African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus, +hyena, hyaena, +red fox, Vulpes vulpes, +kit fox, Vulpes macrotis, +Arctic fox, white fox, Alopex lagopus, +grey fox, gray fox, Urocyon cinereoargenteus, +tabby, tabby cat, +tiger cat, +Persian cat, +Siamese cat, Siamese, +Egyptian cat, +cougar, puma, catamount, mountain lion, painter, panther, Felis concolor, +lynx, catamount, +leopard, Panthera pardus, +snow leopard, ounce, Panthera uncia, +jaguar, panther, Panthera onca, Felis onca, +lion, king of beasts, Panthera leo, +tiger, Panthera tigris, +cheetah, chetah, Acinonyx jubatus, +brown bear, bruin, Ursus arctos, +American black bear, black bear, Ursus americanus, Euarctos americanus, +ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus, +sloth bear, Melursus ursinus, Ursus ursinus, +mongoose, +meerkat, mierkat, +tiger beetle, +ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle, +ground beetle, carabid beetle, +long-horned beetle, longicorn, longicorn beetle, +leaf beetle, chrysomelid, +dung beetle, +rhinoceros beetle, +weevil, +fly, +bee, +ant, emmet, pismire, +grasshopper, hopper, +cricket, +walking stick, walkingstick, stick insect, +cockroach, roach, +mantis, mantid, +cicada, cicala, +leafhopper, +lacewing, lacewing fly, +"dragonfly, darning needle, devils darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk", +damselfly, +admiral, +ringlet, ringlet butterfly, +monarch, monarch butterfly, milkweed butterfly, Danaus plexippus, +cabbage butterfly, +sulphur butterfly, sulfur butterfly, +lycaenid, lycaenid butterfly, +starfish, sea star, +sea urchin, +sea cucumber, holothurian, +wood rabbit, cottontail, cottontail rabbit, +hare, +Angora, Angora rabbit, +hamster, +porcupine, hedgehog, +fox squirrel, eastern fox squirrel, Sciurus niger, +marmot, +beaver, +guinea pig, Cavia cobaya, +sorrel, +zebra, +hog, pig, grunter, squealer, Sus scrofa, +wild boar, boar, Sus scrofa, +warthog, +hippopotamus, hippo, river horse, Hippopotamus amphibius, +ox, +water buffalo, water ox, Asiatic buffalo, Bubalus bubalis, +bison, +ram, tup, +bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis, +ibex, Capra ibex, +hartebeest, +impala, Aepyceros melampus, +gazelle, +Arabian camel, dromedary, Camelus dromedarius, +llama, +weasel, +mink, +polecat, fitch, foulmart, foumart, Mustela putorius, +black-footed ferret, ferret, Mustela nigripes, +otter, +skunk, polecat, wood pussy, +badger, +armadillo, +three-toed sloth, ai, Bradypus tridactylus, +orangutan, orang, orangutang, Pongo pygmaeus, +gorilla, Gorilla gorilla, +chimpanzee, chimp, Pan troglodytes, +gibbon, Hylobates lar, +siamang, Hylobates syndactylus, Symphalangus syndactylus, +guenon, guenon monkey, +patas, hussar monkey, Erythrocebus patas, +baboon, +macaque, +langur, +colobus, colobus monkey, +proboscis monkey, Nasalis larvatus, +marmoset, +capuchin, ringtail, Cebus capucinus, +howler monkey, howler, +titi, titi monkey, +spider monkey, Ateles geoffroyi, +squirrel monkey, Saimiri sciureus, +Madagascar cat, ring-tailed lemur, Lemur catta, +indri, indris, Indri indri, Indri brevicaudatus, +Indian elephant, Elephas maximus, +African elephant, Loxodonta africana, +lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens, +giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca, +barracouta, snoek, +eel, +coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch, +rock beauty, Holocanthus tricolor, +anemone fish, +sturgeon, +gar, garfish, garpike, billfish, Lepisosteus osseus, +lionfish, +puffer, pufferfish, blowfish, globefish, +abacus, +abaya, +"academic gown, academic robe, judges robe", +accordion, piano accordion, squeeze box, +acoustic guitar, +aircraft carrier, carrier, flattop, attack aircraft carrier, +airliner, +airship, dirigible, +altar, +ambulance, +amphibian, amphibious vehicle, +analog clock, +apiary, bee house, +apron, +ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin, +assault rifle, assault gun, +backpack, back pack, knapsack, packsack, rucksack, haversack, +bakery, bakeshop, bakehouse, +balance beam, beam, +balloon, +ballpoint, ballpoint pen, ballpen, Biro, +Band Aid, +banjo, +bannister, banister, balustrade, balusters, handrail, +barbell, +barber chair, +barbershop, +barn, +barometer, +barrel, cask, +barrow, garden cart, lawn cart, wheelbarrow, +baseball, +basketball, +bassinet, +bassoon, +bathing cap, swimming cap, +bath towel, +bathtub, bathing tub, bath, tub, +beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon, +beacon, lighthouse, beacon light, pharos, +beaker, +bearskin, busby, shako, +beer bottle, +beer glass, +bell cote, bell cot, +bib, +bicycle-built-for-two, tandem bicycle, tandem, +bikini, two-piece, +binder, ring-binder, +binoculars, field glasses, opera glasses, +birdhouse, +boathouse, +bobsled, bobsleigh, bob, +bolo tie, bolo, bola tie, bola, +bonnet, poke bonnet, +bookcase, +bookshop, bookstore, bookstall, +bottlecap, +bow, +bow tie, bow-tie, bowtie, +brass, memorial tablet, plaque, +brassiere, bra, bandeau, +breakwater, groin, groyne, mole, bulwark, seawall, jetty, +breastplate, aegis, egis, +broom, +bucket, pail, +buckle, +bulletproof vest, +bullet train, bullet, +butcher shop, meat market, +cab, hack, taxi, taxicab, +caldron, cauldron, +candle, taper, wax light, +cannon, +canoe, +can opener, tin opener, +cardigan, +car mirror, +carousel, carrousel, merry-go-round, roundabout, whirligig, +"carpenters kit, tool kit", +carton, +car wheel, +cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM, +cassette, +cassette player, +castle, +catamaran, +CD player, +cello, violoncello, +cellular telephone, cellular phone, cellphone, cell, mobile phone, +chain, +chainlink fence, +chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour, +chain saw, chainsaw, +chest, +chiffonier, commode, +chime, bell, gong, +china cabinet, china closet, +Christmas stocking, +church, church building, +cinema, movie theater, movie theatre, movie house, picture palace, +cleaver, meat cleaver, chopper, +cliff dwelling, +cloak, +clog, geta, patten, sabot, +cocktail shaker, +coffee mug, +coffeepot, +coil, spiral, volute, whorl, helix, +combination lock, +computer keyboard, keypad, +confectionery, confectionary, candy store, +container ship, containership, container vessel, +convertible, +corkscrew, bottle screw, +cornet, horn, trumpet, trump, +cowboy boot, +cowboy hat, ten-gallon hat, +cradle, +crane, +crash helmet, +crate, +crib, cot, +Crock Pot, +croquet ball, +crutch, +cuirass, +dam, dike, dyke, +desk, +desktop computer, +dial telephone, dial phone, +diaper, nappy, napkin, +digital clock, +digital watch, +dining table, board, +dishrag, dishcloth, +dishwasher, dish washer, dishwashing machine, +disk brake, disc brake, +dock, dockage, docking facility, +dogsled, dog sled, dog sleigh, +dome, +doormat, welcome mat, +drilling platform, offshore rig, +drum, membranophone, tympan, +drumstick, +dumbbell, +Dutch oven, +electric fan, blower, +electric guitar, +electric locomotive, +entertainment center, +envelope, +espresso maker, +face powder, +feather boa, boa, +file, file cabinet, filing cabinet, +fireboat, +fire engine, fire truck, +fire screen, fireguard, +flagpole, flagstaff, +flute, transverse flute, +folding chair, +football helmet, +forklift, +fountain, +fountain pen, +four-poster, +freight car, +French horn, horn, +frying pan, frypan, skillet, +fur coat, +garbage truck, dustcart, +gasmask, respirator, gas helmet, +gas pump, gasoline pump, petrol pump, island dispenser, +goblet, +go-kart, +golf ball, +golfcart, golf cart, +gondola, +gong, tam-tam, +gown, +grand piano, grand, +greenhouse, nursery, glasshouse, +grille, radiator grille, +grocery store, grocery, food market, market, +guillotine, +hair slide, +hair spray, +half track, +hammer, +hamper, +hand blower, blow dryer, blow drier, hair dryer, hair drier, +hand-held computer, hand-held microcomputer, +handkerchief, hankie, hanky, hankey, +hard disc, hard disk, fixed disk, +harmonica, mouth organ, harp, mouth harp, +harp, +harvester, reaper, +hatchet, +holster, +home theater, home theatre, +honeycomb, +hook, claw, +hoopskirt, crinoline, +horizontal bar, high bar, +horse cart, horse-cart, +hourglass, +iPod, +iron, smoothing iron, +"jack-o-lantern", +jean, blue jean, denim, +jeep, landrover, +jersey, T-shirt, tee shirt, +jigsaw puzzle, +jinrikisha, ricksha, rickshaw, +joystick, +kimono, +knee pad, +knot, +lab coat, laboratory coat, +ladle, +lampshade, lamp shade, +laptop, laptop computer, +lawn mower, mower, +lens cap, lens cover, +letter opener, paper knife, paperknife, +library, +lifeboat, +lighter, light, igniter, ignitor, +limousine, limo, +liner, ocean liner, +lipstick, lip rouge, +Loafer, +lotion, +loudspeaker, speaker, speaker unit, loudspeaker system, speaker system, +"loupe, jewelers loupe", +lumbermill, sawmill, +magnetic compass, +mailbag, postbag, +mailbox, letter box, +maillot, +maillot, tank suit, +manhole cover, +maraca, +marimba, xylophone, +mask, +matchstick, +maypole, +maze, labyrinth, +measuring cup, +medicine chest, medicine cabinet, +megalith, megalithic structure, +microphone, mike, +microwave, microwave oven, +military uniform, +milk can, +minibus, +miniskirt, mini, +minivan, +missile, +mitten, +mixing bowl, +mobile home, manufactured home, +Model T, +modem, +monastery, +monitor, +moped, +mortar, +mortarboard, +mosque, +mosquito net, +motor scooter, scooter, +mountain bike, all-terrain bike, off-roader, +mountain tent, +mouse, computer mouse, +mousetrap, +moving van, +muzzle, +nail, +neck brace, +necklace, +nipple, +notebook, notebook computer, +obelisk, +oboe, hautboy, hautbois, +ocarina, sweet potato, +odometer, hodometer, mileometer, milometer, +oil filter, +organ, pipe organ, +oscilloscope, scope, cathode-ray oscilloscope, CRO, +overskirt, +oxcart, +oxygen mask, +packet, +paddle, boat paddle, +paddlewheel, paddle wheel, +padlock, +paintbrush, +"pajama, pyjama, pjs, jammies", +palace, +panpipe, pandean pipe, syrinx, +paper towel, +parachute, chute, +parallel bars, bars, +park bench, +parking meter, +passenger car, coach, carriage, +patio, terrace, +pay-phone, pay-station, +pedestal, plinth, footstall, +pencil box, pencil case, +pencil sharpener, +perfume, essence, +Petri dish, +photocopier, +pick, plectrum, plectron, +pickelhaube, +picket fence, paling, +pickup, pickup truck, +pier, +piggy bank, penny bank, +pill bottle, +pillow, +ping-pong ball, +pinwheel, +pirate, pirate ship, +pitcher, ewer, +"plane, carpenters plane, woodworking plane", +planetarium, +plastic bag, +plate rack, +plow, plough, +"plunger, plumbers helper", +Polaroid camera, Polaroid Land camera, +pole, +police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria, +poncho, +pool table, billiard table, snooker table, +pop bottle, soda bottle, +pot, flowerpot, +"potters wheel", +power drill, +prayer rug, prayer mat, +printer, +prison, prison house, +projectile, missile, +projector, +puck, hockey puck, +punching bag, punch bag, punching ball, punchball, +purse, +quill, quill pen, +quilt, comforter, comfort, puff, +racer, race car, racing car, +racket, racquet, +radiator, +radio, wireless, +radio telescope, radio reflector, +rain barrel, +recreational vehicle, RV, R.V., +reel, +reflex camera, +refrigerator, icebox, +remote control, remote, +restaurant, eating house, eating place, eatery, +revolver, six-gun, six-shooter, +rifle, +rocking chair, rocker, +rotisserie, +rubber eraser, rubber, pencil eraser, +rugby ball, +rule, ruler, +running shoe, +safe, +safety pin, +saltshaker, salt shaker, +sandal, +sarong, +sax, saxophone, +scabbard, +scale, weighing machine, +school bus, +schooner, +scoreboard, +screen, CRT screen, +screw, +screwdriver, +seat belt, seatbelt, +sewing machine, +shield, buckler, +shoe shop, shoe-shop, shoe store, +shoji, +shopping basket, +shopping cart, +shovel, +shower cap, +shower curtain, +ski, +ski mask, +sleeping bag, +slide rule, slipstick, +sliding door, +slot, one-armed bandit, +snorkel, +snowmobile, +snowplow, snowplough, +soap dispenser, +soccer ball, +sock, +solar dish, solar collector, solar furnace, +sombrero, +soup bowl, +space bar, +space heater, +space shuttle, +spatula, +speedboat, +"spider web, spiders web", +spindle, +sports car, sport car, +spotlight, spot, +stage, +steam locomotive, +steel arch bridge, +steel drum, +stethoscope, +stole, +stone wall, +stopwatch, stop watch, +stove, +strainer, +streetcar, tram, tramcar, trolley, trolley car, +stretcher, +studio couch, day bed, +stupa, tope, +submarine, pigboat, sub, U-boat, +suit, suit of clothes, +sundial, +sunglass, +sunglasses, dark glasses, shades, +sunscreen, sunblock, sun blocker, +suspension bridge, +swab, swob, mop, +sweatshirt, +swimming trunks, bathing trunks, +swing, +switch, electric switch, electrical switch, +syringe, +table lamp, +tank, army tank, armored combat vehicle, armoured combat vehicle, +tape player, +teapot, +teddy, teddy bear, +television, television system, +tennis ball, +thatch, thatched roof, +theater curtain, theatre curtain, +thimble, +thresher, thrasher, threshing machine, +throne, +tile roof, +toaster, +tobacco shop, tobacconist shop, tobacconist, +toilet seat, +torch, +totem pole, +tow truck, tow car, wrecker, +toyshop, +tractor, +trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi, +tray, +trench coat, +tricycle, trike, velocipede, +trimaran, +tripod, +triumphal arch, +trolleybus, trolley coach, trackless trolley, +trombone, +tub, vat, +turnstile, +typewriter keyboard, +umbrella, +unicycle, monocycle, +upright, upright piano, +vacuum, vacuum cleaner, +vase, +vault, +velvet, +vending machine, +vestment, +viaduct, +violin, fiddle, +volleyball, +waffle iron, +wall clock, +wallet, billfold, notecase, pocketbook, +wardrobe, closet, press, +warplane, military plane, +washbasin, handbasin, washbowl, lavabo, wash-hand basin, +washer, automatic washer, washing machine, +water bottle, +water jug, +water tower, +whiskey jug, +whistle, +wig, +window screen, +window shade, +Windsor tie, +wine bottle, +wing, +wok, +wooden spoon, +wool, woolen, woollen, +worm fence, snake fence, snake-rail fence, Virginia fence, +wreck, +yawl, +yurt, +web site, website, internet site, site, +comic book, +crossword puzzle, crossword, +street sign, +traffic light, traffic signal, stoplight, +book jacket, dust cover, dust jacket, dust wrapper, +menu, +plate, +guacamole, +consomme, +hot pot, hotpot, +trifle, +ice cream, icecream, +ice lolly, lolly, lollipop, popsicle, +French loaf, +bagel, beigel, +pretzel, +cheeseburger, +hotdog, hot dog, red hot, +mashed potato, +head cabbage, +broccoli, +cauliflower, +zucchini, courgette, +spaghetti squash, +acorn squash, +butternut squash, +cucumber, cuke, +artichoke, globe artichoke, +bell pepper, +cardoon, +mushroom, +Granny Smith, +strawberry, +orange, +lemon, +fig, +pineapple, ananas, +banana, +jackfruit, jak, jack, +custard apple, +pomegranate, +hay, +carbonara, +chocolate sauce, chocolate syrup, +dough, +meat loaf, meatloaf, +pizza, pizza pie, +potpie, +burrito, +red wine, +espresso, +cup, +eggnog, +alp, +bubble, +cliff, drop, drop-off, +coral reef, +geyser, +lakeside, lakeshore, +promontory, headland, head, foreland, +sandbar, sand bar, +seashore, coast, seacoast, sea-coast, +valley, vale, +volcano, +ballplayer, baseball player, +groom, bridegroom, +scuba diver, +rapeseed, +daisy, +"yellow ladys slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum", +corn, +acorn, +hip, rose hip, rosehip, +buckeye, horse chestnut, conker, +coral fungus, +agaric, +gyromitra, +stinkhorn, carrion fungus, +earthstar, +hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa, +bolete, +ear, spike, capitulum, +toilet tissue, toilet paper, bathroom tissue diff --git a/deploy/paddleserving/pipeline_http_client.py b/deploy/paddleserving/pipeline_http_client.py new file mode 100644 index 00000000..bc3fab25 --- /dev/null +++ b/deploy/paddleserving/pipeline_http_client.py @@ -0,0 +1,19 @@ +import numpy as np +import requests +import json +import cv2 +import base64 +import os + +def cv2_to_base64(image): + return base64.b64encode(image).decode('utf8') + +if __name__ == "__main__": + url = "http://127.0.0.1:18080/imagenet/prediction" + with open(os.path.join(".", "daisy.jpg"), 'rb') as file: + image_data1 = file.read() + image = cv2_to_base64(image_data1) + data = {"key": ["image"], "value": [image]} + for i in range(100): + r = requests.post(url=url, data=json.dumps(data)) + print(r.json()) diff --git a/deploy/paddleserving/pipeline_rpc_client.py b/deploy/paddleserving/pipeline_rpc_client.py new file mode 100644 index 00000000..62de9ea9 --- /dev/null +++ b/deploy/paddleserving/pipeline_rpc_client.py @@ -0,0 +1,38 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +try: + from paddle_serving_server_gpu.pipeline import PipelineClient +except ImportError: + from paddle_serving_server.pipeline import PipelineClient +import numpy as np +import requests +import json +import cv2 +import base64 +import os + +client = PipelineClient() +client.connect(['127.0.0.1:9993']) + +def cv2_to_base64(image): + return base64.b64encode(image).decode('utf8') + +if __name__ == "__main__": + with open("daisy.jpg", 'rb') as file: + image_data = file.read() + image = cv2_to_base64(image_data) + + for i in range(1): + ret = client.predict(feed_dict={"image": image}, fetch=["label", "prob"]) + print(ret) diff --git a/deploy/paddleserving/resnet50_web_service.py b/deploy/paddleserving/resnet50_web_service.py new file mode 100644 index 00000000..6c353eb1 --- /dev/null +++ b/deploy/paddleserving/resnet50_web_service.py @@ -0,0 +1,73 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import sys +from paddle_serving_app.reader import Sequential, URL2Image, Resize, CenterCrop, RGB2BGR, Transpose, Div, Normalize, Base64ToImage +try: + from paddle_serving_server_gpu.web_service import WebService, Op +except ImportError: + from paddle_serving_server.web_service import WebService, Op +import logging +import numpy as np +import base64, cv2 + +class ImagenetOp(Op): + def init_op(self): + self.seq = Sequential([ + Resize(256), CenterCrop(224), RGB2BGR(), Transpose((2, 0, 1)), + Div(255), Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225], + True) + ]) + self.label_dict = {} + label_idx = 0 + with open("imagenet.label") as fin: + for line in fin: + self.label_dict[label_idx] = line.strip() + label_idx += 1 + + def preprocess(self, input_dicts, data_id, log_id): + (_, input_dict), = input_dicts.items() + batch_size = len(input_dict.keys()) + imgs = [] + for key in input_dict.keys(): + data = base64.b64decode(input_dict[key].encode('utf8')) + data = np.fromstring(data, np.uint8) + im = cv2.imdecode(data, cv2.IMREAD_COLOR) + img = self.seq(im) + imgs.append(img[np.newaxis, :].copy()) + input_imgs = np.concatenate(imgs, axis=0) + return {"image": input_imgs}, False, None, "" + + def postprocess(self, input_dicts, fetch_dict, log_id): + score_list = fetch_dict["prediction"] + result = {"label": [], "prob": []} + for score in score_list: + score = score.tolist() + max_score = max(score) + result["label"].append(self.label_dict[score.index(max_score)] + .strip().replace(",", "")) + result["prob"].append(max_score) + result["label"] = str(result["label"]) + result["prob"] = str(result["prob"]) + return result, None, "" + + +class ImageService(WebService): + def get_pipeline_response(self, read_op): + image_op = ImagenetOp(name="imagenet", input_ops=[read_op]) + return image_op + + +uci_service = ImageService(name="imagenet") +uci_service.prepare_pipeline_config("config.yml") +uci_service.run_service() diff --git a/deploy/paddleserving/utils.py b/deploy/paddleserving/utils.py deleted file mode 100644 index 6c4a75e1..00000000 --- a/deploy/paddleserving/utils.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import cv2 -import numpy as np - - -class DecodeImage(object): - def __init__(self, to_rgb=True): - self.to_rgb = to_rgb - - def __call__(self, img): - data = np.frombuffer(img, dtype='uint8') - img = cv2.imdecode(data, 1) - if self.to_rgb: - assert img.shape[2] == 3, 'invalid shape of image[%s]' % ( - img.shape) - img = img[:, :, ::-1] - - return img - - -class ResizeImage(object): - def __init__(self, resize_short=None): - self.resize_short = resize_short - - def __call__(self, img): - img_h, img_w = img.shape[:2] - percent = float(self.resize_short) / min(img_w, img_h) - w = int(round(img_w * percent)) - h = int(round(img_h * percent)) - return cv2.resize(img, (w, h)) - - -class CropImage(object): - def __init__(self, size): - if type(size) is int: - self.size = (size, size) - else: - self.size = size - - def __call__(self, img): - w, h = self.size - img_h, img_w = img.shape[:2] - w_start = (img_w - w) // 2 - h_start = (img_h - h) // 2 - - w_end = w_start + w - h_end = h_start + h - return img[h_start:h_end, w_start:w_end, :] - - -class NormalizeImage(object): - def __init__(self, scale=None, mean=None, std=None): - self.scale = np.float32(scale if scale is not None else 1.0 / 255.0) - mean = mean if mean is not None else [0.485, 0.456, 0.406] - std = std if std is not None else [0.229, 0.224, 0.225] - - shape = (1, 1, 3) - self.mean = np.array(mean).reshape(shape).astype('float32') - self.std = np.array(std).reshape(shape).astype('float32') - - def __call__(self, img): - return (img.astype('float32') * self.scale - self.mean) / self.std - - -class ToTensor(object): - def __init__(self): - pass - - def __call__(self, img): - img = img.transpose((2, 0, 1)) - return img -- GitLab