Flask快速搭建輕量級(jí)圖像識(shí)別服務(wù)器
筆者選擇Flask作為開發(fā)后臺(tái)。Flask是一個(gè)基于Python編寫的Web應(yīng)用框架,相對(duì)于Django及Tornado,F(xiàn)lask可以說是一個(gè)輕量級(jí)選手,靈活、可擴(kuò)展性強(qiáng)(主要是容易上手
),很適用于開發(fā)中小型網(wǎng)站或應(yīng)用服務(wù)。
# 使用以下命令進(jìn)行安裝pip?install?Flask
要部署的模型則是基于Keras深度學(xué)習(xí)框架下(以TensorFlow為后端)訓(xùn)練保存的模型,其格式為HDF5,需同時(shí)含有網(wǎng)絡(luò)結(jié)構(gòu)信息與權(quán)重信息。因此需要在服務(wù)器端安裝TensorFlow及Keras,若需要使用顯卡加速,則還需安裝CUDA及cuDNN,并升級(jí)TensorFlow為GPU版本。

# 使用顯卡加速時(shí),根據(jù)ID指定特定的顯卡
import?os
os.environ["CUDA_VISIBLE_DEVICES"]?=?"0"
# 調(diào)整顯存使用率,方便服務(wù)器快速啟動(dòng)
import?tensorflow?as?tf
config=tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth=True???
sess=tf.compat.v1.Session(config=config)?
# 加載其他所需組件
from?keras.preprocessing.image?import?img_to_array
from?keras.models?import?load_model
from?keras.applications?import?imagenet_utils
from?PIL?import?Image
import?numpy?as?np
import?flask
import?io
#?新建一個(gè)應(yīng)用服務(wù)實(shí)例及定義保存模型的變量名
app?=?flask.Flask(__name__)
model?=?None
# 加載事先訓(xùn)練好的模型,注意這里函數(shù)名為load_model2旨在為避免與keras的load_model重名而報(bào)錯(cuò)
def?load_model2():
??# 設(shè)為全局變量,確保調(diào)用正確
??global?model
??model?=load_model('model_name.h5')
# 圖片預(yù)處理過程
def?prepare_image(image,?target):
??#?如果文件通道非RGB排列則調(diào)整為RGB
??if?image.mode?!=?"RGB":
????image?=?image.convert("RGB")
??#?尺寸縮放及數(shù)據(jù)格式調(diào)整
??image?=?image.resize(target)
??image?=?img_to_array(image)
??image?=?np.expand_dims(image,?axis=0)
??image?=?imagenet_utils.preprocess_input(image)
??#?返回處理后結(jié)果
??return?image
# 使用函數(shù)裝飾器對(duì)新建的服務(wù)實(shí)例進(jìn)行地址與請(qǐng)求方式的擴(kuò)展設(shè)置
@app.route("/predict",?methods=["POST"])
# 圖像識(shí)別判斷函數(shù),若將load_model寫入則每次發(fā)送請(qǐng)求都會(huì)加載一次模型
def?predict():
??#?初始化狀態(tài)值
??data?=?{"success":?False}
??#?判斷請(qǐng)求方式是否為POST,若為真則讀入圖片
??if?flask.request.method?==?"POST":
????if?flask.request.files.get("image"):
??????image?=?flask.request.files["image"].read()
??????image?=?Image.open(io.BytesIO(image))
??????#?對(duì)圖像進(jìn)行預(yù)處理
??????image?=?prepare_image(image,?target=(224,?224))
??????#?使用模型進(jìn)行識(shí)別
??????preds?=?model.predict(image)
??????#?將識(shí)別結(jié)果進(jìn)行轉(zhuǎn)換
??????fct=np.argmax(preds,?axis=1)+1
??????#?創(chuàng)建返回結(jié)果的字典
??????data["predictions"]?=?[]
??????# 保存識(shí)別結(jié)果及對(duì)應(yīng)的概率
??????r?=?{"能見度等級(jí)":?str(fct[0]),?"probability":?str(preds[0][fct[0]-1])}
??????# 將結(jié)果存放入字典中
??????data["predictions"].append(r)
??????#?改變狀態(tài)值
??????data["success"]?=?True
??????# 服務(wù)端顯示結(jié)果
??????print(data)
??#?將結(jié)果以JSON格式返回
??return?flask.jsonify(data)
if?__name__?==?"__main__":
??#?加載模型
??load_model2()
??#?啟動(dòng)服務(wù)(若出現(xiàn)thread_local錯(cuò)誤,請(qǐng)?jiān)趓un中添加threaded=False,或升級(jí)keras版本)
??app.run()
# 加載所需組件
import?requests
# 設(shè)置URL地址
KERAS_REST_API_URL?=?"http://localhost:5000/predict"
# 設(shè)置圖像文件地址
IMAGE_PATH?=?"test.jpg"
#?讀取圖像并將其保存在字典中進(jìn)行發(fā)送
image?=?open(IMAGE_PATH,?"rb").read()
payload?=?{"image":?image}
#?以POST發(fā)送請(qǐng)求,并將返回的JSON格式進(jìn)行解析
r?=?requests.post(KERAS_REST_API_URL,?files=payload).json()
#?確保服務(wù)端程序執(zhí)行正確,并顯示結(jié)果,否則提示請(qǐng)求失敗
if?r["success"]:
??print(r["predictions"])
else:
??print("Request?failed")
---— 5.結(jié)果展示 —---
#首先啟動(dòng)服務(wù)python?keras_serve.py#由于在本地調(diào)式未啟用WSGI服務(wù),會(huì)有warning提示,另在生產(chǎn)環(huán)境中切勿使用debug模式。
開啟應(yīng)用后,服務(wù)端界面

#其次發(fā)送請(qǐng)求python client_request.py
發(fā)送請(qǐng)求后,用戶端界面

服務(wù)端界面

更多閱讀
特別推薦

點(diǎn)擊下方閱讀原文加入社區(qū)會(huì)員
評(píng)論
圖片
表情
