1. 程式人生 > 實用技巧 >OpenVINO Model Server的服務化部署——step3(django服務構建)

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

為了能夠將OpenVINO在伺服器的推斷結果可以被外部呼叫,需要構建相應的django服務構建。經過一段時間努力,成功搭建。這裡整理出的是一些基本的設定方法,細節比較多,不一定能夠全面涵蓋。最終呼叫的方法,可以直接測試:1、開啟地址:http://81.68.242.86:8000/upload2、選擇並上傳圖片,完成後回顯地址(需要消耗一定時間):
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 runserver8080

    這樣,我們的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 runserver0.0.0.0:8080

二、檔案結構和各種作用

manage.py檔案位於整個專案的最外層,是該專案的專案管理器,通過不指定命令執行,可以發現它具備以下功能。

比如,我們在上面使用過的:

建立應用:python3 manage.py startapp goApp
啟動專案:python3 manage.py runserver8080

wsgi.py:全稱webserver getway interface,即Web伺服器的閘道器介面

urls.py:即路由配置

django下所有的頁面都需要urls檔案中配置一下,否則在訪問的時候會找不到該檔案。

settings.py:
配置檔案,各種路徑、國際化、debug、模版等均在此檔案中配置。

2.3、簡單示例

我了進一步加速對相關知識的理解,我們建立一個最為簡單的程式,它能夠實現的就是讀取並顯示當前系統OpenCV版本。我們需要改寫以下檔案:

url控制器 url.py

fromdjango.contribimportadmin
fromdjango.urlsimportpath
fromgoAppimportviews

urlpatterns=[
path('admin/', admin.site.urls),
path('index/',views.index),
]
檢視 view.pyfromdjango.shortcutsimportrender
fromdjango.httpimportHttpResponse
importcv2

defindex(request):
returnHttpResponse(cv2.__version__)

以上程式碼中,標紅的部分代表是新新增的,程式碼修改後,djangon會自動更新。執行結果如下:需要注意到,goApp是我們新建立的app的名稱,這裡相當於在主目錄中,引用我們的新編模組。如果能夠執行到這一步,那麼證明OpenCV相關的引入工作已經沒有問題。
三、演算法融合,構建django服務構建我們從最簡單的情況,一步一步來實現。(需要進一步總計當前的演算法細節)3.1 新增新路由,修改url.pyfromdjango.contribimportadminfromdjango.urlsimportpath,register_converter,re_pathfromdjango.conf.urlsimporturlfromgoAppimportviewsfromdjango.confimportsettingsfromdjango.conf.urls.staticimportstaticfromdjango.views.staticimportserve

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中fromdjango.shortcutsimportrenderfromdjango.httpimportHttpResponsefromdjango.confimportsettingsfromdjango.shortcutsimportredirect,reverse#from.modelsimportUser,Articlefromdatetimeimportdatetime
importargparseimportcv2importdatetime
importgrpcimportnumpyasnpimportosimportsysimporthashlib
fromtensorflowimportmake_tensor_proto,make_ndarrayfromtensorflow_serving.apisimportpredict_pb2fromtensorflow_serving.apisimportprediction_service_pb2_grpcsys.path.append('/root/mysites/goApp')fromclient_utilsimportprint_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)]
defload_image(file_path):img=cv2.imread(file_path)#BGRcolorformat,shapeHWCimg=cv2.resize(img,(2048,1024))img=img.transpose(2,0,1).reshape(1,3,1024,2048)returnimg
defindex(request):#users=User.objects.all()#article=Article.objects.all()returnrender(request,'index.html')
defupload(request):ifrequest.method=='GET':returnrender(request,'upload.html')else:name=request.POST.get('name')pic=request.FILES.get('avator')#media_root=settings.MEDIA_ROOT#mediamedia_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+'/'+pathifnotos.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)ifpic.name.split('.')[-1]notinallow_upload:returnHttpResponse('fail')withopen(full_path+'/'+pic.name,'wb')asf:forcinpic.chunks():#相當於切片f.write(c)#User.objects.create(name=name,avator=path+pic.name)#returnredirect('index.html')#returnHttpResponse(full_path+pic.name)returnprocess_detail(request,full_path+pic.name)
defprocess(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#TODOfiles=os.listdir('/root/mysites/goApp/images')print(files)imgs=np.zeros((0,3,1024,2048),np.dtype('<f'))foriinfiles:img=load_image(os.path.join('/root/mysites/goApp/images',i))imgs=np.append(imgs,img,axis=0)#containsallimportedimagesiteration=0
forxinrange(0,imgs.shape[0]-batch_size+1,batch_size):iteration+=1request=predict_pb2.PredictRequest()request.model_spec.name="semantic-segmentation-adas"img=imgs[x:(x+batch_size)]#print("\nRequestshape",img.shape)request.inputs["data"].CopyFrom(make_tensor_proto(img,shape=(img.shape)))start_time=datetime.datetime.now()result=stub.Predict(request,10.0)#resultincludesadictionarywithallmodeloutputsprint(img.shape)output=make_ndarray(result.outputs["4455.1"])
foryinrange(0,img.shape[0]):#iterateoverresponsesfromallimagesinthebatchimg_out=output[y,:,:,:]print("imageinbatchitem",y,",outputshape",img_out.shape)img_out=img_out.transpose(1,2,0)print("savingresultto",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)forbatch,datainenumerate(output):classes_map=np.zeros(shape=(out_h,out_w,3),dtype=np.int)foriinrange(out_h):forjinrange(out_w):iflen(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)returnHttpResponse(output_str)defprocess_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#TODOfilepathoutput_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("\nRequestshape",img.shape)
img=imgs[0:1]request.inputs["data"].CopyFrom(make_tensor_proto(img,shape=(img.shape)))result=stub.Predict(request,10.0)#resultincludesadictionarywithallmodeloutputsprint(img.shape)output=make_ndarray(result.outputs["4455.1"])
foryinrange(0,img.shape[0]):#iterateoverresponsesfromallimagesinthebatchimg_out=output[y,:,:,:]print("imageinbatchitem",y,",outputshape",img_out.shape)img_out=img_out.transpose(1,2,0)print("savingresultto",os.path.join('/root/mysites/goApp/results',param1+'.result.jpg'))out_h,out_w,_=img_out.shapeprint(out_h)print(out_w)forbatch,datainenumerate(output):classes_map=np.zeros(shape=(out_h,out_w,3),dtype=np.int)foriinrange(out_h):forjinrange(out_w):iflen(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)returnHttpResponse(output_str)3.3 在template 中新增兩段html用於介面顯示

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>OpenVINOModelServer的服務化部署(天空分割模型)</title></head><body><formaction="/upload/"method="post"enctype="multipart/form-data">{%csrf_token%}圖片:<inputtype="file"name="avator"><br><inputtype="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/進行帶引數除錯



來自為知筆記(Wiz)

附件列表