【AI视觉】基于flask部署(3-1)

1,098 阅读3分钟

来咯来咯,它带着沉淀了半个月的学习回来了,上一篇: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)请求接口
  • 我们可以看响应码,也可以看服务端的结果

image.png

欧克,小编写的不是很好,主要是也是刚学的,也只是学了图像的,视频流还没学,项目还没上过手,只是看开源项目。写的不好,希望大家多多指正,因为自己确实有打算往这条路发展。