From f1d51561ae21e8b44b46d9220988f1a8282cb8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E5=8D=9A=E5=9F=B9?= <58476312+zbp-xxxp@users.noreply.github.com> Date: Fri, 19 Mar 2021 10:15:38 +0800 Subject: [PATCH] =?UTF-8?q?Upload=20New=20Module=E2=80=94=E2=80=94marine?= =?UTF-8?q?=5Fbiometrics=20(#1325)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add marine_biometrics --- .../Image_Classification_MarineBiometrics.png | Bin 0 -> 9445 bytes .../marine_biometrics/README.md | 69 ++++++++ .../marine_biometrics/__init__.py | 1 + .../marine_biometrics/module.py | 147 ++++++++++++++++++ .../marine_biometrics/serving_client_demo.py | 25 +++ 5 files changed, 242 insertions(+) create mode 100644 docs/imgs/Readme_Related/Image_Classification_MarineBiometrics.png create mode 100644 modules/thirdparty/image/classification/marine_biometrics/README.md create mode 100644 modules/thirdparty/image/classification/marine_biometrics/__init__.py create mode 100644 modules/thirdparty/image/classification/marine_biometrics/module.py create mode 100644 modules/thirdparty/image/classification/marine_biometrics/serving_client_demo.py diff --git a/docs/imgs/Readme_Related/Image_Classification_MarineBiometrics.png b/docs/imgs/Readme_Related/Image_Classification_MarineBiometrics.png new file mode 100644 index 0000000000000000000000000000000000000000..0076ea232298f58055664ddfaa06c76a1d205fae GIT binary patch literal 9445 zcmVpdx0*s7;h~vkIUl1uzLkWl8|Bon1tz z;!Yqt@X#(-5twdk(AYd`SOgY ztR8qYq^D7!Q&i}L0{(&KJ!&UfYZdAuDJoyrZ|<;qY-*-pq60uoK#Y_Cz|bT}09Z)- z@fo&t7cKQ@Yh25zp13xTI}X4ZGp{igA_8|Z?t*X#s)D460Px%diKI)&2ccN1q^P(O zfB+(>2`Y<-+G%uRVTd~b1py=h*;=lE1DX;^brnz?>ZlL`uGA#?(L~AWKXexr5g}={ zifBseq`NCLvHkNb9XH-C$_EhpW{z9si*zMNL>F zD|A8U5RsV6DMvp+f&?9!K%zQT#UCp}I96+_2{4bBN{~nTA)IIHRaNtY~KC4F>L|jRlXg@|YmM{iuhac|pL|sLKfg#Tx~?-PBCWc*7Fm<9^#q`yr^0qP z01vaL$Us}$t_mD=iK78Pcy)!k7(s{g_>Gfrz?an{0)wlnhDiZPrj=HTn&bJ}l%fzQ z34oMz^Y06#zO%4&spH>9UScpxV*uxo)6^)Yx zNlz-kag-mGM@I1RcUL&;SpPD^iUwT}x~Q!VQExz`c@#gc(CKa`#24^LBs_chgbB-hx`l8yFm$x{F)Zo{fQbXBi6Wv*W+tMfQ=*pyo*?d1iyeSiJR9u^ zY!#mafWTbrl8873l0sX}5E1F-Q)j~dHryAZ?5FFH*&%%@1ko|-A{Mc7ayp68T6<>R4Nu+76{|$KOCve!StZTflZZ$T|3FWmJ6Qs7KWqt3 zeQ^?)uy8fG0>GvMM|>{?Fia2;QIZRSLsF4i4M6lz2multK+${BrB~AHTuDkvB(rn? zlC3QU07$k+a^oNbhg5-2`bW*5dhq7a@Ar>cI;`~9Q}6%LV_0zpKctWh_Y8ugE&5ZH zMZiBSkJ+@%kJ{tEO+C;+N%Q_S)&&4*E26D=Z$E6dELbuD;LfH6R=sL=2QvVLIh&Iw zQTIZ(0LTP@Q~}_2V*OeCIYTZ3((@GC66^9WBPE}5C1!MKYRFBgai~Yw5ReWss%vA_3X*? zms)blq8;EW;$%t*z&sasGb4bMvWT!#0Q=oeREv2^$(<=FOL6ys`M5$OyyW;4iMnR= z+pkC?-GN-S`JWA`hqeL$Bo_d6F$i4Zn(Gz2mbhkR1Y}GMTtI!GBAV@s>v+o*O&=}V zdY-!MS31*qd0XZ(U(N*Z)o=gK=UHY;nsR@ZbN2IX?m9>5x=uD5IPQq#!Y+w+y}{|; z;1fxX3a6(PyAL>zlP(5PB!v?s>52qEVXb!y!@FuefTMqt7NYX#rmaTm!S#wiaHEJs zj9}4IcvRdOs)z1IC#fnaX_q@unWk}?rt~J%WhT z)hMmmrLr2kh|{5Y>IusS7Mr91?tE0yo+PNXz)-?{fG)kX0qv#rzJ!EiNRVe^d}2`3DO-OQI)4PJgV)eqDYofN-5L( zZw`mU+1GFPyS?8W0BnsSGS71@#f&72)x%-`esmT2Uw3awmKWF8*UzS#XV=%)ozE|x zzqlAKfwm@=*wm*G(*v5{m2}co(;`!kn%>YV0F28YNkWvQMh1fdi^tcbj{vY=P`)o( zAUUWgfwllFeq1zon+5<~C4jTSX`0Tzy_=>f{rx|5wZ4A;-rZl{Pa^W%L_~BRhiNPm zNzbPJ{=QCgDf6?h{%M|zU7cTEUtfIj=GCiLxaZZ??)I;L(RE#Bmy$+w^J8PwJOLB{ zgwVM$(z)wFm|)=&3yTF$m-eP8Y3Vi<;56+pE* z&+|Br08&aKCt_VxKQ>^kNA(n`#F|IvLXoWT)DTv$PIBZ%p`s$9fJ}$!_+&)lLT7fx z0E`JZTFfK>dUQFZ83JJ3CX#ZPt=69&b^yxV-ObGne*g8|-QCZ>`uYm^_5Fe5=T%i? zo^2e*J63n!2-*30VKuw7!{>v(?0M+;`R1bU`+Mn2DZ9J-OUQg*bN8-%`K+7A12)Av zO`39sCc4kzQHLB=keD)@?2?B}kVGNf#w;RwHd8b>&j#gAL-jFI>C=4E$BLVoh_xuO zx*KY(X8ZYIwbtG4ez&Xl_v1J=E?Oyod7_Vw3~;Ye_;Dk0g#XYh(&ZD zXr2kQ)MT>&*vxdt^;d8A`~AhY-(8R6t8cy|`Ng4_`SrAScfcS5S`zE25NyrplvIVr z1XB?&k|s$)rz91#J*QF%udklHJZC?!@B7r})XkkhB(!ZJg>?r!GpQZ3?f;!FwhSpyMIgcl*-9`u@lm#7d)JX0 z@eXLYcT2!80T_Hk^4!ekI=p{7-`?iG`)&9BJ^uD@JCUy2oLyX6rJGGKcdz0MpB=8x^?V~a1-p@wP?%H^(NiS= zsxX+)hRP!^VbN0pDv}59vLMez@D_BBk0OpASEgxFP3CpC-`~A``|Y>yF24Ty{{BAS z-I3gF>M#tYhMN{j%G}(1Hg~I2?y?B1+BlA-)G5OY{IW4EM3f#3w#FG8w8X02l z#U-WOOINK9h3@m=xBv9+?c4MZ|8u&#d-2`7bo1StZ^y37zT52%e)jq0X0zE(x6;XU zICNdtq4#Mrcb|*a@h~2ydSUc~W45vbYW2NzB&W@#S$&riH$#1PbvQrUym>W>jD6Om z^a@C?+0A-$YF211MTMd=%rFBLIptlM5o?P+Iq578xS5-XWO)=aZTW!Yk_q`ol_N8$ zK+Y+ptVwtK_q+Rh`}*te-hX#_IOLo!FE2#oZ14NSq0}-A!x8(>^PF-DWEc}3EToE> zyVYtAtF9IOKx+nm$EK!8;uln+kVchFD+O#)dLkeu=v=gLJC|B3-u}M6eS7(j zzwM^!i{1U%`T4K&*{#-tDCaT{NMgHkKVwqtkN~T5oo4gu-gjFO^?7Hkdz+oUt7^o- zI{;(16_IyNq+G8r@ZuR>T=CgO9s0iSr=BIbx;SBTG5FR+1mkoV_Xq6vrPOY$UDp-W zO+Sd_aNGnMF`$h@M69l2$VV^*JhqoVyaconh`XzS&O@1}X&UeDZfe=&W zrSDafE@_{UK}u3ol;TdaQc{foZ8yu5tT4XS$GjhB}f{eA8G zezV#3ea{2uGS^a6WE#g>E!R@3nHMvUG8@TKs{p7T@l+m}wP6_Eym_N9UtB-CF4xbx zE&~WQA{y8fP0Do|=Xv(IjN@V2@5jTKXno&zK-YDn^JuwFZ0Evg<#YGQ;;sraC!A!_ zBuQ9+MMJH39$__VYq`rsNu)A~*=B#|?&srOKkwgcrFPwGv0Cc$%xm>c8qfQJR9q(S zrmA|o@4MM-%vPbU(=<)e{B4V}&pf!nrk}8>zS%JfpXJeri^IFs3X)L;*b#o?=6b=fSlP8d(5pk&ILJ?`P zz~%#bl59UTL$8%miil)U5l=}|(zCPkoV$L!>-+u^-84-Xc{sng7^=7U+RaF61)i-axxW2x=?|J~^IEsj#={yI`15J92 z4@I$R(=^TFp_JMu9fqOr`|$gYnepo-67ivop%Zif6xrP&g+TDM>j-m%+YJg}TE$)a zc_O*32H=&=0MdL@N;xmCBClBc^Zpn40>EFM55q9Lx;>D@e0O+vcU9)gdHU^mUI2ah z(xBVk)w*sfbd@=|TQ%`{o;y&7i_20?90 zpdwbMoMdC2TMM(K;7DpKDiAS91m6)w!5@8nNUCWYS}^ z2U}b$*plS_(U1mLd6>sLapC50)1<@DCDqO*0GF2+!!Uf=U8S72_V)Jnc03$*`~Cg> zu9Qk@Db;uT+~ow6Qa0h5iBZ(alrvfG?(T<6t!AYb)s%BL48!Kx^|R~i+IM~5^?l#> zz4blmkvC7;5fz5!6@jXppP!dnOyO=hdXT;%2XR-&nP04t&(I?QwV z_I7x;msxuDSCFbwU41kv)p=JPkg@M;t-s%U?()>Br><~LxxW!jNvG}h`uh6v=U>?C z7k0KSeJ6c~E+ti`Kq~-OH@HIS@RUerH3+)1&80ruUYrB)tVxq~dD2E3t7_nb<9Nky zcJ~l3hf}rXqDbsg`v8T|_@b43#cwErxs?0ey}MuS59Xfk?n*7ecGh7yJ3Bu!G4sPX zj^nuB@5XT~HIr=k8&<8-;O-NN&_}6l@3LyhsMS^V{OtV2^B2!Q|NQFe>bA>C698|q zb&nl6zT`uY4D=|A-s$^p7zPnBfxD?DQQ<0td!+4-cXCdtY6-!_5$iSw1`GJB4b`P@+Ig(5|TtkAz~seXJQ6mUCK#iJ|dnLx$?yk0g%ld5g(Ta8b?F| z0Z0B=>{r#3aXgLpQD;rlRBAEzTFT*Y5RtPUec#`ed6PDxGSBmFzuWKjH@EWc{kw7O z=XsuIjN?dz#RycKN-fho-QV92Lw@<<<+Cqe^?mpCe3+)mbANex`Pol?a(#V$c5$)Y zo=v*!s0%Q@cxtVA`Zz2sKvH!xH+Qrgji5jAp|T*)Di;4pCL*b2{uY%~sU$%OM~H+P z0caK{G+4x>?sng!2=={>&VS5v;e4M;%J~hTz-4!tG}m3;-;H0DG?x7LZeLIJfbA`H zt}_8mPWO@_qHnvhoA>Xv$aVMgzy8JNZ@w5lyQ)@izP_L5+0L)Z#ku|LXZ7l8y1vTi zXS*7s3=yG*+uZyTIE5|Az?U?oEMkHrVss&esI^wITag99yT!;w*7qvcWfcJyQBh&! z7BEEV!)Z{WB5VdiMEbrzJKOGdtY+1W9lD__a{-{UPt#Pr_I>{>_awi$l~Rkj9)R2> zk~>c0VTbgw|4XD===HS@`l7zL`kiie_xG;pyR+?g z>8o+u9j;Jjx#c__rmryjxqS9-|K=xOekpI>r+bir~t0>m58`@B2rU#o77YU zUeC4wsQD-bE&z1!2$2w=k#rY@h@cv4wY$4{w-XX-X~wqi*tIyWh|F?|n@#qieDtQ- z4ep+GomUl1^C{x?w9NA?A~_{bX&45xDk@#-INgiLG)?0;&Kq^oYIXNv7;bNGYpDRH zX{xn$XT7_B@#f9T7ca`?C4jQYDW$;Wo%8@aHZMN(RX^Z;=A)E1JKZ(?VO6pVG}H#>AGl!yU$=G2Dy8tkc7|EcsK5LrBtCOku9WGJ;=hZ zha8f=%9qS|sCtYhB1Cfz0X#@m_#_D$<}$)^r4|5P-zQb?>15ya!!W#`{ct$U`+Y5C zx8IYzxw+ZxcH5tP_T`sf4uAO z0XQ<~!NK>nlp>Nz``xUn**<^Kb@}ei^)yY&K54rB=G)ut-rwGSeLMZ(cDlK_`40H( zi=S=&&0oFz)vxf=*YCP+y1YJUnngTo2SrLiN5HKBh;2S?Q*UHKt+pqx`?>cDfvT7> zw-GgZoz19txSCFex)a5#`ug}L3`-`(BcP4D0R?svbty?J|eb@j7f|N0j{|G9qo*~^zN$IDAI zFR@ohL{%fxF!V!Yq5M&SBa&vZK2FBH@B5T8s5$5ON|wL?@sh7!KVIj1Wu(s~aaHZa zNp{uf9M{Q0;ZOT%r}3h>fJL%)IT`x*=}bfq&o5Nd=bExvHH*zZErLI_|pw! ztK#Zzo{&f;fbK%5F>i)mq-qusNy*KNd1Ez!OeNjolpg@ceDv_PBg|`N$xTI5N+NPt z#{mO0t=8Jpk~F10LFIbNhe(_wIgI=K1yO*T4FkFMsmI7oWYp z=(_&vX*TnV^Q*4!Co<;<7cHA<0(z^jkoRcRY$dXmyMxGq^mQuPQDTh?w`v`%*3qh&0iKfP z+~u5-X8_3+z?>2m{>xIqQ9CpNZVqt#<53^7g~E<=kl^lCO09-%igBekAKZ(PjBFh5 zI+BJ{T8giBRjfLKG%dNqe}kz(rejxUBNmn~sZo?|+5|sSp6~1X^9>28fPQKI&Dfhi%6`4=uJCi zA*_U-LOtPKhMkRFhmje7Sk43jK(*twr^vevzKE6#?o6b_j;7P*Gp2}}3(47y^y&&} zZRiOs`*;FVMNgw&e2=nM;wSwX(|U9e^Bot?iI=0Ewsl z2s=CUliL&VTc6g^G+@k}sH@W;q6@zc z6%EXxDbe|94VhD0;EPUKWtp%1@?%-?r;8)Ow8zL6Hwe)7 z=hIWxa_oW?J6R8T;KBXL%EKe{Ja&Zv!c`o=>2!@8tM5%=%~D;`$;vFEpjZ&rB2uS) zqKkXlgytx7xozqmj4Ap600enSL_t);@vTU8FAO`i@)Dc?E^P)7^5LPJn6T`>aSS-^ z^%4NNt~~jb?V|x;K_ywkdR7`Nb{d&Gl}A%1B2+mcKzala>DG^@y)y0C##n71+zs+C zw2&V@JK>nc`azK)o0R^Pbw55|&)5`e22xuUD#d1*_K5^r*qWgFPV;**~;> zcB>j<2h_3`7>{Oh1tFIFQU_33fhNEyxR7N}S=cK&LyBSpL*xmyJx2?t#ABT+7p}F# zfRDOx|Dwu~DSxEwj`6;y&-*G`^8-tc=<(y*tNH(!w;mzar5O#Ef3U3c`DArxUR%?RtY-&NphyiW0cVNlH>qBm5=TX zTeY`Nz4~#0>d#Uhp5O4{S#D=OKJ3QRX!)aZ(gO?TUZEHQkMR_6L^lm8KIR)frmfa@ z;@xZ~Te+^GrWK5Nf;MHPL25()_4Lr{GZP$we$}d_qSZl6tNY!mzw1M*)~DhA|MLAM zg9oJo=&BwM#9E{y1L)`g#tt|l>~<=L18qNO%uy~Gi}$zIDH{o2Qho898jBE&7$Old zLa-5zX)+SXTSO`qK%8^C7PYW(Irmu5Up_fSxaWMlUayY_;} zV!#u4sD<2>xk&`@EQ7khVCv$f7w7V-&x+4Eb%l!vpE8ro+NnI>)AAov*25vEuP7jZf~ON_o}O&AFkGi{ zOl;OJ z*^nH^QB)3xy_>n2iny88+Jdp + +## 输出结果 +~~~ +[{'category_id': 16, 'category': 'Plectroglyphidodon_dickii', 'score': 0.9932127}] +~~~ + +# 贡献者 +郑博培、彭兆帅 + +# 依赖 +paddlepaddle >= 2.0.0 + +paddlehub >= 2.0.0 diff --git a/modules/thirdparty/image/classification/marine_biometrics/__init__.py b/modules/thirdparty/image/classification/marine_biometrics/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/modules/thirdparty/image/classification/marine_biometrics/__init__.py @@ -0,0 +1 @@ + diff --git a/modules/thirdparty/image/classification/marine_biometrics/module.py b/modules/thirdparty/image/classification/marine_biometrics/module.py new file mode 100644 index 00000000..f20cf1ae --- /dev/null +++ b/modules/thirdparty/image/classification/marine_biometrics/module.py @@ -0,0 +1,147 @@ +from __future__ import absolute_import +from __future__ import division + +import os +import cv2 +import argparse +import base64 +import paddlex as pdx + +import numpy as np +import paddlehub as hub +from paddlehub.module.module import moduleinfo, runnable, serving + + +def base64_to_cv2(b64str): + data = base64.b64decode(b64str.encode('utf8')) + data = np.fromstring(data, np.uint8) + data = cv2.imdecode(data, cv2.IMREAD_COLOR) + return data + + +def cv2_to_base64(image): + # return base64.b64encode(image) + data = cv2.imencode('.jpg', image)[1] + return base64.b64encode(data.tostring()).decode('utf8') + + +def read_images(paths): + images = [] + for path in paths: + images.append(cv2.imread(path)) + return images + + +@moduleinfo( + name='marine_biometrics', + type='cv/classification', + author='郑博培、彭兆帅', + author_email='2733821739@qq.com, 1084667371@qq.com', + summary='The model uses convolution neural network to tell you the key to identify marine fish, so that anyone can call out the names of the creatures.', + version='1.0.0') +class MODULE(hub.Module): + def _initialize(self, **kwargs): + self.default_pretrained_model_path = os.path.join( + self.directory, 'assets') + self.model = pdx.deploy.Predictor(self.default_pretrained_model_path, + **kwargs) + + def predict(self, + images=None, + paths=None, + data=None, + batch_size=1, + use_gpu=False, + **kwargs): + + all_data = images if images is not None else read_images(paths) + total_num = len(all_data) + loop_num = int(np.ceil(total_num / batch_size)) + + res = [] + for iter_id in range(loop_num): + batch_data = list() + handle_id = iter_id * batch_size + for image_id in range(batch_size): + try: + batch_data.append(all_data[handle_id + image_id]) + except IndexError: + break + out = self.model.batch_predict(batch_data, **kwargs) + res.extend(out) + return res + + @serving + def serving_method(self, images, **kwargs): + """ + Run as a service. + """ + images_decode = [base64_to_cv2(image) for image in images] + results = self.predict(images_decode, **kwargs) + res = [] + for result in results: + if isinstance(result, dict): + # result_new = dict() + for key, value in result.items(): + if isinstance(value, np.ndarray): + result[key] = cv2_to_base64(value) + elif isinstance(value, np.generic): + result[key] = np.asscalar(value) + + elif isinstance(result, list): + for index in range(len(result)): + for key, value in result[index].items(): + if isinstance(value, np.ndarray): + result[index][key] = cv2_to_base64(value) + elif isinstance(value, np.generic): + result[index][key] = np.asscalar(value) + else: + raise RuntimeError('The result cannot be used in serving.') + res.append(result) + return res + + @runnable + def run_cmd(self, argvs): + """ + Run as a command. + """ + self.parser = argparse.ArgumentParser( + description="Run the {} module.".format(self.name), + prog='hub run {}'.format(self.name), + usage='%(prog)s', + add_help=True) + self.arg_input_group = self.parser.add_argument_group( + title="Input options", description="Input data. Required") + self.arg_config_group = self.parser.add_argument_group( + title="Config options", + description= + "Run configuration for controlling module behavior, not required.") + self.add_module_config_arg() + self.add_module_input_arg() + args = self.parser.parse_args(argvs) + results = self.predict( + paths=[args.input_path], + use_gpu=args.use_gpu) + return results + + def add_module_config_arg(self): + """ + Add the command config options. + """ + self.arg_config_group.add_argument( + '--use_gpu', + type=bool, + default=False, + help="whether use GPU or not") + + def add_module_input_arg(self): + """ + Add the command input options. + """ + self.arg_input_group.add_argument( + '--input_path', type=str, help="path to image.") + +if __name__ == '__main__': + module = MODULE(directory='./new_model') + images = [cv2.imread('./cat.jpg'), cv2.imread('./cat.jpg'), cv2.imread('./cat.jpg')] + res = module.predict(images=images) diff --git a/modules/thirdparty/image/classification/marine_biometrics/serving_client_demo.py b/modules/thirdparty/image/classification/marine_biometrics/serving_client_demo.py new file mode 100644 index 00000000..3acaa6c9 --- /dev/null +++ b/modules/thirdparty/image/classification/marine_biometrics/serving_client_demo.py @@ -0,0 +1,25 @@ +# coding: utf8 +import requests +import json +import cv2 +import base64 + + +def cv2_to_base64(image): + data = cv2.imencode('.jpg', image)[1] + return base64.b64encode(data.tostring()).decode('utf8') + + +if __name__ == '__main__': + # 获取图片的base64编码格式 + img1 = cv2_to_base64(cv2.imread("IMAGE_PATH1")) + img2 = cv2_to_base64(cv2.imread("IMAGE_PATH2")) + data = {'images': [img1, img2]} + # 指定content-type + headers = {"Content-type": "application/json"} + # 发送HTTP请求 + url = "http://127.0.0.1:8866/predict/MarineBiometrics" + r = requests.post(url=url, headers=headers, data=json.dumps(data)) + + # 打印预测结果 + print(r.json()["results"]) -- GitLab