用flask搭建模型服务

用flask搭建tensorflow2的服务

# -*- coding: utf-8 -*-
# @File : www.py
# @Project : www
# @desc : 启动flask

import tensorflow as tf
import io
from PIL import Image
from flask import Flask, request
import cv2
import numpy as np


app = Flask(__name__)


TF2_DETECTION_URL = "/kctf2"


def load_test_img(path):
    img_raw = tf.io.read_file(path)   # 读取图片为二进制
    img_tensor = tf.image.decode_jpeg(img_raw, channels=3)   # 解码为张量
    img_tensor = tf.image.resize(img_tensor, [299, 299])   # 图片大小缩放
    img_tensor = tf.cast(img_tensor, tf.float32)   # 转换图片数字类型从uint8转为float32便于计算
    img_tensor = img_tensor / 255      # 图片数据归一化
    return img_tensor

@app.route(TF2_DETECTION_URL, methods=["POST"])
def tfpredict():
    if not request.method == "POST":
        return

    if request.files.get("image"):
        image_file = request.files["image"]
        image_bytes = image_file.read()
        img_tensor = cv2.imdecode(np.array(bytearray(image_bytes), dtype='uint8'), cv2.IMREAD_UNCHANGED)
        # img = Image.open(io.BytesIO(image_bytes))
        # img.save("./static/img/tmp.png")
        # testimg = load_test_img("./static/img/tmp.png")
        # testimg = tf.expand_dims(testimg, 0)
        # img_tensor = tf.image.encode_jpg(img_tensor, channels=3)

        # model = tf.keras.models.load_model('kcEnterGame.h5')
        # img_raw = tf.io.read_file('1.jpg')
        # img_tensor = tf.image.decode_jpeg(img_raw, channels=3)  # 解码为张量

        img_tensor = tf.image.resize(img_tensor, [299, 299])  # 图片大小缩放
        img_tensor = tf.cast(img_tensor, tf.float32)  # 转换图片数字类型从uint8转为float32便于计算
        img_tensor = img_tensor / 255  # 图片数据归一化
        testimg = tf.expand_dims(img_tensor, 0)
        pred = model.predict(testimg)
        if np.max(pred) > 0.6:
           if np.argmax(pred) == 0:
               return 'fail'
           else:
               return 'pass'
        else:
            print('unknow')



if __name__ == '__main__':

    gpus = tf.config.list_physical_devices("GPU")
    print(gpus)
    if gpus:
        gpu0 = gpus[0]  # 如果有多个GPU,仅使用第0个GPU
        tf.config.experimental.set_memory_growth(gpu0, True)  # 设置GPU显存用量按需使用
        tf.config.set_visible_devices([gpu0], "GPU")

    model = tf.keras.models.load_model('kcEnterGame.h5')
    app.run(host="0.0.0.0", port=8987, debug=True)  # debug=True causes Restarting with stat

用flask搭建YOLOV5的服务-客户端

# -*- coding: utf-8 -*-
# @Time : 2021/12/10 18:25
# @Author : 李思
# @99U : 234695
# @File : test.py
# @Project : www
# @desc : 发送请求



import pprint
import requests
import json

DETECTION_URL = "http://localhost:5000/kc"
TEST_IMAGE = "F:/kuaiceimage/images/Screenshot_2021-11-05-16-40-22-300_com.google.android.packageinstaller.png"
image_data = open(TEST_IMAGE, "rb").read()
# response = requests.post(DETECTION_URL, files={"image": image_data}).json()
response = requests.post(DETECTION_URL, files={"image": image_data})
pprint.pprint(response.text)

# {"x": 159.5, "y": 549.0}'

用flask搭建YOLOV5的服务-服务端

# -*- coding: utf-8 -*-
# @File : www.py
# @Project : www
# @desc : 启动flask


import argparse
import json
from pathlib import Path
from flask import Flask, request
import cv2
import torch
import numpy as np
from models.experimental import attempt_load
from utils.datasets import letterbox
from utils.general import check_img_size, non_max_suppression
from utils.torch_utils import select_device


app = Flask(__name__)

DETECTION_URL = "/kc"



def loadmodel():
    save_dir, source, weights, view_img, save_txt, imgsz = \
        Path(opt.save_dir), opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size
    # 获取设备
    device = select_device(opt.device)
    # 如果设备为gpu,使用Float16
    half = device.type != 'cpu'  # half precision only supported on CUDA

    # Load model
    # 加载Float32模型,确保用户设定的输入图片分辨率能整除32(如不能则调整为能整除并返回)
    model = attempt_load(weights, map_location=device)  # load FP32 model
    imgsz = check_img_size(imgsz, s=model.stride.max())  # check img_size
    # 设置Float16
    if half:
        model.half()  # to FP16
    return model


@app.route(DETECTION_URL, methods=["POST"])
def predict():
    if not request.method == "POST":
        return

    if request.files.get("image"):
        # 获取设备
        device = select_device(opt.device)
        # 如果设备为gpu,使用Float16
        half = device.type != 'cpu'  # half precision only supported on CUDA
        # 进行一次前向推理,测试程序是否正常
        img = torch.zeros((1, 3, opt.img_size, opt.img_size), device=device)  # init img
        _ = model(img.half() if half else img) if device.type != 'cpu' else None  # run once

        image_file = request.files["image"]
        image_bytes = image_file.read()

        img = cv2.imdecode(np.array(bytearray(image_bytes), dtype='uint8'), cv2.IMREAD_UNCHANGED)

        # img = Image.open(io.BytesIO(image_bytes))
        # img.save("./static/img/tmp.png")

        # img = cv2.imread("./static/img/tmp.png")

        # Padded resize
        img = letterbox(img, new_shape=opt.img_size)[0]

        # Convert
        img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416
        img = np.ascontiguousarray(img)

        img = torch.from_numpy(img).to(device)
        # 图片也设置为Float16
        img = img.half() if half else img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        # 没有batch_size的话则在最前面添加一个轴
        if img.ndimension() == 3:
            img = img.unsqueeze(0)
        """
           前向传播 返回pred的shape是(1, num_boxes, 5+num_class)
           h,w为传入网络图片的长和宽,注意dataset在检测时使用了矩形推理,所以这里h不一定等于w
           num_boxes = h/32 * w/32 + h/16 * w/16 + h/8 * w/8
           pred[..., 0:4]为预测框坐标
           预测框坐标为xywh(中心点+宽长)格式
           pred[..., 4]为objectness置信度
           pred[..., 5:-1]为分类结果
           """
        pred = model(img, augment=opt.augment)[0]

        # Apply NMS
        # 进行NMS
        """
        pred:前向传播的输出
        conf_thres:置信度阈值
        iou_thres:iou阈值
        classes:是否只保留特定的类别
        agnostic:进行nms是否也去除不同类别之间的框
        经过nms之后,预测框格式:xywh-->xyxy(左上角右下角)
        pred是一个列表list[torch.tensor],长度为batch_size
        每一个torch.tensor的shape为(num_boxes, 6),内容为box+conf+cls
        """
        pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)

        # Process detections
        # 对每一张图片作处理
        for i, det in enumerate(pred):  # detections per image
                # 保存预测结果
                for *xyxy, conf, cls in reversed(det):
                    mcx = (int(xyxy[2]) + int(xyxy[0])) / 2
                    mcy = (int(xyxy[1]) + int(xyxy[3])) / 2
                    print(mcx, mcy)
                    return json.dumps({'x': mcx, 'y': mcy})

        return 'dddd'



if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='I:/kuaicemodel/weights/best.pt', help='model.pt path(s)')
    parser.add_argument('--source', type=str, default='F:/kuaiceimage', help='source')  # file/folder, 0 for webcam
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--save-dir', type=str, default='runs/detect', help='directory to save results')
    parser.add_argument('--name', default='', help='name to append to --save-dir: i.e. runs/{N} -> runs/{N}_{name}')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    opt = parser.parse_args()

    model = loadmodel()

    app.run(host="0.0.0.0", port=5000, debug=True)  # debug=True causes Restarting with stat

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注