Python进阶-部署Flask项目(以TensorFlow图像识别项目WSGI方式启动为例)

本文详细介绍了如何通过WSGI方式部署一个基于TensorFlow图像识别的Flask项目。首先简要介绍了Flask框架的基本概念及其特点,其次详细阐述了Flask项目的部署流程,涵盖了服务器环境配置、Flask应用的创建与测试、WSGI服务器的安装与配置等内容。本文旨在帮助读者掌握Flask项目的部署方法,解决在部署过程中可能遇到的问题,确保项目能够稳定高效地运行。

一、Flask简介

Flask是一个轻量级的Web应用框架,由Python语言编写。它是基于Werkzeug WSGI工具包和Jinja2模板引擎的,并且采用BSD许可证。Flask的设计哲学是“微核”,也就是说其核心保持简洁,功能通过扩展实现。这使得Flask非常灵活,能够满足从小型单一页面应用到大型复杂项目的不同需求。

Flask的主要特点包括:

  1. 轻量级和灵活:Flask仅提供核心功能,开发者可以根据需要引入各种扩展。
  2. 易于学习和使用:Flask的API设计非常简洁明了,即使是初学者也能快速上手。
  3. 强大的扩展能力:Flask的生态系统中有许多可用的扩展,可以轻松添加数据库、表单验证、用户认证等功能。
  4. 社区支持:Flask拥有活跃的社区,大量的教程和文档可以帮助开发者解决问题。

二、Flask项目部署流程

1. 准备工作

在开始部署Flask项目之前,需要完成以下准备工作:

① 服务器安装Anaconda

Anaconda是一个用于科学计算的Python发行版,支持多种数据科学包的快速安装。它还包含了Conda,这是一种包管理器和环境管理器,能够轻松创建和管理不同的Python环境。

首先,下载并安装Anaconda。可以从Anaconda官网下载适用于Windows的安装包。安装过程非常简单,按照提示进行即可。

② Anaconda创建Python环境

安装完成后,使用Conda创建一个新的Python环境。这可以帮助你隔离项目的依赖,确保环境的一致性。打开终端(或命令提示符),输入以下命令创建一个名为opencv的环境,并指定Python版本:

conda create -n opencv python=3.8

创建完成后,激活这个环境:

conda activate opencv

在这里插入图片描述

③ Anaconda环境安装相关包

在激活的环境中,安装Flask、Flask-CORS、TensorFlow、scikit-learn和OpenCV等必要的包:

conda install flask flask-cors tensorflow scikit-learn opencv

这些包包含了构建和运行Flask应用及其依赖的所有工具。

2. 创建Flask应用

在本地编写并测试Flask应用代码。以下是一个简单的Flask应用示例,它使用TensorFlow的MobileNetV2模型进行图像分类和相似度计算:

from flask import Flask, request, jsonify
from flask_cors import CORS
import numpy as np
import cv2
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image
from sklearn.metrics.pairwise import cosine_similarityapp = Flask(__name__)
CORS(app)# 加载预训练的MobileNetV2模型
model = MobileNetV2(weights='imagenet', include_top=True)def classify_image(img):img = cv2.resize(img, (224, 224))  # MobileNetV2的输入尺寸为224x224x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)preds = model.predict(x)return decode_predictions(preds, top=1)[0][0][1], model.predict(x)  # 返回类别名称和特征向量def calculate_similarity(feature1, feature2):return cosine_similarity(feature1, feature2)[0][0]@app.route('/compare', methods=['POST'])
def compare_images():file1 = request.files['image1']file2 = request.files['image2']npimg1 = np.frombuffer(file1.read(), np.uint8)npimg2 = np.frombuffer(file2.read(), np.uint8)img1 = cv2.imdecode(npimg1, cv2.IMREAD_COLOR)img2 = cv2.imdecode(npimg2, cv2.IMREAD_COLOR)# 分类和特征提取class1, feature1 = classify_image(img1)class2, feature2 = classify_image(img2)if class1 != class2:similarity = 0.0risk_level = "低"intervention = "否"else:similarity = calculate_similarity(feature1, feature2)risk_level = "高" if similarity > 0.8 else "中" if similarity > 0.5 else "低"intervention = "是" if similarity > 0.8 else "否"return jsonify({'similarity': f'{similarity * 100:.2f}%','risk_level': risk_level,'intervention': intervention,'class1': class1,'class2': class2})if __name__ == '__main__':app.run(debug=True)

在确保代码在本地运行正常。

3、本地运行Flask服务器

在本地Anaconda中启动opencv环境的终端,运行以下命令启动Flask服务器:

python app.py

在这里插入图片描述
服务器启动后,将会监听在本地的5000端口。

① 页面前端代码实现

创建一个HTML文件(test.html),实现图片上传和结果展示功能,全部代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>图片对比</title><style>body {font-family: Arial, sans-serif;display: flex;flex-direction: column;align-items: center;margin: 0;padding: 20px;}.container {display: flex;justify-content: space-between;width: 80%;margin-bottom: 20px;}.image-box {width: 45%;border: 2px dashed #ccc;padding: 10px;text-align: center;position: relative;}.image-box img {max-width: 100%;max-height: 200px;display: none;}.image-box input {display: none;}.upload-btn {cursor: pointer;color: #007BFF;text-decoration: underline;}.loading-bar {width: 80%;height: 20px;background-color: #f3f3f3;border: 1px solid #ccc;margin-top: 10px;display: none;position: relative;}.loading-bar div {width: 0;height: 100%;background-color: #4caf50;position: absolute;animation: loading 5s linear forwards;}@keyframes loading {to {width: 100%;}}.result {display: none;margin-top: 20px;}</style>
</head>
<body><h1>图片对比</h1><div class="container"><div class="image-box" id="box1"><label for="upload1" class="upload-btn">上传图片</label><input type="file" id="upload1" accept="image/*"><img id="image1" alt="左边文本抓取图片"></div><div class="image-box" id="box2"><label for="upload2" class="upload-btn">上传图片</label><input type="file" id="upload2" accept="image/*"><img id="image2" alt="右边文本数据库图片"></div></div><button id="compare-btn">人工智能对比</button><div class="loading-bar" id="loading-bar"><div></div></div><div class="result" id="result"><p>相似百分比: <span id="similarity">0%</span></p><p>相似度: <span id="risk-level"></span></p><p>相同个体推测: <span id="intervention"></span></p><p>1种类: <span id="class1">-</span></p><p>2种类: <span id="class2">-</span></p></div><script>document.getElementById('upload1').addEventListener('change', function(event) {loadImage(event.target.files[0], 'image1', 'box1');});document.getElementById('upload2').addEventListener('change', function(event) {loadImage(event.target.files[0], 'image2', 'box2');});function loadImage(file, imgId, boxId) {const reader = new FileReader();reader.onload = function(e) {const img = document.getElementById(imgId);img.src = e.target.result;img.style.display = 'block';document.querySelector(`#${boxId} .upload-btn`).style.display = 'none';}reader.readAsDataURL(file);}document.getElementById('compare-btn').addEventListener('click', function() {const loadingBar = document.getElementById('loading-bar');const result = document.getElementById('result');const image1 = document.getElementById('upload1').files[0];const image2 = document.getElementById('upload2').files[0];if (!image1 || !image2) {alert('请上传两张图片进行对比');return;}const formData = new FormData();formData.append('image1', image1);formData.append('image2', image2);loadingBar.style.display = 'block';result.style.display = 'none';fetch('http://localhost:5000/compare', {method: 'POST',body: formData}).then(response => response.json()).then(data => {loadingBar.style.display = 'none';result.style.display = 'block';document.getElementById('similarity').innerText = data.similarity;document.getElementById('risk-level').innerText = data.risk_level;document.getElementById('intervention').innerText = data.intervention;document.getElementById('class1').innerText = data.class1;document.getElementById('class2').innerText = data.class2;}).catch(error => {loadingBar.style.display = 'none';alert('对比过程中发生错误,请重试');console.error('Error:', error);});});</script>
</body>
</html>

② 运行网页

双击运行,刚刚创建的test.html文件,效果如图:
在这里插入图片描述
上传左右图片,比较两只相同品种的狗的相似度:
在这里插入图片描述

可以看到系统识别出了两只狗的种类相同,相似比也高达75.2%,但因为没有达到我们设置的80%的阈值,所以判断非同一个体。当然,这里的80%非常牵强,实际操作中难免误差较大。由于本文算法使用的是MobileNetV2预训练模型,并没有根据实际应用场景大量训练和调参,所以如果投入应用,仍需重新训练并根据实际效果定义阈值。

确认本地运行正常,接下来就可以进行部署了。

4. 安装Waitress服务器

Waitress是一个Python WSGI服务器,适用于在生产环境中部署Flask应用。它简单易用,适合部署中小型应用。使用pip安装Waitress:

pip install waitress

在这里插入图片描述

5. 修改代码以使用Waitress

将Flask应用代码保存为 compare.py,并确保在本地测试通过。然后创建一个批处理文件 start.cmd,内容如下:

@echo off
python -m waitress --listen=*:8000 compare:app
pause

确保 compare.py 文件中的Flask应用对象名为 app,例如:

from flask import Flask, request, jsonify
from flask_cors import CORS
import numpy as np
import cv2
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image
from sklearn.metrics.pairwise import cosine_similarityapp = Flask(__name__)
CORS(app)# 加载预训练的MobileNetV2模型
model = MobileNetV2(weights='imagenet', include_top=True)def classify_image(img):img = cv2.resize(img, (224, 224))  # MobileNetV2的输入尺寸为224x224x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)preds = model.predict(x)return decode_predictions(preds, top=1)[0][0][1], model.predict(x)  # 返回类别名称和特征向量def calculate_similarity(feature1, feature2):return cosine_similarity(feature1, feature2)[0][0]@app.route('/compare', methods=['POST'])
def compare_images():file1 = request.files['image1']file2 = request.files['image2']npimg1 = np.frombuffer(file1.read(), np.uint8)npimg2 = np.frombuffer(file2.read(), np.uint8)img1 = cv2.imdecode(npimg1, cv2.IMREAD_COLOR)img2 = cv2.imdecode(npimg2, cv2.IMREAD_COLOR)# 分类和特征提取class1, feature1 = classify_image(img1)class2, feature2 = classify_image(img2)if class1 != class2:similarity = 0.0risk_level = "低"intervention = "否"else:similarity = calculate_similarity(feature1, feature2)risk_level = "高" if similarity > 0.8 else "中" if similarity > 0.5 else "低"intervention = "是" if similarity > 0.8 else "否"return jsonify({'similarity': f'{similarity * 100:.2f}%','risk_level': risk_level,'intervention': intervention,'class1': class1,'class2': class2})

6. 运行启动

配置WSGI启动:

python -m waitress --listen=*:5000 compare:app

在这里插入图片描述

你可以通过访问 http://localhost:5000 来测试你的应用。

然后给5000端口配置安全组/防火墙,实现通过公网访问。


三、Flask项目部署总结

本文详细介绍了如何通过WSGI方式部署一个基于TensorFlow图像识别的Flask项目。从安装和配置Anaconda环境,到编写和测试Flask应用,再到安装和配置WSGI服务器,我们覆盖了部署过程中的每一个步骤。这些步骤帮助确保你的Flask应用能够稳定高效地运行,并且在生产环境中易于维护和扩展。

通过遵循这些步骤,你可以确保你的Flask应用在各种环境中都能够正常运行,避免了在部署过程中可能遇到的许多常见问题。同时,这种方式也为你提供了一种标准化的部署流程,使得以后部署新的Flask项目变得更加简单和高效。希望本文对你的Flask开发和部署之旅有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/25517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA-LeetCode 热题 100 第56.合并区间

思路&#xff1a; class Solution {public int[][] merge(int[][] intervals) {if(intervals.length < 1) return intervals;List<int[]> res new ArrayList<>();Arrays.sort(intervals, (o1,o2) -> o1[0] - o2[0]);for(int[] interval : intervals){if(res…

【嵌入式】波特率9600,发送8个字节需要多少时间,如何计算?

问题&#xff1a; 波特率9600&#xff0c;发送 01 03 00 00 00 04 44 09 (8字节) 需要多少时间&#xff0c;如何计算&#xff1f; 在计算发送数据的时间时&#xff0c;首先要考虑波特率以及每个字符的数据格式。对于波特率9600和标准的UART数据格式&#xff08;1个起始位&…

AIRNet模型使用与代码分析(All-In-One Image Restoration Network)

AIRNet提出了一种较为简易的pipeline&#xff0c;以单一网络结构应对多种任务需求&#xff08;不同类型&#xff0c;不同程度&#xff09;。但在效果上看&#xff0c;ALL-In-One是不如One-By-One的&#xff0c;且本文方法的亮点是batch内选择patch进行对比学习。在与sota对比上…

JAVA-学习-2

一、类 1、类的定义 把相似的对象划分了一个类。 类指的就是一种模板&#xff0c;定义了一种特定类型的所有对象的属性和行为 在一个.java的问题件中&#xff0c;可以有多个class&#xff0c;但是智能有一个class是用public的class。被声明的public的class&#xff0c;必须和文…

Pytorch 实现目标检测一(Pytorch 23)

一 目标检测和边界框 在图像分类任务中&#xff0c;我们假设图像中只有一个主要物体对象&#xff0c;我们只关注如何识别其类别。然而&#xff0c;很多时候图像里有多个我们感兴趣的目标&#xff0c;我们不仅想知 道它们的类别&#xff0c;还想得到它们在图像中的具体位置。在…

【前端】响应式布局笔记——自适应布局

自适应布局 自适应布局是不同设备对应不同的html(局部自适应)&#xff0c;通过判断设备的类型或控制局部的变化。 1、获取设备是移动端还是pc端 // 获取设备的信息let userAgent navigator.userAgent.toLowerCase();// 使用正则表达式来判断类型let device /ipad|iphone|m…

数据并非都是正态分布:三种常见的统计分布及其应用

你有没有过这样的经历&#xff1f;使用一款减肥app&#xff0c;通过它的图表来监控自己的体重变化&#xff0c;并预测何时能达到理想体重。这款app预测我需要八年时间才能恢复到大学时的体重&#xff0c;这种不切实际的预测是因为应用使用了简单的线性模型来进行体重预测。这个…

服务部署:.NET项目使用Docker构建镜像与部署

前提条件 安装Docker&#xff1a;确保你的Linux系统上已经安装了Docker。如果没有&#xff0c;请参考官方文档进行安装。 步骤一&#xff1a;准备项目文件 将你的.NET项目从Windows系统复制到Linux系统。你可以使用Git、SCP等工具来完成这个操作。如何是使用virtualbox虚拟电…

国产操作系统上给virtualbox中win7虚拟机安装增强工具 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上给virtualbox中win7虚拟机安装增强工具 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产操作系统上给win7虚拟机安装virtualbox增强工具的文章。VirtualBox增强工具&#xff08;Guest Additions&a…

Liunx环境下redis主从集群搭建(保姆级教学)02

Redis在linux下的主从集群配置 本次演示使用三个节点实例一个主节点&#xff0c;两个从节点&#xff1a;7000端口&#xff08;主&#xff09;&#xff0c;7001端口&#xff08;从&#xff09;&#xff0c;7002端口&#xff08;从&#xff09;&#xff1b; 主节点负责写数据&a…

Rust-02-变量与可变性

在Rust中&#xff0c;变量和可变性是两个重要的概念。 变量&#xff1a;变量是用于存储数据的标识符。在Rust中&#xff0c;变量需要声明其类型&#xff0c;例如&#xff1a; let x: i32 5; // 声明一个名为x的变量&#xff0c;类型为i32&#xff08;整数&#xff09;&#…

安装MySQL Sample Database

本文安装的示例数据库为官方的Employees Sample Database。 操作过程参考其安装部分。 在安装前&#xff0c;MySQL已安装完成&#xff0c;环境为Linux。 克隆github项目&#xff1a; $ git clone https://github.com/datacharmer/test_db.git Cloning into test_db... remo…

【西瓜书】6.支持向量机

目录&#xff1a; 1.分类问题SVM 1.1.线性可分 1.2.非线性可分——核函数 2.回归问题SVR 3.软间隔——松弛变量 3.1.分类问题&#xff1a;0/1损失函数、hinge损失、指数损失、对率损失 3.2.回归问题&#xff1a;不敏感损失函数、平方 4.正则化

计算机组成原理之指令格式

1、指令的定义 零地址指令&#xff1a; 1、不需要操作数&#xff0c;如空操作、停机、关中断等指令。 2、堆栈计算机&#xff0c;两个操作数隐藏在栈顶和此栈顶&#xff0c;取两个操作数&#xff0c;并运算的结果后重新压回栈顶。 一地址指令&#xff1a; 二、三地址指令 四…

配置免密登录秘钥报错

移除秘钥&#xff0c;执行 ssh-keygen -R cdh2即可 参考&#xff1a;ECDSA主机密钥已更改,您已请求严格检查。 - 简书

Python爬虫入门与登录验证自动化思路

1、pytyon爬虫 1.1、爬虫简介 Python爬虫是使用Python编写的程序&#xff0c;可以自动访问网页并提取其中的信息。爬虫可以模拟浏览器的行为&#xff0c;自动点击链接、填写表单、进行登录等操作&#xff0c;从而获取网页中的数据。 使用Python编写爬虫的好处是&#xff0c;…

【数据结构】十二、八种常用的排序算法讲解及代码分享

目录 一、插入排序 1)算法思想 2&#xff09;代码 二、希尔排序 1&#xff09;算法思想 2&#xff09;代码 三、选择排序 1&#xff09;算法思想 2&#xff09;代码 四、堆排序 1&#xff09;什么是最大堆 2&#xff09;如何创建最大堆 3&#xff09;算法思想 4&a…

C# Excel操作类EPPlus

摘要 EPPlus 是一个流行的用于操作 Excel 文件的开源库&#xff0c;适用于 C# 和 .NET 环境。它提供了丰富的功能&#xff0c;能够轻松地读取、写入和格式化 Excel 文件&#xff0c;使得在 C# 中进行 Excel 文件处理变得更加简单和高效。EPPlus 不需要安装 Microsoft Office 或…

知乎网站只让知乎用户看文章,普通人看不了

知乎默认不显示全部文章&#xff0c;需要点击展开阅读全文 然而点击后却要登录&#xff0c;这意味着普通人看不了博主写的文章&#xff0c;只有成为知乎用户才有权力查看文章。我想这不是知乎创作者希望的情况&#xff0c;他们写文章肯定是希望所有人都能看到。 这个网站篡改…

应用商店如何检测在架应用内容是否违规?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…