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

本文主要是介绍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开发和部署之旅有所帮助。

这篇关于Python进阶-部署Flask项目(以TensorFlow图像识别项目WSGI方式启动为例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1046603

相关文章

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函