OpenVINO Model Server的服務化部署——step3(django服務構建) Invalid HTTP_HOST header

爲了能夠將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("\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/ 進行帶參數調試





附件列表

     

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章