OpenVINO Model Server的服务化部署——step3(django服务构建)

为了能够将OpenVINO在服务器的推断结果可以被外部调用,需要构建相应的django服务构建。经过一段时间努力,成功搭建。
这里整理出的是一些基本的设置方法,细节比较多,不一定能够全面涵盖。
最终调用的方法,可以直接测试:
1、打开地址:http://81.68.242.86:8000/upload
2、选择并上传图片,完成后回显地址(需要消耗一定时间):
3、需要手工粘贴,而后显示处理后的结果。
比如上图就改为
“ http://81.68.242.86:8000/medias/111038jzs1zz11sx11snj6.jpg.result.jpg”,注意由upload改为medias
一、Django环境构建

1、在管理员权限下,直接可以使用pip进行安装。

    pip3 install django

如果网络正常,那么可以通过

    pip3 show django

查看django版本和django安装路径:

  

2、创建一个django project

在空文件夹下,使用以下命令创建django project

    django-admin.py startproject mysites

我们可以使用vscode来查看,其中较为关键的几成都项:

manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
urls.py ----- 负责把URL模式映射到应用程序。   

需要注意的是,这里的几个py都是行使管理权限的。

3、在mysites目录下创建应用(app)

    python3 manage.py startapp goApp

这新建一个goApp的实际项目,这个实际的项目是可以被启动的。

4、启动django项目

    python3 manage.py runserver 8080

    这样,我们的django就启动起来了。当我们访问http://127.0.0.1:8080/时,可以看到

    

    

如果以上工作全部能够成功,那么证明Django的下载安装是成功的,下面我们来具体理解其相关内容。

这里需要注意,如果需要外部IP访问,这样设置:python manage.py runserver 0.0.0.0:8000

如果再出现“Invalid HTTP_HOST header

解决方法:

  修改settings.py

ALLOWED_HOSTS = ['192.168.2.157','127.0.0.1']

  值为'*',可以使所有的网址都能访问Django项目了,失去了保护的作用,可以用于测试

ALLOWED_HOSTS = [ ' * ' ]

比如,这样运行

python3 manage.py runserver 0.0.0.0:8080

二、文件结构和各种作用

manage.py文件位于整个项目的最外层,是该项目的项目管理器,通过不指定命令运行,可以发现它具备以下功能。

比如,我们在上面使用过的:

创建应用:python3 manage.py startapp goApp
启动项目:python3 manage.py runserver 8080

wsgi.py:全称 webserver getway interface,即Web服务器的网关接口

urls.py:即路由配置

django下所有的页面都需要urls文件中配置一下,否则在访问的时候会找不到该文件。

settings.py:
配置文件,各种路径、国际化、debug、模版等均在此文件中配置。

2.3、简单示例

我了进一步加速对相关知识的理解,我们创建一个最为简单的程序,它能够实现的就是读取并显示当前系统OpenCV版本。我们需要改写以下文件:

url控制器 url.py

from  django.contrib  import  admin from  django.urls  import  path from goApp import views urlpatterns  =  [     path( 'admin/' , admin. site .urls),      path('index/',views.index), ]
视图 view.py
from  django.shortcuts  import  render from django.http import HttpResponseimport cv2def index(request):    return HttpResponse(cv2.__version__ )
以上代码中,标红的部分代表是新添加的,代码修改后,djangon会自动更新。运行结果如下:
需要注意到,goApp是我们新创建的app的名称,这里相当于在主目录中,引用我们的新编模块。
如果能够运行到这一步,那么证明OpenCV相关的引入工作已经没有问题。
三、算法融合,构建 django服务构建
我们从最简单的情况,一步一步来实现。(需要进一步总计当前的算法细节)
3.1 添加新路由,修改url.py
from django.contrib  import admin
from django.urls  import path,register_converter,re_path
from django.conf.urls  import url
from goApp  import views
from django.conf  import settings
from django.conf.urls.static  import static
from django.views.static  import serve
urlpatterns = [
    path( 'admin/', admin.site.urls),
    path( 'index/',views.index),
    path( 'upload/', views.upload),  # 上传图片
    path( 'process/',views.process),
    url( r '^process_detail/(.+ )/$',views.process_detail),
    url( r '^medias/( ?P<path> .* )$', serve, { 'document_root': '/root/mysites/goApp/upload/'}), 
]
其中,upload是显示界面;process_detail是单图片处理页面,medias是图片显示页面。
3.2 算法主要在goApp中实现
主要算法,实现在view.py中
from django.shortcuts  import render
from django.http  import HttpResponse
from django.conf  import settings
from django.shortcuts  import redirect, reverse
#from .models import User,Article
from datetime  import datetime
import argparse
import cv2
import datetime
import grpc
import numpy  as np
import os
import sys
import hashlib
from tensorflow  import make_tensor_proto, make_ndarray
from tensorflow_serving.apis  import predict_pb2
from tensorflow_serving.apis  import prediction_service_pb2_grpc
sys.path.append( '/root/mysites/goApp')
from client_utils  import print_statistics
classes_color_map = [
    ( 150,  150,  150),
    ( 58,  55,  169),
    ( 211,  51,  17),
    ( 157,  80,  44),
    ( 23,  95,  189),
    ( 210,  133,  34),
    ( 76,  226,  202),
    ( 101,  138,  127),
    ( 223,  91,  182),
    ( 80,  128,  113),
    ( 235,  155,  55),
    ( 44,  151,  243),
    ( 159,  80,  170),
    ( 239,  208,  44),
    ( 128,  50,  51),
    ( 82,  141,  193),
    ( 9,  107,  10),
    ( 223,  90,  142),
    ( 50,  248,  83),
    ( 178,  101,  130),
    ( 71,  30,  204)
]
def load_image(file_path):
    img = cv2.imread(file_path)   # BGR color format, shape HWC
    img = cv2.resize(img, ( 2048,  1024))
    img = img.transpose( 2, 0, 1).reshape( 1, 3, 1024, 2048)
     return img
def index(request):
     #users = User.objects.all()
     #article = Article.objects.all()
     return render(request, 'index.html')
def upload(request):
     if request.method ==  'GET':
         return render(request,  'upload.html')
     else:
        name = request.POST.get( 'name')
        pic = request.FILES.get( 'avator')
         #media_root = settings.MEDIA_ROOT # media
        media_root =  '/root/mysites/goApp'
        allow_upload = settings.ALLOW_UPLOAD  # ALLOW_UPLOAD
         #path = 'upload/{}_{}_{}/'.format(datetime.datetime.now().year,'{:02d}'.format(datetime.datetime.now().month), '{:02d}'.format(datetime.datetime.now().day))
        path =  'upload/'
        full_path = media_root +  '/' + path
         if  not os.path.exists(full_path):  # 判断路径是否存在
            os.makedirs(full_path)  # 创建此路径
         # 要不要改图片的名字 生成hash
         # 这块要不要判断图片类型 .jpg .png .jpeg
         # '/../../../myviews/setting.py'
        print(pic)
        print(full_path)
        print(full_path+pic.name)
         if pic.name.split( '.')[- 1]  not  in allow_upload:
              return HttpResponse( 'fail')
         with open(full_path +  '/' + pic.name,  'wb')  as f:
             for c  in pic.chunks():  # 相当于切片
                f.write(c)
         #User.objects.create(name=name, avator=path + pic.name)
         #return redirect('index.html')
         #return HttpResponse(full_path+pic.name)
         return process_detail(request,full_path+pic.name)
def process(request):
    options = [( 'grpc.max_receive_message_length',  100 *  1024 *  1024),( 'grpc.max_send_message_length',  100 *  1024 *  1024)]
    channel = grpc.insecure_channel( "{}:{}".format( 'localhost', 9000),options = options)
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    batch_size =  1
     # TODO
    files = os.listdir( '/root/mysites/goApp/images')
    print(files)
    imgs = np.zeros(( 0, 3, 1024, 2048), np.dtype( '<f'))
     for i  in files:
        img = load_image(os.path.join( '/root/mysites/goApp/images', i))
        imgs = np.append(imgs, img, axis= 0)   # contains all imported images
    iteration =  0
     for x  in range( 0, imgs.shape[ 0] - batch_size +  1, batch_size):
        iteration +=  1
        request = predict_pb2.PredictRequest()
        request.model_spec.name =  "semantic-segmentation-adas"
        img = imgs[x:(x + batch_size)]
         #print("\nRequest shape", img.shape)
        request.inputs[ "data"].CopyFrom(make_tensor_proto(img, shape=(img.shape)))
        start_time = datetime.datetime.now()
        result = stub.Predict(request,  10.0)     # result includes a dictionary with all model outputs print(img.shape) 
        output = make_ndarray(result.outputs[ "4455.1"])
         for y  in range( 0,img.shape[ 0]):   # iterate over responses from all images in the batch
            img_out = output[y,:,:,:]
            print( "image in batch item",y,  ", output shape",img_out.shape)
            img_out = img_out.transpose( 1, 2, 0)
            print( "saving result to",os.path.join( '/root/mysites/goApp/results',str(iteration)+ "_"+str(y)+ '.jpg'))
            out_h, out_w,_ = img_out.shape
             #print(out_h)
             #print(out_w)
             for batch, data  in enumerate(output):
                classes_map = np.zeros(shape=(out_h, out_w,  3), dtype=np.int)
                 for i  in range(out_h):
                     for j  in range(out_w):
                         if len(data[:, i, j]) ==  1:
                            pixel_class = int(data[:, i, j])
                         else:
                            pixel_class = np.argmax(data[:, i, j])
                        classes_map[i, j, :] = classes_color_map[min(pixel_class,  20)]
                output_str = os.path.join( '/root/mysites/goApp/results',str(iteration)+ "_"+str(batch)+ '.jpg')
                cv2.imwrite(output_str,classes_map)
     return HttpResponse(output_str)
def process_detail(request,param1):
    options = [( 'grpc.max_receive_message_length',  100 *  1024 *  1024),( 'grpc.max_send_message_length',  100 *  1024 *  1024)]
    channel = grpc.insecure_channel( "{}:{}".format( 'localhost', 9000),options = options)
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    batch_size =  1
     # TODO  filepath
    output_str= 'filepath'
    imgfile = os.path.join( '/root/mysites/goApp/images',param1)
    print(imgfile)
    img = load_image(imgfile)
    imgs = np.zeros(( 0, 3, 1024, 2048), np.dtype( '<f'))
    imgs = np.append(imgs, img, axis= 0)
    request = predict_pb2.PredictRequest()
    request.model_spec.name =  "semantic-segmentation-adas"
    print( "\nRequest shape", img.shape)
    img = imgs[ 0: 1]
    request.inputs[ "data"].CopyFrom(make_tensor_proto(img, shape=(img.shape)))  
    result = stub.Predict(request,  10.0)     # result includes a dictionary with all model outputs print(img.shape) 
    output = make_ndarray(result.outputs[ "4455.1"])
     for y  in range( 0,img.shape[ 0]):   # iterate over responses from all images in the batch
        img_out = output[y,:,:,:]
        print( "image in batch item",y,  ", output shape",img_out.shape)
        img_out = img_out.transpose( 1, 2, 0)
        print( "saving result to",os.path.join( '/root/mysites/goApp/results',param1+ '.result.jpg'))
        out_h, out_w,_ = img_out.shape
        print(out_h)
        print(out_w)
         for batch, data  in enumerate(output):
            classes_map = np.zeros(shape=(out_h, out_w,  3), dtype=np.int)
             for i  in range(out_h):
                 for j  in range(out_w):
                     if len(data[:, i, j]) ==  1:
                        pixel_class = int(data[:, i, j])
                     else:
                        pixel_class = np.argmax(data[:, i, j])
                    classes_map[i, j, :] = classes_color_map[min(pixel_class,  20)]
            output_str = os.path.join( '/root/mysites/goApp/results',param1+ '.result.jpg')
            cv2.imwrite(output_str,classes_map)
     return HttpResponse(output_str)
3.3 在template 中添加两段html用于界面显示
<! DOCTYPE  html >
< html  lang= "en" >
< head >
   < meta  charset= "UTF-8" >
   < title >OpenVINO Model Server的服务化部署(天空分割模型) </ title >
</ head >
< body >
< form  action= "/upload/"  method= "post"  enctype= "multipart/form-data" >
  {% csrf_token %}
  图片: < input  type= "file"  name= "avator" >< br >
   < input  type= "submit"  value= "提交" >
</ form >
</ body >
</ html >
前段编写的时候,细节很多,这里无法一一重复。
四、服务器标准重启命令
1 、启动docker  [root@VM - 0 - 13 - centos / ] # docker run -d -v /models:/models:ro -p 9000:9000 openvino/model_server:latest --model_path /models/model2 --model_name semantic-segmentation-adas --port 9000 --log_level DEBUG --shape auto 2 、启动django [root@VM - 0 - 13 - centos mysites] # python3 manage.py runserver 0.0.0.0:8000 3 、浏览器中输入:http : / / 81 . 68 . 242 . 86 : 8000 / index /  进行测试 也可以输入 http : / / 81 . 68 . 242 . 86 : 8000 / process_detail / sky20.jpg /  进行带参数调试

附件列表

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    jsxyhelu2015

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值