当前位置: 首页 > 后端技术 > Python

SpringBoot部署深度学习模型(Java-Pytorch)

时间:2023-03-26 11:01:29 Python

为什么要用Java框架SpringBoot部署深度学习模型前面训练了一些深度学习模型,在模型部署中遇到了一些问题。首先,现有的很多业务都是用java实现的,比如预算控制、用户配额等,图像识别和这些系统直接交互会造成一定的代码入侵,多系统会冗余,所以考虑使用SpringBoot将图片检测服务打包,独立使用在现场,搭建一个服务,对外提供图片检测的功能。其次,Spring框架在服务管理和负载方面有成熟的解决方案,也便于日后的扩展和升级。本文记录使用Java部署深度学习模型的过程。请注意,模型的核心仍然运行在Pytorch框架上,它只是一个提供外围访问或域内调用的API。完整的Java项目可以直接参考:https://github.com/anylots/detectionpython模型项目的DetectNet:https://github.com/anylots/DetectNet,提供http接口;基于Yet-Another-EfficientDet-Pytorch框架组成应用架构在管理时是SpringBoot+Thymeleaf+Bootstrap的组合,在运行时是Pytorch+Flask的组合。设想的系统架构:Java管理的第一步是使用接收到的imageLink或者上传的文件调用图像识别服务,返回的数据是图像的BASE64编码。第二步是组装Spring的ModelAndView对象。第三步,返回ModelAndView对象,Thymeleaf引擎会将识别结果返回给前端。`@ControllerpublicclassImageDetectController{/***imageDetect服务*/@AutowiredprivateImageDetectServiceimageDetectService;/***检测**@returndetect.html*/@RequestMapping(value="/detect",method=RequestMethod.GET)publicStringdetect(){return"detect";}/***检测出**@paramimageLink*@returndetectOut.html*/@RequestMapping(value="/detectImage",method=RequestMethod.POST)publicModelAndViewdetectOut(StringimageLink){//步骤1.检测图片由imageUrlStringdetectFrame=imageDetectService.detect(imageLink);//步骤2.组装modelAndViewModelAndViewmodelAndView=newModelAndView();modelAndView.setViewName("detectOut");modelAndView.addObject("img",detectFrame);//step3.返回检测结果页面returnmodelAndView;}`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26*27*28*29*30*31*32*33*34*35*36*37*38*39*40springboot项目结构Python运行时部分使用flask提供http接口这里先根据传入的url获取图片,然后调用服务层获取识别出的图片信息,最后通过http接口返回给springboot管理(现在不懂python的rpc框架,以后再研究)图片数据格式参考旷视的图片识别接口,采用BASE64编码传输图片信息,`@app.route('/detect/imageDetect',methods=['post'])defprocess():#step1.接收图片urlimage_link=request.form.get("imageLink")ifnotimage_link.strip():return"error"#检查请求response=req.get(image_link)image=Image.open(BytesIO(response.content))#步骤2.检测图像image_array=service.detect(image)#步骤3.将image_array转换为byte_arrayimg=Image.fromarray(image_array,'RGB')img_byte_array=io.BytesIO()img.save(img_byte_array,format='JPEG')#步骤4.将图像信息返回到页面config['TEMPLATES_AUTO_RELOAD']=Trueapp.run(debug=False,port=8081)`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26*27*28Pytorch部署EfficientDet。这里使用一个service层来封装EfficientDet模型,transforms、CLASS分类信息、recognizers定义为全局变量,避免每次请求都初始化这些。信息,减少耗时`importrandomimporttimeimportcv2asopencvimportnumpyasnpimporttorchvisionfromPILimportImagefromdetectorimport*#imagedetector,returnoutputofdetectiondatadetector=Detector()#datatransformstransforms=torchvision.transforms.Compose([torchvision.transforms.ToTensor()])#setofnamesandcolorsnames=cfg.COCO_CLASS#drawidentificationframebasedondetectiondataclassImgDetectService:#returnaimagewithboxesbasedondetectiondatadefdetect(self,img):start_time=time.time()#将图像转换为数组frame=np.array(img)#转换为cv格式frames=frame[:,:,::-1]#转换为模型格式image=Image.fromarray(frames,'RGB')width,high=image.sizex_w=宽度/416y_h=高/416normal_img=image.resize((416,416))img_data=transforms(normal_img)img_data=torch.FloatTensor(img_data).view(-1,3,416,416).to(cfg.DEVICE)#检测图像y=detector(img_data,0.7,cfg.ANCHORS_GROUP)[0]tl=round(0.002*(width+high)/2)+1#线宽tf=1foriiny:#在图像img上绘制一个边界框x1=int((i[0])*x_w)y1=int((i[1])*y_h)x2=int((i[2])*x_w)y2=int((i[3])*y_h)cls=i[5]color=[random.randint(0,255)for_inrange(3)]opencv.rectangle(frame,(x1,y1),(x2,y2),color,thickness=2)#绘制标签label=names[int(cls)]label_size=opencv.getTextSize(label,0,fontScale=tl/3,thickness=tf)[0]opencv.rectangle(frame,(x1,y1),(x1+label_size[0],y1-label_size[1]-3),颜色,-1)opencv.putText(frame,label,(x1,y1-8),0,tl/3,[225,255,255],thickness=tf,lineType=opencv.LINE_AA)end_time=time.time()print(end_time-start_time)returnframe`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26*27*28*29*30*31*32*33*34*35*36*37*38*39*40*41*42*43*44*45*46*47*48*49*50*51*52*53*54*55*56*57*58*59*60*61*62*63*64*65*66*67*68*69*70效果演示:分别启动detection和DetectNet项目,填写需要识别的图片url或者上传图片文件,点击提交识别结果请求。GTX1050Ti),管理时间需要60ms(i584008GRAM),耗时较长。这个估计跟http接口有关。后续会研究python的rpc调用和数据压缩传输。模型权重:链接:https://pan.baidu.com/s/1SyIa...提取码:3pif说明:本文在细节和逻辑上还有很多不完善的地方,图像识别服务的搭建和部署会继续研究,再继续更新原文:https://blog.csdn.net/m0_4650...