基于flask的YOLO⽬标检测web服务及接⼝
这个⼩项⽬是基于flask微型⽬标检测服务。使⽤的是YOLOv3版本,使⽤的是在coco数据集上已经训练好的参数。整个⽬录结构如下(我运⾏的环境是window10,pycharm):
其中:
1. cfg是YOLOv3的配置⽂件,包括权重,⽹络结构和coco数据集的标签;
2. static是通过⽹络访问该服务时被保存的图⽚;
3. templates是⽹页UI的代码;
4. flask_yolo.py是启动该服务的⼊⼝;
5. testYoloSer.py是测试该服务的接⼝代码;
6. yolomain.py是YOLOv3的实现代码;
需要注意的是,由于上传⼤⼩的限制只能上传⼩于220M的⽂件,⽽该⽬录中yolov3_coco.weights就有230多M。如果想运⾏你需要下载该⽂件,当然你⽤积分下载该项⽬后不想⾃⼰,也可以在下⾯评论留⾔,我可以发给你。
其中,主要⽂件的代码如下:
flask_yolo.py
# -*- coding: utf-8 -*-#
# Author: weiz
# Date: 2019/9/16 14:12
# Name: flask_yolo
# Description: ⼀个可以在浏览器使⽤YOLO⽬标检测的函数,和⼀个可以通过⽹络访问的YOLO⽬标检测的接⼝
# 直接运⾏就可以在浏览器上⾯输⼊带检测图⽚,并返回检测的结果;同时,可以接受通过局域⽹
# 访问该接⼝的服务。
from flask import Flask, render_template, request, jsonify, make_response
from werkzeug.utils import secure_filename
import os
import cv2
import time
import json
from PIL import Image
from io import BytesIO
import json
import numpy as np
from datetime import timedelta
import yolomain
# 设置允许的⽂件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
app = Flask(__name__)
# 设置静态⽂件缓存过期时间
app.send_file_max_age_default = timedelta(seconds=1)
# @ute('/upload', methods=['POST', 'GET'])
@ute('/upload', methods=['POST', 'GET']) # 添加路由
def upload():
hod == 'POST':
f = request.files['file']
if not (f and allowed_file(f.filename)):
return jsonify({"error": 1001, "msg": "请检查上传的图⽚类型,仅限于png、PNG、jpg、JPG、bmp"}) user_input = ("name")
# 当前⽂件所在路径
basepath = os.path.dirname(__file__)
# 注意:没有的⽂件夹⼀定要先创建,不然会提⽰没有该路径
upload_path = os.path.join(basepath, 'static/images', secure_filename(f.filename))
f.save(upload_path)
lab, img, loc = lo_detect(pathIn=upload_path)
cv2.imwrite(os.path.join(basepath, 'static/images', 'test.jpg'), img)
return render_template('upload_ok.html', userinput=user_input, val1=time.time(), data_dict=lab)
return render_template('upload.html')
@ute('/yolo_service',methods=['POST'])
def detection():
img = ad()
f = BytesIO(img)
image = Image.open(f)
image = np.array(image, dtype='float32')
boxes, lab = lo_ser(image)
rsp = make_response(json.dumps(lab))
rsp.mimetype = 'application/json'
rsp.headers['Connection'] = 'close'
return rsp
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
testYoloSer.py
# -*- coding: utf-8 -*-#
# Author: weiz
# Date: 2019/9/16 17:05
flask下载# Name: test_yolo
# Description: 测试YOLOweb服务是否可以使⽤的代码(请先运⾏flask_yolo.py)
import requests
import os
import json
if __name__ == '__main__':
# 注意填写⾃⼰电脑的IP地址
url = '192.168.124.19:5000/yolo_service'
headers = {'Content-Type': 'image/jpeg'}
file = {'media': open('./static/images/test.jpg', 'rb')}
requests.post(url, files=file)
data = open('./static/images/test.jpg', 'rb').read()
r = requests.post(url, data=data, headers=headers, verify=False)
print("类别:置信度 (左上⾓X坐标,左上⾓Y坐标) (⽬标的宽, ⽬标的⾼)")
)
yolomain.py
# -*- coding: utf-8 -*-
# Author: weiz
# Date: 2019/9/16 17:00
# Name: test_yolo
# Description: YOLOv3⽬标检测的代码,提供检测的接⼝;也可以单独运⾏。
# 载⼊所需库
import cv2
import numpy as np
import os
import time
def yolo_detect(im=None,
pathIn=None,
label_path='./cfg/coco.names',
config_path='./cfg/yolov3_coco.cfg',
weights_path='./cfg/yolov3_coco.weights',
confidence_thre=0.5,
nms_thre=0.3):
'''
im:原始图⽚
pathIn:原始图⽚的路径
label_path:类别标签⽂件的路径
config_path:模型配置⽂件的路径
weights_path:模型权重⽂件的路径
confidence_thre:0-1,置信度(概率/打分)阈值,即保留概率⼤于这个值的边界框,默认为0.5 nms_thre:⾮极⼤值抑制的阈值,默认为0.3
'''
# 加载类别标签⽂件
LABELS = open(label_path).read().strip().split("\n")
nclass = len(LABELS)
# 为每个类别的边界框随机匹配相应颜⾊
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(nclass, 3), dtype='uint8')
# 载⼊图⽚并获取其维度
#base_path = os.path.basename(pathIn)
if pathIn == None:
if pathIn == None:
img = im
else:
img = cv2.imread(pathIn)
(H, W) = img.shape[:2]
net = adNetFromDarknet(config_path, weights_path)
# 获取YOLO输出层的名字
ln = LayerNames()
ln = [ln[i[0] - 1] for i UnconnectedOutLayers()]
# 将图⽚构建成⼀个blob,设置图⽚尺⼨,然后执⾏⼀次
# YOLO前馈⽹络计算,最终获取边界框和相应概率
blob = cv2.dnn.blobFromImage(img, 1 / 255.0, (416, 416), swapRB=True, crop=False) net.setInput(blob)
start = time.time()
layerOutputs = net.forward(ln)
end = time.time()
# 初始化边界框,置信度(概率)以及类别
boxes = []
confidences = []
classIDs = []
# 迭代每个输出层,总共三个
for output in layerOutputs:
# 迭代每个检测
for detection in output:
# 提取类别ID和置信度
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID]
# 只保留置信度⼤于某值的边界框
if confidence > confidence_thre:
# 将边界框的坐标还原⾄与原图⽚相匹配,记住YOLO返回的是
# 边界框的中⼼坐标以及边界框的宽度和⾼度
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height) = box.astype("int")
# 计算边界框的左上⾓位置
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
# 更新边界框,置信度(概率)以及类别
boxes.append([x, y, int(width), int(height)])
confidences.append(float(confidence))
classIDs.append(classID)
# 使⽤⾮极⼤值抑制⽅法抑制弱、重叠边界框
idxs = cv2.dnn.NMSBoxes(boxes, confidences, confidence_thre, nms_thre)
lab = []
loc = []
# 确保⾄少⼀个边界框
if len(idxs) > 0:
# 迭代每个边界框
for i in idxs.flatten():
# 提取边界框的坐标
(x, y) = (boxes[i][0], boxes[i][1])
(w, h) = (boxes[i][2], boxes[i][3])
# 绘制边界框以及在左上⾓添加类别标签和置信度
color = [int(c) for c in COLORS[classIDs[i]]]
text = '{}: {:.3f}'.format(LABELS[classIDs[i]], confidences[i])
(text_w, text_h), baseline = TextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2) angle(img, (x, y-text_h-baseline), (x + text_w, y), color, -1)
cv2.putText(img, text, (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
text_inf = text + ' ' + '(' + str(x) + ',' + str(y) + ')' + ' ' + '宽:' + str(w) + '⾼:' + str(h)
loc.append([x, y, w, h])
lab.append(text_inf)
return lab, img, loc
def yolo_ser(im,
label_path='./cfg/coco.names',
config_path='./cfg/yolov3_coco.cfg',
weights_path='./cfg/yolov3_coco.weights',
confidence_thre=0.5,
nms_thre=0.3):
'''
im:原始图⽚
label_path:类别标签⽂件的路径
config_path:模型配置⽂件的路径
weights_path:模型权重⽂件的路径
confidence_thre:0-1,置信度(概率/打分)阈值,即保留概率⼤于这个值的边界框,默认为0.5 nms_thre:⾮极⼤值抑制的阈值,默认为0.3
'''
LABELS = open(label_path).read().strip().split("\n")
nclass = len(LABELS)
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(nclass, 3), dtype='uint8')
img = im
(H, W) = img.shape[:2]
net = adNetFromDarknet(config_path, weights_path)
# 获取YOLO输出层的名字
ln = LayerNames()
ln = [ln[i[0] - 1] for i UnconnectedOutLayers()]
# 将图⽚构建成⼀个blob,设置图⽚尺⼨,然后执⾏⼀次
# YOLO前馈⽹络计算,最终获取边界框和相应概率
blob = cv2.dnn.blobFromImage(img, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
start = time.time()
layerOutputs = net.forward(ln)
end = time.time()
# 初始化边界框,置信度(概率)以及类别
boxes = []
confidences = []
classIDs = []
# 迭代每个输出层,总共三个
for output in layerOutputs:
# 迭代每个检测
for detection in output:
# 提取类别ID和置信度
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID]
# 只保留置信度⼤于某值的边界框
if confidence > confidence_thre:
# 将边界框的坐标还原⾄与原图⽚相匹配,记住YOLO返回的是
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论