天天看點

深層檢測模型部署-測試版

連結:源代碼

提取碼:7gpf

B站視訊:第一次講,有很多問題,也先放在這裡吧,麥克分問題,聲音很小

上:https://www.bilibili.com/video/BV19f4y1y7xd?from=search&seid=4295823664546149809

下:https://www.bilibili.com/video/BV1qK411p72Q?from=search&seid=4295823664546149809

深 度 檢 測 模 型 部 署 − 測 試 版 深層檢測模型部署-測試版 深層檢測模型部署−測試版

  • 1.技術架構及編碼邏輯
  • 2.一測
  • 3.二測
  • 4.補充

1.技術架構及編碼邏輯

深層檢測模型部署-測試版
技術架構:

Pytorch-GPU 、Flask
           
編碼邏輯:

#------------------------------------------------------0.引入庫--------------------------------------------------------------

#------------------------------------------------------1.加載模型--------------------------------------------------------------

#------------------------------------------------------2.擷取Inference資料--------------------------------------------------------------

#------------------------------------------------------3.定義資料預處理--------------------------------------------------------------

#------------------------------------------------------4.模型預測--------------------------------------------------------------

#------------------------------------------------------5.服務傳回--------------------------------------------------------------

#------------------------------------------------------6.主函數--------------------------------------------------------------




           

2.一測

服務端:Server.py

# -*- coding: utf-8 -*-
# 導入常用的庫
import time
import os
import torch
from PIL import Image
import torchvision.transforms as transforms
# 導入flask庫的Flask類和request對象
from flask import request, Flask
app = Flask(__name__)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# # 定義字典className_list,把種類索引轉換為種類名稱
# className_list = ['__background__', 'wheat_head']

#------------------------------------------------------1.加載模型--------------------------------------------------------------
path_model="./saved_model/model2.pkl"
model_loaded=torch.load(path_model)

#------------------------------------------------------2.擷取測試圖檔--------------------------------------------------------------

# img_dir=os.path.join(BASE_DIR ,"data", "global-wheat-detection","test")
# names = [name for name in list(filter(lambda x: x.endswith(".jpg"), os.listdir(img_dir)))]
#path_img = os.path.join(BASE_DIR ,"data", "global-wheat-detection","test",i)

# 根據圖檔檔案路徑擷取圖像資料矩陣
def get_imageNdarray(imageFilePath):
    input_image = Image.open(imageFilePath).convert("RGB")
    return input_image


#------------------------------------------------------3.定義圖檔預處理--------------------------------------------------------------
# 模型預測前必要的圖像處理
def process_imageNdarray(input_image):
    preprocess = transforms.Compose([
        transforms.ToTensor(),
    ])
    img_chw = preprocess(input_image)
    return img_chw  # chw:channel height width

#------------------------------------------------------4.模型預測--------------------------------------------------------------
# 使用模型對指定圖檔檔案路徑完成圖像分類,傳回值為預測的種類名稱
def predict_image(model, imageFilePath):
    model.eval()  # 參數固化
    input_image = get_imageNdarray(imageFilePath)
    img_chw = process_imageNdarray(input_image)
    if torch.cuda.is_available():
        img_chw = img_chw.to('cuda')
        model.to('cuda')
    input_list = [img_chw]
    with torch.no_grad():  # 不計算梯度
        output_list = model(input_list)
        output_dict = output_list[0]
        #print('對此圖檔路徑 %s 的預測結果為 %s' % (output_dict))
        return output_dict

#------------------------------------------------------5.服務傳回--------------------------------------------------------------
# 定義回調函數,接收來自/的post請求,并傳回預測結果
@app.route("/", methods=['POST'])
def return_result():
    startTime = time.time()
    received_file = request.files['file']
    imageFileName = received_file.filename
    if received_file:
        received_dirPath = './resources/received_images'
        if not os.path.isdir(received_dirPath):
            os.makedirs(received_dirPath)
        imageFilePath = os.path.join(received_dirPath, imageFileName)
        received_file.save(imageFilePath)
        print('圖檔檔案儲存到此路徑:%s' % imageFilePath)
        usedTime = time.time() - startTime
        print('接收圖檔并儲存,總共耗時%.2f秒' % usedTime)
        startTime = time.time()
        print(imageFilePath)
        result = predict_image(model_loaded, imageFilePath)
        result = str(result)
        print(result)
        usedTime = time.time() - startTime
        print('完成對接收圖檔的檢測,總共耗時%.2f秒' % usedTime)
        print("testtest",result)
        return result
    else:
        return 'failed'


# 主函數
if __name__ == "__main__":
    #print('在開啟服務前,先測試predict_image函數')
    # imageFilePath = os.path.join(BASE_DIR, "data", "global-wheat-detection", "test", "51b3e36ab.jpg")
    # result = predict_image(model_loaded, 'D:\\PycharmWorkPlaces\\DeepModel_deploy_flask\\data\\global-wheat-detection\\test\\51b3e36ab.jpg')
    # print(result)
    app.run("127.0.0.1", port=5000)

           

用戶端:Client.py

import requests
import os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))


# 主函數
if __name__ == "__main__":
    url = "http://127.0.0.1:5000"
    while True:
        input_content = input('輸入圖檔路徑,輸入-1退出,預設值os.path.join(BASE_DIR, "data", "global-wheat-detection", "test", "51b3e36ab.jpg") ')
        if input_content.strip() == "":
            input_content = 'D:\\PycharmWorkPlaces\\DeepModel_deploy_flask\\data\\global-wheat-detection\\test\\51b3e36ab.jpg'
        if input_content.strip() == "-1":
            break
        elif not os.path.exists(input_content.strip()):
            print('輸入圖檔路徑不正确,請重新輸入')
        else:
            imageFilePath = input_content.strip()
            imageFileName = os.path.split(imageFilePath)[1]
            file_dict = {
                'file':(imageFileName,
                    open(imageFilePath,'rb'),
                    'image/jpg')}
            result = requests.post(url, files=file_dict)
            predict_result = result.text
            print('圖檔路徑:%s 預測結果為:%s\n' %(imageFilePath, predict_result))
           

3.二測(用戶端為頁面)

服務端:Server2.py

# -*- coding: utf-8 -*-
# 導入常用的庫
import time
import os
import torch
from PIL import Image
import torchvision.transforms as transforms
import json
# 導入flask庫的Flask類和request對象
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# # 定義字典className_list,把種類索引轉換為種類名稱
# className_list = ['__background__', 'wheat_head']

#------------------------------------------------------1.加載模型--------------------------------------------------------------
path_model="./saved_model/model2.pkl"
#model_loaded=torch.load(path_model,map_location='cpu') # 隻有cpu加載模型
model_loaded=torch.load(path_model)
#------------------------------------------------------2.擷取測試圖檔--------------------------------------------------------------

# img_dir=os.path.join(BASE_DIR ,"data", "global-wheat-detection","test")
# names = [name for name in list(filter(lambda x: x.endswith(".jpg"), os.listdir(img_dir)))]
#path_img = os.path.join(BASE_DIR ,"data", "global-wheat-detection","test",i)

# 根據圖檔檔案路徑擷取圖像資料矩陣
def get_imageNdarray(imageFilePath):
    input_image = Image.open(imageFilePath).convert("RGB")
    return input_image


#------------------------------------------------------3.定義圖檔預處理--------------------------------------------------------------
# 模型預測前必要的圖像處理
def process_imageNdarray(input_image):
    preprocess = transforms.Compose([
        transforms.ToTensor(),
    ])
    img_chw = preprocess(input_image)
    return img_chw  # chw:channel height width

#------------------------------------------------------4.模型預測--------------------------------------------------------------
# 使用模型對指定圖檔檔案路徑完成圖像分類,傳回值為預測的種類名稱
def predict_image(model, imageFilePath):
    model.eval()  # 參數固化
    input_image = get_imageNdarray(imageFilePath)
    img_chw = process_imageNdarray(input_image)
    if torch.cuda.is_available():
        img_chw = img_chw.to('cuda')
        model.to('cuda')
    input_list = [img_chw]
    with torch.no_grad():  # 不計算梯度
        output_list = model(input_list)
        output_dict = output_list[0]
        #print('對此圖檔路徑 %s 的預測結果為 %s' % (output_dict))
        return output_dict

#------------------------------------------------------5.服務傳回--------------------------------------------------------------


# 通路首頁時的調用函數
@app.route('/')
def index_page():
    return render_template('index.html')


# 使用predict_image這個API服務時的調用函數
@app.route("/upload_image", methods=['POST'])
def anyname_you_like():
    startTime = time.time()
    received_file = request.files['input_image']
    imageFileName = received_file.filename
    if received_file:
        received_dirPath = '../resources/received_images'
        if not os.path.isdir(received_dirPath):
            os.makedirs(received_dirPath)
        imageFilePath = os.path.join(received_dirPath, imageFileName)
        received_file.save(imageFilePath)
        print('image file saved to %s' % imageFilePath)
        usedTime = time.time() - startTime
        print('接收圖檔并儲存,總共耗時%.2f秒' % usedTime)
        startTime = time.time()
        result = predict_image(model_loaded, imageFilePath)
        result = str(result)
        usedTime = time.time() - startTime
        print('完成對接收圖檔的預測,總共耗時%.2f秒' % usedTime)
        # return result
        return render_template("result.html",result=result)
    else:
        return 'failed'



# 主函數
if __name__ == "__main__":
    # print('在開啟服務前,先測試predict_image函數')
    # imageFilePath = 'D:\\PycharmWorkPlaces\\DeepModel_deploy_flask\\data\\global-wheat-detection\\test\\51b3e36ab.jpg'
    # result = predict_image(model_loaded, imageFilePath)
    app.run("127.0.0.1", port=5000)
           

用戶端:index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>測試</title>
    </head>
    <body>
        <div>
            <form method="post" action="http://localhost:5000/upload_image" enctype="multipart/form-data">
               <input type="file"  value="選擇檢測圖檔" size="22" id="select_files" name="input_image" onchange="show_selectedImage()"/>
               <br>
               <canvas id="image_canvas" height="1020" width="1020"></canvas>
               <text name="image_className" value=""/>
               <br>
               <input type="submit" class="button-new" value="送出資訊" style="margin-top:15px;"/>
            </form>

            <script type="text/javascript">
                function show_selectedImage(){
                    /// get select files.
                    var selected_files = document.getElementById("select_files").files;
                    for(var file of selected_files){
                        console.log(file.webkitRelativePath);
                        /// read file content.
                        var reader = new FileReader();
                        reader.readAsDataURL(file);
                        reader.onloadend = function(){
                            /// deal data.
                            var img = new Image();
                            /// after loader, result storage the file content result.
                            img.src = this.result;
                            img.onload = function(){
                                var canvas = document.getElementById("image_canvas");
                                var cxt = canvas.getContext('2d');
                                cxt.drawImage(img, 0, 0);
                            }
                        }
                    }
                }
            </script>
        </div>
    </body>
</html>
           

傳回結果網頁:result.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>傳回結果</title>
</head>
<body>
<h1>傳回結果是:</h1>


{{ result }}

</body>
</html>
           

4.補充

圖像識别工程的工作步驟:

  • 1.資料準備:

    1.1拍攝照片或者下載下傳資料集;

    1.2圖像标注;

    1.3圖像資料處理(圖像合成、圖像剪裁、圖像改變像素大小);

    1.4檢查标注檔案的正确性;

    1.5劃分訓練集、驗證集.

  • 2.模型搭建
  • 3.模型訓練(讀取資料的多線程生成器、多GPU并行訓練、儲存模型)
  • 4.模型評估(加載模型、使用業務對應的評估名額在驗證集上計算模型效果)
  • 5.模型測試(使用實際場景中的圖像資料測試模型效果,單張圖檔檢測、實時視訊檢測)
  • 6.模型部署(web、Android、開發闆)
  • 7.閉環優化

    7.1根據業務使用場景在第2步優化;

    7.2根據模型在實際場景的使用效果在第3-6步之,間循環疊代

    7.2.1如果新加入的資料提高了模型在驗證集上的效果,則替換模型部署使用的權重檔案

    7.2.2如果替換後的新權重檔案在實際場景中使用效果不好,則使用版本控制工具回退到上一-個版本的權重檔案

完成搭建神經網絡的要點:

1.确定網絡的輸入矩陣的形狀;

2.确定網絡的輸出矩陣的形狀;

3.了解網絡的架構流程;

4.确定每個資料層、處理層的矩陣形狀:

5.了解并實作網絡計算損失的損失函數;

6.了解權重優化使用的優化器;