来咯来咯,它带着沉淀了半个月的学习回来了,上一篇:yolo基于flask部署是以小白的身份,一步步的从拉代码到部署的过程:
- github 拉取 yolov5源码
- 本地创建flask项目
- 借用别人写好的前后端实现
- 调通代码,跑跑跑
本篇和之前侧重点有所不同了,这里我们不care使用哪个模型,也不care前端样式。本篇我们只在意我们的模型是如何让flask对外暴露的(写个接口)的流程,模拟客户端请求接口。重点是重要步骤的理解
首先还是上一篇那个项目,流程:
- 项目是启动后,
app.run(host='0.0.0.0', debug=True)
- 调用页面,
@app.route('/')
def index():
return render_template('index.html') # template文件夹下的index.html
- 执行视频流,
<img src="{{ url_for('video_feed') }}">
- 加载模型。
Camera()
- 实现图像检测
im0, img = self.preprocess(frame) # 转到处理函数
pred = self.m(img, augment=False)[0] # 输入到模型
简单的小结一下:
对于上面的流程我们可以发现这是我们启动完项目之后,当我们用到了图像检测的时候,才会去加载我们的模型,这个效率其实是会比较慢的,建议就是在启动项目的时候就去加载模型。
好,接下来就是重头戏了,我们怎么写一个接口去调用我们的模型:
@app.route('/detect', methods=['POST'])
def vedio_stream():
if request.method == 'POST':
stream = request.files['videoFile'].stream
# 将文件流写入临时文件
temp_video_path = 'temp_video.mp4'
with open(temp_video_path, 'wb') as temp_video_file:
temp_video_file.write(stream.read())
video_manager.cap = cv2.VideoCapture(temp_video_path)
return redirect('/') # 重定向到显示处理视频的页面
return 'request method error!'
- flask框架自带的,先指定方法的接口,和请求类型
- 判断请求方式
- 打开视频,读取视频流,重定向回到首页 (这些步骤可以忽略)
- 视频流播放调用到了图像检测
@app.route('/video_feed') # 这个地址返回视频流响应
def video_feed():
return Response(gen(Camera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
def preprocess(self, img):
img0 = img.copy()
img = letterbox(img, new_shape=self.img_size)[0]
img = img[:, :, ::-1].transpose(2, 0, 1)
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(self.device)
img = img.half() # 半精度
img /= 255.0 # 图像归一化
if img.ndimension() == 3:
img = img.unsqueeze(0)
return img0, img
- 先对视频图片做一个预处理的操作
- 图片矩阵转换
- 转成基于cuda的tensor格式
for det in pred:
if det is not None and len(det):
det[:, :4] = scale_boxes(
img.shape[2:], det[:, :4], im0.shape).round()
for *x, conf, cls_id in det:
lbl = self.names[int(cls_id)]
x1, y1 = int(x[0]), int(x[1])
x2, y2 = int(x[2]), int(x[3])
pred_boxes.append(
(x1, y1, x2, y2, lbl, conf))
count += 1
key = '{}-{:02}'.format(lbl, count)
image_info[key] = ['{}×{}'.format(
x2 - x1, y2 - y1), np.round(float(conf), 3)]
frame = self.plot_bboxes(frame, pred_boxes)
ret, jpeg = cv2.imencode('.jpg', frame)
return jpeg.tobytes()
- 接上面模型预测出来的结果,对预测结果进行遍历
- 获取对应的坐标值,标签,偏置,添加到列表中
- 然后将标签和序号作为key,坐标作为value
- 最后将结果输出
不考虑前端的情况下,我们引入 requests 实现客户端。
import requests
# url和端口携程自己的
flask_url = 'http://127.0.0.1:5000/detect'
with open("temp_video.mp4", 'rb') as f:
file_data = {'videoFile': (f.name, f)}
# 发送POST请求
response = requests.post(flask_url, files=file_data)
# 检查响应状态码
if response.status_code == 200:
print('Request successful!')
else:
print(f'Request failed with status code {response.status_code}')
- with 打开我们的视频文件
- 通过requests.post(flask_url, files=file_data)请求接口
- 我们可以看响应码,也可以看服务端的结果
欧克,小编写的不是很好,主要是也是刚学的,也只是学了图像的,视频流还没学,项目还没上过手,只是看开源项目。写的不好,希望大家多多指正,因为自己确实有打算往这条路发展。