zoukankan      html  css  js  c++  java
  • OpenVINO Model Server的服务化部署——step3(django服务构建)

    基于OpenVINO的“semantic-segmentation-adas”模型,能够较为精确的分割出天空;使用OpenCV的seamlessClone等函数,实现天空的无缝替换;基于Django实现网络化部署。三者结合,实现并部署“天空替换”模型。
    目前服务已经上线:打开地址:http://81.68.242.86:8000/upload 就可以体验,手机端和PC端都可以。虽然界面比较简陋,速度也比较慢,但是基本可用。总的来说,openvino自带的这个模型本来是用于道路分割的,不是专用的,能够出一定效果,但是有些时候不精确;再加上后期处理,还有粗糙的地方。但本文最为重要的是证明工具链的可行,探索一条道路,这个是有价值的。

    OpenVINO Model Server的服务化部署——step1(OpenVINO™ Model Server Quickstart)
    https://www.cnblogs.com/jsxyhelu/p/13796161.html

    OpenVINO Model Server的服务化部署——step2(天空分割模型)
    https://www.cnblogs.com/jsxyhelu/p/13829051.html

    OpenVINO Model Server的服务化部署——step3(django服务构建) 
    https://www.cnblogs.com/jsxyhelu/p/13878335.html

    OpenVINO Model Server的服务化部署——step4(实现天空替换)
    https://www.cnblogs.com/jsxyhelu/p/13894565.html

    ===================================================================================================

    为了能够将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 HttpResponse
    import cv2

    def 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 = [
        (150150150),
        (5855169),
        (2115117),
        (1578044),
        (2395189),
        (21013334),
        (76226202),
        (101138127),
        (22391182),
        (80128113),
        (23515555),
        (44151243),
        (15980170),
        (23920844),
        (1285051),
        (82141193),
        (910710),
        (22390142),
        (5024883),
        (178101130),
        (7130204)
    ]

    def load_image(file_path):
        img = cv2.imread(file_path)  # BGR color format, shape HWC
        img = cv2.resize(img, (20481024))
        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('.')[-1not 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(" Request 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(" Request 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/ 进行带参数调试
     





    附件列表

  • 相关阅读:
    js事件分类
    过3s弹出广告条,点叉号关闭
    js进阶
    js入门
    html
    R Markdown + Infinite Moon Reader + 编辑实时更新
    png转ico+windows图标+GIMP
    微生物+计算细胞倍增时间
    使用Mathjax网页插入公式
    Firefox+zoom+全局缩放比例
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/13878335.html
Copyright © 2011-2022 走看看