四部署: W a i t r e s s + N g i n x 四 部署:Waitress+Nginx 四部署:Waitress+Nginx
链接:https://pan.baidu.com/s/1L3jydu-8ots7OwMwNCpffg
提取码:1234
1.waitress安装和使用
pip install waitress -i https://pypi.tuna.tsinghua.edu.cn/simple
from flask import Flask, request
from exts import db
import os
import numpy as np
import uuid
from flask_cors import CORS
import config
from flask_migrate import Migrate
import restful
import cv2
from MajorAlgo import MajorModel
from waitress import serve
# 发生关联
from models import ModelInfo
# flask实例
app = Flask(__name__,static_folder='./dist', template_folder = "./dist",static_url_path="" )
# 导入配置文件(数据库配置参数)
app.config.from_object(config)
# 数据库绑定app
db.init_app(app)
# 将模型映射到数据库
migrate = Migrate(app,db)
# 跨域访问
CORS(app,resources=r'/*')
# 模型算法实例字典
algo_dict = {}
# 上传AI模型
@app.route("/api/model/upload",methods=['GET','POST'])
def AIModelUploaf():
try:
files = request.files
AIModel = files['AIModel']
if not os.path.exists("./AIModelZoo"):
os.makedirs("./AIModelZoo")
uniqueId = str(uuid.uuid1())
model_path = os.path.join("./AIModelZoo",uniqueId+"_"+AIModel.filename)
AIModel.save(model_path)
return restful.ok(data={"res": model_path})
except:
return restful.server_error()
# 增加模型
@app.route("/api/addModel",methods=['GET','POST'])
def addModel():
try:
algoCategory = request.form["algoCategory"]
task = request.form["task"]
imgsz = request.form["imgsz"]
device = request.form["device"]
modelPath = request.form["modelPath"]
# 添加进数据库
modelInfo = ModelInfo(algoCategory=algoCategory, task=task, imgsz=imgsz, device=device, modelPath=modelPath)
db.session.add_all([modelInfo])
# session提交
db.session.commit()
return restful.ok(data=modelInfo.to_dict())
except:
return restful.server_error()
# 获取所有AI模型列表
@app.route("/api/getAiModelList",methods=['GET','POST'])
def getAiModelList():
try:
all_items = db.session.query(ModelInfo).all()
item_dicts = [item.to_dict() for item in all_items]
return restful.ok(data=item_dicts)
except:
return restful.server_error()
# 获取所有AI模型初始化状态
@app.route("/api/getAiModelInitStateList",methods=['GET','POST'])
def getAiModelInitStateList():
try:
return restful.ok(data=algo_dict)
except:
return restful.server_error()
# 删除模型
@app.route("/api/deleteModel",methods=['GET','POST'])
def deleteModel():
# 获取传递参数
id = request.form.get("id")
try:
# 根据主键获取对象
imgInfo = db.session.query(ModelInfo).get(id)
# 删除操作
db.session.delete(imgInfo)
# 提交数据库
db.session.commit()
# 返回操作成功
return restful.ok()
except:
return restful.server_error()
# 修改模型
@app.route("/api/editModel",methods=['GET','POST'])
def editModel():
try:
# 获取传递参数
id = request.form.get("id")
# 根据主键获取对象
modelInfo = db.session.query(ModelInfo).get(id)
algoCategory = request.form["algoCategory"]
task = request.form["task"]
imgsz = request.form["imgsz"]
device = request.form["device"]
modelPath = request.form["modelPath"]
modelInfo.algoCategory = algoCategory
modelInfo.task = task
modelInfo.imgsz = imgsz
modelInfo.device = device
modelInfo.modelPath = modelPath
# 提交数据库
db.session.commit()
# 返回操作成功
return restful.ok(data=modelInfo.to_dict())
except:
return restful.server_error()
'''
初始化AI模型
'''
@app.route("/api/initModel",methods=['GET','POST'])
def initModel():
try:
# 1.获取模型信息
id = request.form["id"]
algoCategory = request.form["algoCategory"]
task = request.form["task"]
imgsz = request.form["imgsz"]
device = request.form["device"]
modelPath = request.form["modelPath"]
# 2.转字典
parms = {
"uuid": id,
"algoCategory": algoCategory,
"task": task,
"imgsz": imgsz,
"device": device,
"weights": modelPath}
# 3.实例模型
alg = MajorModel(**parms)
# 4.模型实例添加到字典中
algo_dict[id] = alg
# 返回操作成功
return restful.ok()
except:
return restful.server_error()
'''
AI模型测试
'''
@app.route("/api/test",methods=['GET','POST'])
def testDetect():
uuid = request.form['id']
file = request.files['image']
img_buffer_numpy = np.frombuffer(file.read(), dtype=np.uint8)
# 转cv2
img_numpy = cv2.imdecode(img_buffer_numpy, 1)
results = algo_dict[uuid].test(source=img_numpy)
# 返回json数组
re_res = []
# 多张图像
for result in results:
# gpu
# 单张图像
if algo_dict[uuid].device != 'cpu':
xyxy = result.boxes.cuda().cpu().numpy().xyxy
xywh = result.boxes.cuda().cpu().numpy().xywh
cls = result.boxes.cuda().cpu().numpy().cls # Masks object for segmentation masks outputs
conf = result.boxes.cuda().cpu().numpy().conf # Class probabilities for classification outputs
for index_item in range(len(xyxy)):
res_dict = {}
res_dict['SourceImageSerialNumber'] = "seri001"
res_dict['DefectName'] = result.names[cls[index_item]]
res_dict['CenterRowPixel'] = xywh[index_item][0]
res_dict['CenterColPixel'] = xywh[index_item][1]
res_dict['LeftXPixel'] = xyxy[index_item][0]
res_dict['LeftYPixel'] = xyxy[index_item][0]
res_dict['Width'] = xywh[index_item][2]
res_dict['Height'] = xywh[index_item][3]
res_dict['Angle'] = 0
res_dict['Area'] = xywh[index_item][2] * xywh[index_item][3]
res_dict['Gray'] = 0
res_dict['Dev'] = 0
re_res.append(res_dict)
# cpu
else:
xyxy = result.boxes.cpu().numpy().xyxy
xywh = result.boxes.cpu().numpy().xywh
cls = result.boxes.cpu().numpy().cls # Masks object for segmentation masks outputs
conf = result.boxes.cpu().numpy().conf # Class probabilities for classification outputs
for index_item in range(len(xyxy)):
res_dict = {}
res_dict['SourceImageSerialNumber'] = "seri001"
res_dict['DefectName'] = result.names[cls[index_item]]
res_dict['CenterRowPixel'] = xywh[index_item][0]
res_dict['CenterColPixel'] = xywh[index_item][1]
res_dict['LeftXPixel'] = xyxy[index_item][0]
res_dict['LeftYPixel'] = xyxy[index_item][0]
res_dict['Width'] = xywh[index_item][2]
res_dict['Height'] = xywh[index_item][3]
res_dict['Angle'] = 0
res_dict['Area'] = xywh[index_item][2] * xywh[index_item][3]
res_dict['Gray'] = 0
res_dict['Dev'] = 0
re_res.append(res_dict)
return restful.ok(data=str(re_res))
if __name__ == '__main__':
# app.run()
serve(app, host='0.0.0.0', port=5000)
2.python虚拟环境配置
1)下载包
pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple
(2)创建虚拟环境
1.新建文件夹
2.在新建文件夹目录,输入下面的命令
virtualenv ENV
3.进入Script文件夹激活虚拟环境
activate
4.安装pytorch和torchvision
pip install "F:\BaiduNetdiskDownload\torch-2.0.1+cu117-cp38-cp38-win_amd64.whl" -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install "F:\BaiduNetdiskDownload\torchvision-0.15.2+cu117-cp38-cp38-win_amd64.whl" -i https://pypi.tuna.tsinghua.edu.cn/simple
5.安装yolov8
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
6.安装其他所需库
pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install SQLAlchemy-serializer -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask_cors -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-migrate -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install waitress -i https://pypi.tuna.tsinghua.edu.cn/simple
在虚拟环境中进行试运行,成功运行后,准备打包
3.pyinstaller打包
安装pyinstaller
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
pyinstaller -D flask_app.py
或者直接激活虚拟环境进行打包
pyinstaller -D D:\workplace\PycharmProjects\TestFlaskVue\flask_app.py
复制所需资源
打包运行成功
打包vue前端
npm run build
前端和后端直接绑定相连
4.Nginx下载安装
## [中文网:https://nginx.p2hp.com/](https://nginx.p2hp.com/)
官网:http://nginx.org/
nginx.exe -s stop //停止nginx
nginx.exe -s reload //重新加载nginx
nginx.exe -s quit //退出nginx
Nginx常用指令
1、检查配置文件
在重启Nginx之前首先要检查配置文件是否有误:
nginx -t -c ./conf/nginx.conf
如果没有语法错误,则会输出以下信息:
nginx: the configuration file /path/to/nginx.conf syntax is ok
nginx: configuration file /path/to/nginx.conf test is successful
2、修改配置文件
打开nginx.conf文件,并进行修改
3、停止Nginx
在重启Nginx之前需要先停止当前正在运行的Nginx进程。
nginx -s stop
如果当前进程没有停止,则可以使用以下命令来强制停止:
nginx -s quit
4、启动Nginx
start nginx
如果想要启动Nginx并指定配置文件,则可以使用以下命令:
nginx -c ./conf/nginx.conf
5、重启Nginx
重启Nginx时,配置文件会被重新加载。
nginx -s reload
6、设定自启动
如果想要在系统启动时Nginx自动启动,可以将Nginx添加到系统服务中。可以使用以下命令将Nginx添加到服务:
以管理员身份运行cmd,然后运行下面指令
sc create nginx binPath= "D:\nginx-1.24.0\nginx-1.24.0\nginx.exe" displayName= "Nginx" start= "auto"
在上述命令中,binPath为Nginx可执行文件的路径,displayName为服务的显示名称,start为服务的启动类型。
注意:
1.在Windows下重启Nginx需要先检查配置文件,修改需要修改的配置项,然后停止当前正在运行的进程,并重新启动或重启Nginx。
2.可以将Nginx添加到系统服务中,实现自动启动。
5. Nginx反向代理和负载均衡
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream major{
server 127.0.0.1:5000 weight=1;
server 127.0.0.1:6000 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
proxy_pass http://major;
client_max_body_size 1024m;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}