当前位置: 首页 > news >正文

用Flask搭建简单的web模型部署服务

目录结构如下:
在这里插入图片描述

分类模型web部署

classification.py

import os
import cv2
import numpy as np
import onnxruntime
from flask import Flask, render_template, request, jsonifyapp = Flask(__name__)onnx_session = onnxruntime.InferenceSession("mobilenet_v2.onnx", providers=['CPUExecutionProvider'])input_name = []
for node in onnx_session.get_inputs():input_name.append(node.name)output_name = []
for node in onnx_session.get_outputs():output_name.append(node.name)def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])def preprocess(image):if image.shape[0] < image.shape[1]: #h<wimage = cv2.resize(image, (int(256*image.shape[1]/image.shape[0]), 256))else:image = cv2.resize(image, (256, int(256*image.shape[0]/image.shape[1])))crop_size = min(image.shape[0], image.shape[1])left = int((image.shape[1]-crop_size)/2)top = int((image.shape[0]-crop_size)/2)image_crop = image[top:top+crop_size, left:left+crop_size]image_crop = cv2.resize(image_crop, (224,224))image_crop = image_crop[:,:,::-1].transpose(2,0,1).astype(np.float32)   #BGR2RGB和HWC2CHWimage_crop[0,:] = (image_crop[0,:] - 123.675) / 58.395   image_crop[1,:] = (image_crop[1,:] - 116.28) / 57.12image_crop[2,:] = (image_crop[2,:] - 103.53) / 57.375return  np.expand_dims(image_crop, axis=0)  @app.route('/classification', methods=['POST', 'GET'])  # 添加路由
def classification():if request.method == 'POST':f = request.files['file']if not (f and allowed_file(f.filename)):return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})basepath = os.path.dirname(__file__)  # 当前文件所在路径upload_path = os.path.join(basepath, 'static/images/temp.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径f.save(upload_path)image = cv2.imread(upload_path)     tensor = preprocess(image)inputs = {}for name in input_name:inputs[name] = tensor   outputs = onnx_session.run(None, inputs)[0]label = np.argmax(outputs)score = np.exp(outputs[0][label]) / np.sum(np.exp(outputs), axis=1)return render_template('classification.html', label=label, score=score[0])return render_template('upload.html')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)

classification.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body><h1>请上传本地图片</h1><form action="" enctype='multipart/form-data' method='POST'><input type="file" name="file" style="margin-top:20px;"/><input type="submit" value="上传" class="button-new" style="margin-top:15px;"/></form><h2>图片类别为:{{label}}        置信度为:{{score}} </h2><img src="{{ url_for('static', filename= './images/temp.jpg') }}"  alt="你的图片被外星人劫持了~~"/>
</body>
</html>

运行程序,在浏览器输入http://127.0.0.1:8000/classification,效果展示:
在这里插入图片描述

检测模型web部署

detection.py

import os
import cv2
import numpy as np
import onnxruntime
from flask import Flask, render_template, request, jsonifyapp = Flask(__name__)class_names = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light','fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow','elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee','skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard','tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple','sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch','potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone','microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear','hair drier', 'toothbrush'] #coco80类别      
input_shape = (640, 640) 
score_threshold = 0.2  
nms_threshold = 0.5
confidence_threshold = 0.2   onnx_session = onnxruntime.InferenceSession("yolov5n.onnx", providers=['CPUExecutionProvider'])input_name = []
for node in onnx_session.get_inputs():input_name.append(node.name)output_name = []
for node in onnx_session.get_outputs():output_name.append(node.name)def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])def nms(boxes, scores, score_threshold, nms_threshold):x1 = boxes[:, 0]y1 = boxes[:, 1]x2 = boxes[:, 2]y2 = boxes[:, 3]areas = (y2 - y1 + 1) * (x2 - x1 + 1)keep = []index = scores.argsort()[::-1] while index.size > 0:i = index[0]keep.append(i)x11 = np.maximum(x1[i], x1[index[1:]]) y11 = np.maximum(y1[i], y1[index[1:]])x22 = np.minimum(x2[i], x2[index[1:]])y22 = np.minimum(y2[i], y2[index[1:]])w = np.maximum(0, x22 - x11 + 1)                              h = np.maximum(0, y22 - y11 + 1) overlaps = w * hious = overlaps / (areas[i] + areas[index[1:]] - overlaps)idx = np.where(ious <= nms_threshold)[0]index = index[idx + 1]return keepdef xywh2xyxy(x):y = np.copy(x)y[:, 0] = x[:, 0] - x[:, 2] / 2y[:, 1] = x[:, 1] - x[:, 3] / 2y[:, 2] = x[:, 0] + x[:, 2] / 2y[:, 3] = x[:, 1] + x[:, 3] / 2return ydef filter_box(outputs): #过滤掉无用的框    outputs = np.squeeze(outputs)outputs = outputs[outputs[..., 4] > confidence_threshold]classes_scores = outputs[..., 5:]boxes = []scores = []class_ids = []for i in range(len(classes_scores)):class_id = np.argmax(classes_scores[i])outputs[i][4] *= classes_scores[i][class_id]outputs[i][5] = class_idif outputs[i][4] > score_threshold:boxes.append(outputs[i][:6])scores.append(outputs[i][4])class_ids.append(outputs[i][5])if len(boxes) == 0 :return      boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, score_threshold, nms_threshold) output = boxes[indices]return outputdef letterbox(im, new_shape=(416, 416), color=(114, 114, 114)):# Resize and pad image while meeting stride-multiple constraintsshape = im.shape[:2]  # current shape [height, width]# Scale ratio (new / old)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])# Compute paddingnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))    dw, dh = (new_shape[1] - new_unpad[0])/2, (new_shape[0] - new_unpad[1])/2  # wh padding top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))left, right = int(round(dw - 0.1)), int(round(dw + 0.1))if shape[::-1] != new_unpad:  # resizeim = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add borderreturn imdef scale_boxes(boxes, shape): # Rescale boxes (xyxy) from input_shape to shapegain = min(input_shape[0] / shape[0], input_shape[1] / shape[1])  # gain  = old / newpad = (input_shape[1] - shape[1] * gain) / 2, (input_shape[0] - shape[0] * gain) / 2  # wh paddingboxes[..., [0, 2]] -= pad[0]  # x paddingboxes[..., [1, 3]] -= pad[1]  # y paddingboxes[..., :4] /= gainboxes[..., [0, 2]] = boxes[..., [0, 2]].clip(0, shape[1])  # x1, x2boxes[..., [1, 3]] = boxes[..., [1, 3]].clip(0, shape[0])  # y1, y2return boxesdef draw(image, box_data):box_data = scale_boxes(box_data, image.shape)boxes = box_data[...,:4].astype(np.int32) scores = box_data[...,4]classes = box_data[...,5].astype(np.int32)for box, score, cl in zip(boxes, scores, classes):top, left, right, bottom = boxcv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 1)cv2.putText(image, '{0} {1:.2f}'.format(class_names[cl], score), (top, left), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 1)def preprocess(img):input = letterbox(img, input_shape)input = input[:, :, ::-1].transpose(2, 0, 1).astype(dtype=np.float32)input = input / 255.0input = np.expand_dims(input, axis=0)return input@app.route('/detection', methods=['POST', 'GET'])  # 添加路由
def detection():if request.method == 'POST':f = request.files['file']if not (f and allowed_file(f.filename)):return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})basepath = os.path.dirname(__file__)  # 当前文件所在路径upload_path = os.path.join(basepath, 'static/images/temp.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径f.save(upload_path)image = cv2.imread(upload_path)     tensor = preprocess(image)inputs = {}for name in input_name:inputs[name] = tensor   outputs = onnx_session.run(None, inputs)[0]boxes = filter_box(outputs)if boxes is not None:draw(image, boxes)cv2.imwrite(os.path.join(basepath, 'static/images/temp.jpg'), image)return render_template('detection.html')return render_template('upload.html')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)

detection.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body><h1>请上传本地图片</h1><form action="" enctype='multipart/form-data' method='POST'><input type="file" name="file" style="margin-top:20px;"/><input type="submit" value="上传" class="button-new" style="margin-top:15px;"/></form><img src="{{ url_for('static', filename= './images/temp.jpg') }}"  alt="你的图片被外星人劫持了~~"/>
</body>
</html>

运行程序,在浏览器输入http://127.0.0.1:8000/detection,效果展示:
在这里插入图片描述

相关文章:

用Flask搭建简单的web模型部署服务

目录结构如下&#xff1a; 分类模型web部署 classification.py import os import cv2 import numpy as np import onnxruntime from flask import Flask, render_template, request, jsonifyapp Flask(__name__)onnx_session onnxruntime.InferenceSession("mobilen…...

PCL 点云匹配 3 之 (非线性迭代点云匹配)lM-ICP

一、IM迭代法 PCL IterativeClosestPointNonLinear 非线性L-M迭代法-CSDN博客 Matlab 非线性迭代法&#xff08;3&#xff09;阻尼牛顿法 L-M-CSDN博客 MATLAB实现最小二乘法_matlab最小二乘法-CSDN博客...

【C语言】SCU安全项目2-BufBomb

目录 关键代码解读&#xff1a; getxs() getbuf() test() 核心思路 具体操作1 具体操作2 前段时间忙于强网杯、英语4级和一些其他支线&#xff0c;有点摸不清头绪了&#xff0c;特别是qwb只有一个输出&#xff0c;太过坐牢&#xff0c;决定这个安全项目做完后就继续投身…...

C++第一讲之初入C++

注&#xff1a;本文是对于学完C语言再学C同学的讲解&#xff0c;主要补充C与C语言不同之处&#xff0c;如果你没学过C语言&#xff0c;不建议观看本文。 一.C简介 我们都知道C语言是过程性语言&#xff08;强调的是实现过程&#xff09;&#xff0c;即对计算机语言要处理的两…...

如何实现公网访问本地内网搭建的WBO白板远程协作办公【内网穿透】

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 前言1. 部署WBO白板2. 本地访问WBO白板3. Linux 安装cp…...

js知识点1:防抖节流

js知识点1&#xff1a;防抖节流 防抖节流 防抖节流&#xff0c;本质上是优化高频率执行代码的一种手段 定义&#xff1a; 防抖: n 秒后再执行该事件&#xff0c;若在 n 秒内被重复触发&#xff0c;则重新计时 节流: n 秒内只运行一次&#xff0c;若在 n 秒内重复触发&#xff0…...

虚拟机下Ubuntu上网设置

文章目录 一、虚拟机上网的两种方式1.1 NAT模式&#xff08;Network Address Translation&#xff09;1.2 桥接模式&#xff08;Bridge Mode&#xff09;1.3 简介 二、实际配置2.1 NAT模式配置2.2 桥接模式配置 之前跟着博客配了好几个也没用&#xff0c;后来自己慢慢模式实践测…...

Unity3d C#利用Editor编辑器拓展实现配置UI背景样式一键设置UI背景样式功能(含源码)

前言 在开发UI滚动列表的时候&#xff0c;经常会有每项的背景图不统一的情况&#xff0c;会间隔重复的情况居多。这种情况下&#xff0c;手动去设置间隔一行的背景图或者颜色是比较麻烦的。在此背景下&#xff0c;笔者尝试写个小工具&#xff0c;在搭建UI时配置一下循环背景的…...

【微服务】服务间调用

当我们的应用从一个大单体拆分成多个微服务之后,服务间调用有多少种方式?服务间调用如果出现超时,如果避免雪崩,即如何做限流熔断机制,原理是什么? 服务间调用方式 OpenFeign 使用Feign进行服务间调用,我们会在启动类加@EnableFeignClients启用。 package org.sprin…...

一句话分清C/C++声明和定义

定义告诉编译器在在哪个位置存储变量&#xff0c;声明没有 声明&#xff1a;告诉编译器&#xff0c;变量类型和名字 定义&#xff1a;告诉编译器变量存储的位置。 举例子 int i; // 这是声明定义。声明&#xff1a;告诉编译器变量类型int,变量名字i&#xff0c; // 定义&…...

《哥德尔证明》阅读笔记——初等命题逻辑的一致性证明过程

前言 前两节主要阐述了公理系统的发展历史&#xff0c;一致性问题的提出&#xff0c;以及希尔伯特的洞见&#xff0c;本节将给出哥德尔证明所需的最后一次具体背景阐述&#xff0c;包含两个问题&#xff1a;一是罗素所著的《数学原理》是为何而写&#xff1f;二是从数学原理中…...

迪文屏开发保姆级教程—弹出键盘录入ASCII字符

本篇文章主要介绍了在DGBUS平台上使用文本录入键盘录入ASCII字符&#xff0c;数字和字母的教程。 文本录入键盘支持录入ASCII字符&#xff0c;数字和字母。 官方开发指南PDF&#xff1a;&#xff08;不方便下载的私聊我发给你&#xff09; https://download.csdn.net/download…...

Java,处理字符串的案例()

场景 为了得到一个都是英雄名字的字符数组&#xff0c;需要对如下字符串进行处理 疾风剑豪&#xff0c;影流之主&#xff0c;封魔剑魂&#xff0c;暗裔剑魔&#xff0c;无极剑圣&#xff0c;无双剑姬&#xff0c;武器大师&#xff0c;德邦总管&#xff0c;蛮族之王&#xff0…...

微信小程序更新机制

1/同步更新 1、定期检查更新时&#xff1b; 2、长期未使用&#xff0c;首次进入会同步更新&#xff0c;但在弱网或者下载新版本失败的情况下&#xff0c;还会使用旧版本。 2/异步更新&#xff1a; 启动时异步更新 3/开发者手动触发更新 在启动时异步更新的情况下&#xff0c;…...

CentOS 7 部署 Nacos-2.3.0 (单机版)

CentOS 7 部署 Nacos-2.3.0 &#xff08;单机版&#xff09; 1. 下载 Nacos 安装包 历史版本&#xff1a;https://github.com/alibaba/nacos/releases/ 我选的是 2.3.0 版本&#xff0c;https://github.com/alibaba/nacos/releases/download/2.3.0/nacos-server-2.3.0.tar.g…...

Springboot优雅实现对接口返回统一封装

前端在调用后端接口时往往不同的接口返回的数据是不一样的&#xff0c;但是通常我们会与前端约定一个固定的返回格式&#xff0c;通过固定的格式告诉他们什么时候接口是返回成功&#xff0c;什么时候返回失败&#xff0c;返回成功后他们如何拿到接口返回的数据去渲染前端页面。…...

Kafka 安装与部署

目录 Kafka 下载 &#xff08;1&#xff09;将 kafka_2.11-2.4.1.tgz 上传至 /opt/software/ &#xff08;2&#xff09;解压安装包至 /opt/module/ [huweihadoop101 ~]$ cd /opt/software/ [huweihadoop101 software]$ tar -zxvf kafka_2.11-2.4.1.tgz -C ../module/&#…...

计算 N*4*4 位姿形状的逆变换,在N*3*4位姿后补充 [0,0,0,1]

针对 [N,4,4] shape 的 poses&#xff0c;函数 ComputeInversePoses 返回 相同 shape&#xff0c;但是每个 pose 都是前面的 逆 pose。 针对 [N,3,4] shape 的 poses&#xff0c;函数 AddIdentityToPoses 返回 在每个 [3,4] pose下加上 [0,0,0,1] 后的pose&#xff0c;返回的…...

人工智能可以战胜人类智慧大脑么?

引言 在当今快速发展的科技时代&#xff0c;人工智能的进步日新月异&#xff0c;引发了一场深刻的讨论&#xff1a;能否有一天&#xff0c;人工智能能够超越甚至战胜人类智慧&#xff1f;这个问题涉及到人类认知的广泛领域&#xff0c;牵涉到人类思维的深层次特质以及AI技术在…...

【数据结构和算法】 K 和数对的最大数目

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一&#xff1a;双指针排序 三、代码 3.1 方法一&#xff1a;双指针排序 3.2 方法二&#xff1…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...