Fastapi学习笔记之使用 Amazon ec2 部署图像检测模型-1
创始人
2025-05-31 21:24:34

前言

我写了一个关于 FastAPI 的简单教程,它是关于简化和理解 API 的工作原理,以及使用框架创建一个简单的 API。

该帖子得到了很好的反响,但问得最多的问题是如何在 ec2 上部署 FastAPI API,以及如何使用图像数据而不是简单的字符串、整数和浮点数作为 API 的输入。

我为此在网上进行了搜索,但我所能找到的只是一些简单的文档以及人们使用 NGINX 或 ECS 进行部署的许多不同方式。 这些对我来说似乎都不是特别伟大或完整。

因此,我尝试使用 FastAPI 文档中的一些帮助自己完成此操作。 在这篇文章中,我们将主要关注四件事:

  • 设置亚马逊实例

  • 创建用于对象检测的 FastAPI API

  • 使用 Docker 部署 FastAPI

  • 带 UI 的端到端应用程序

所以,事不宜迟,让我们开始吧。由于文档比较长,我们先从上面俩个加黑的标题开始介绍:)

1. 设置亚马逊实例

在我们开始使用 Amazon ec2 实例之前,我们需要设置一个。 您可能需要使用您的电子邮件 ID 注册并在 AWS 网站上设置付款信息。 就像单点登录一样工作。 从这里开始,我假设您有一个 AWS 账户,因此我将解释接下来的重要部分,以便您可以跟进。

  • 使用 https://us-west-2.console.aws.amazon.com/console 转到 AWS 管理控制台。

  • 在 AWS 管理控制台上,您可以选择“启动虚拟机”。 在这里,我们尝试设置将部署 FastAPI API 的机器。

(1)第一步,您需要为机器选择 AMI 模板。 我从 Ubuntu 开始选择 18.04 Ubuntu Server。

(2)在第二步中,我选择了 t2.xlarge 机器,它有 4 个 CPU 和 16GB RAM,而不是免费层,因为我想使用对象检测模型并且需要一些资源。

继续按下一步,直到到达“6。 配置安全组”选项卡。 这是这里最关键的一步。 您需要添加类型为“HTTP”且端口范围为:80 的规则。

您可以点击“Review and Launch”,最后点击“Launch”按钮来启动实例。 单击启动后,您可能需要创建一个新的密钥对。 在这里,我正在创建一个名为 fastapi 的新密钥对,并使用“下载密钥对”按钮下载它。 请妥善保管此密钥,因为每次您需要登录此特定计算机时都需要用到它。 下载密钥对后点击“Launch Instance”

您现在可以转到您的实例以查看您的实例是否已启动。 提示:查看实例状态; 它应该显示“正在运行”。

另外,这里要注意公共 DNS(IPv4) 地址和 IPv4 公共 IP。 我们将需要它来连接到这台机器。 对我来说,他们是:

Public DNS (IPv4): ec2-18-237-28-174.us-west-2.compute.amazonaws.comIPv4 Public IP: 18.237.28.174

在文件夹中运行以下命令后,您保存了 fastapi.pem 文件。 如果文件名为 fastapi.txt,您可能需要将其重命名为 fastapi.pem。

# run fist command if fastapi.txt gets downloaded.
# mv fastapi.txt fastapi.pemchmod 400 fastapi.pem
ssh -i "fastapi.pem" ubuntu@

现在我们已经启动并运行了我们的 Amazon 实例。 我们可以继续到帖子的真实部分。

2、创建用于对象检测的 FastAPI API

在我们部署 API 之前,我们需要有一个 API,对吗? 在我最近的一篇文章中,我转载一个简单的教程来理解 FastAPI 和 API 基础知识。 如果您想了解 FastAPI 基础知识,请阅读这篇文章。

因此,在这里我将尝试创建一个图像检测 API。 至于如何将Image数据传递给API? 这个想法是——什么是图像而不是字符串? 图像只是由字节组成的,我们可以将这些字节编码为字符串。 我们将使用 base64 字符串表示,这是一种将二进制数据转换为 ASCII 字符的流行方式。 并且,我们将传递此字符串表示形式以向我们的 API 提供图像。

(1)一些图像基础知识:什么是图像

那么,让我们首先看看如何将图像转换为字符串。 我们使用“rb”标志从图像文件中读取二进制数据,并使用 base64.b64encode 函数将其转换为 base64 编码数据表示。 然后我们使用 decode to utf-8 函数将基本编码数据转换为人类可读的字符。 如果它现在没有多大意义,请不要担心。 只需了解任何数据都是二进制的,我们可以使用一系列步骤将二进制数据转换为其字符串表示形式。

举个简单的例子,如果我有一个像下面这样的简单图像,我们可以使用以下方法将它转换为字符串:

import base64with open("sample_images/dog_with_ball.jpg", "rb") as image_file:base64str = base64.b64encode(image_file.read()).decode("utf-8")

在这里,我的笔记本电脑上有一个名为 dog_with_ball.png 的文件的字符串表示形式。

太好了,我们现在有了图像的字符串表示。 而且,我们可以将此字符串表示形式发送到我们的 FastAPI。 但我们还需要有一种方法从图像的字符串表示中读回图像。 毕竟,我们使用 PyTorch 和任何其他包的图像检测 API 需要有一个可以预测的图像对象,而这些方法不适用于字符串。

所以这是一种从图像的 base64 字符串创建 PIL 图像的方法。 大多数情况下,我们只是按照相同的顺序执行相反的步骤。 我们使用 .encode 编码为‘utf-8’。 然后我们使用 base64.b64decode 解码为字节。 我们使用这些字节通过 io.BytesIO 创建一个字节对象,并使用 Image.open 打开这个字节 IO 对象作为 PIL 图像,它可以很容易地用作我的 PyTorch 预测代码的输入。*** 再次简单地说,它 只是一种将 base64 图像字符串转换为实际图像的方法。***

import base64
import io
from PIL import Imagedef base64str_to_PILImage(base64str):base64_img_bytes = base64str.encode('utf-8')base64bytes = base64.b64decode(base64_img_bytes)bytesObj = io.BytesIO(base64bytes)img = Image.open(bytesObj)return img

那么这个功能有用吗? 让我们自己看看。 我们可以只使用字符串来取回图像。

(2)编写实际的 FastAPI 代码

在这里,我将使用来自 torchvision.models 的 Pytorch 预训练 fasterrcnn_resnet50_fpn 检测模型进行对象检测,该模型在 COCO 数据集上进行训练以保持代码简单,但可以使用任何模型。 如果您想使用 Pytorch 训练您的自定义图像分类或图像检测模型,您可以查看这些帖子。

下面是 FastAPI 的完整代码。 虽然看起来很长,但我们已经知道了所有的部分。 在这段代码中,我们主要执行以下步骤:

  • 使用 FastAPI() 构造函数创建我们的快速 API 应用程序。

  • 加载我们的模型和训练它的类。 我从 PyTorch 文档中获得了类列表。

  • 我们还定义了一个新类 Input ,它使用一个名为 pydantic 的库来验证我们将从 API 最终用户获得的输入数据类型。 在这里,最终用户为对象检测预测提供了 base64str 和一些分数阈值。

  • 我们添加了一个名为 base64str_to_PILImage 的函数,它按照它的名字进行操作。

  • 我们编写了一个名为 get_predictionbase64 的预测函数,它使用图像的 base64 字符串表示和阈值作为输入返回边界框和类的字典。 我们还在这个函数之上添加 @app .put(“/predict”) 来定义我们的端点。

from fastapi import FastAPI
from pydantic import BaseModel
import torchvision
from torchvision import transforms
import torch
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
from PIL import Image
import numpy as np
import cv2
import io, json
import base64app = FastAPI()# load a pre-trained Model and convert it to eval mode.
# This model loads just once when we start the API.
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
COCO_INSTANCE_CATEGORY_NAMES = ['__background__', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus','train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A', 'stop sign','parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow','elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack', 'umbrella', 'N/A', 'N/A','handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball','kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket','bottle', 'N/A', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl','banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza','donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'N/A', 'dining table','N/A', 'N/A', 'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone','microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'N/A', 'book','clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'
]
model.eval()# define the Input class
class Input(BaseModel):base64str : strthreshold : floatdef base64str_to_PILImage(base64str):base64_img_bytes = base64str.encode('utf-8')base64bytes = base64.b64decode(base64_img_bytes)bytesObj = io.BytesIO(base64bytes)img = Image.open(bytesObj)return img@app.put("/predict")
def get_predictionbase64(d:Input):'''FastAPI API will take a base 64 image as input and return a json object'''# Load the imageimg = base64str_to_PILImage(d.base64str)# Convert image to tensortransform = transforms.Compose([transforms.ToTensor()])img = transform(img)# get prediction on imagepred = model([img])pred_class = [COCO_INSTANCE_CATEGORY_NAMES[i] for i in list(pred[0]['labels'].numpy())]pred_boxes = [[(float(i[0]), float(i[1])), (float(i[2]), float(i[3]))] for i in list(pred[0]['boxes'].detach().numpy())]pred_score = list(pred[0]['scores'].detach().numpy())pred_t = [pred_score.index(x) for x in pred_score if x > d.threshold][-1]pred_boxes = pred_boxes[:pred_t+1]pred_class = pred_class[:pred_t+1]return {'boxes': pred_boxes,'classes' : pred_class}

(3)在本地测试 FastAPI 代码

在我们继续使用 AWS 之前,让我们检查一下代码是否可以在我们的本地机器上运行。 我们可以使用以下命令在笔记本电脑上启动 API:

uvicorn fastapiapp:app --reload

以上意味着您的 API 现在正在本地服务器上运行,并且 –reload 标志表示当您更改 fastapiapp.py 文件时 API 会自动更新。 这在开发和测试时非常有用,但是当您将 API 投入生产时,您应该删除这个 –reload 标志。

你应该看到类似的东西:

您现在可以尝试访问此 API 并使用 requests 模块查看它是否有效:

import requests,jsonpayload = json.dumps({"base64str": base64str,"threshold": 0.5
})response = requests.put("[http://127.0.0.1:8000/predict](http://127.0.0.1:8000/predict)",data = payload)
data_dict = response.json()

因此,我们使用 API 获得结果。 此图像包含一只狗和一个运动球。 我们还有边界框的角 1 (x1,y1) 和角 2 (x2,y2) 坐标。

(4)让我们可视化一下

我们可以在 Jupyter notebook 中可视化结果的样子:

from PIL import Image
import numpy as np
import cv2
import matplotlib.pyplot as pltdef PILImage_to_cv2(img):return np.asarray(img)def drawboundingbox(img, boxes,pred_cls, rect_th=2, text_size=1, text_th=2):img = PILImage_to_cv2(img)class_color_dict = {}#initialize some random colors for each class for better looking bounding boxesfor cat in pred_cls:class_color_dict[cat] = [random.randint(0, 255) for _ in range(3)]for i in range(len(boxes)):cv2.rectangle(img, (int(boxes[i][0][0]), int(boxes[i][0][1])),(int(boxes[i][1][0]),int(boxes[i][1][1])),color=class_color_dict[pred_cls[i]], thickness=rect_th)cv2.putText(img,pred_cls[i], (int(boxes[i][0][0]), int(boxes[i][0][1])),  cv2.FONT_HERSHEY_SIMPLEX, text_size, class_color_dict[pred_cls[i]],thickness=text_th) # Write the prediction classplt.figure(figsize=(20,30))plt.imshow(img)plt.xticks([])plt.yticks([])plt.show()img = Image.open("sample_images/dog_with_ball.jpg")
drawboundingbox(img, data_dict['boxes'], data_dict['classes'])

输出如下:

在这里你会注意到我从本地文件系统获取图像,这种行为可以被视为作弊,因为我们不想保存用户通过 Web UI 发送给我们的每个文件。 我们应该能够使用创建此图像时也必须使用的相同 base64string 对象。 正确的?

不用担心,我们也可以做到。 还记得我们的 base64str_to_PILImage 函数吗? 我们也可以使用它。

img = base64str_to_PILImage(base64str)
drawboundingbox(img, data_dict['boxes'], data_dict['classes'])

看起来不错。 我们有我们的工作 FastAPI,我们也有我们的亚马逊实例。 我们现在可以继续部署,请参考后续博客。

相关内容

热门资讯

最新!2025新势力5月销量出... 5月新势力表现如何?2025年5月的销售周期刚刚过去,不少造车新势力厂商的销量数据,已经新鲜出炉。数...
两家A股公司,收终止上市决定 又有两家A股上市公司收到股票终止上市决定,6月10日进入退市整理期。 上述自律监管决定书指出,因2...
重磅,事关教育强国,主力提前埋... 数据是个宝数据宝投资少烦恼这些产业的景气度处于上升期。《求是》杂志发表文章《加快建设教育强国》6月1...
阳光诺和“二刷”收购 80后富... 《投资者网》蔡俊时隔2年后,阳光诺和(688621.SH,下称“公司”)再拟收购同一个资产。实际上,...
买车,不安全了? 买车,不安全... 在新能源汽车市场竞争空前激烈的当下,车企、经销商习惯于采取更加激进的营销、市场策略,尤其在行业加速“...
欧佩克+同意7月再增产41.1... 为了增产惩罚超产国并争夺市场份额,欧佩克+连续第三个月大幅增产,美国页岩油生产商或首当其冲,美油一度...
经济学泰斗菲舍尔逝世:培育伯南... 当地时间6月1日,以色列央行发布声明称,世界著名经济学家、以色列央行前行长及美联储前副主席菲舍尔(S...
更名!“天府证券”来了 天府证... 【导读】宏信证券更名为天府证券中国基金报记者 吴君这家券商,历史上第二次更名。5月末,工商信息显示,...
两家A股公司,收终止上市决定 ... 又有两家A股上市公司收到股票终止上市决定,6月10日进入退市整理期。*ST鹏博(600804)公告称...
瑞幸降价迈入“6块9”时代?瑞... 说起最近几年的咖啡茶饮市场,相信每个人都不会陌生,各家咖啡茶饮企业的各种降价消息是此起彼伏,就在最近...
主次节奏:6.1黄金 - 每周... 本文每周初更新发布梳理各级别走势分析和预期主次节奏:做有品质的三方服务黄金月线图(超长线) 月线图...
超400亿资金狂涌!这类ETF... 债券ETF市场持续扩容。今年以来,债券市场表现震荡,债券类基金回报远不及预期,但这并未妨碍债券型ET...
坚定信心 行稳致远(记者手记) 侯琳良 最近一段时间,海尔集团上世纪90年代投资制作的《海尔兄弟》动画片,在多个视频平台上线高清重制...
世纪大辩论2——哈耶克与凯恩斯... 本来节后决定启动一个项目,但家里临时有事,需要陪家人去一趟北京,节后拉群的事,因此要推迟一周左右(具...
4月广州消费品市场表现强劲 1-4月,随着消费品以旧换新等促消费政策持续发力和各类会展活动陆续开展,政策相关消费快速增长,升级类...
金价,又跌了! 人民财讯5月31日电,5月30日,COMEX黄金期货收跌0.92%,报3313.1美元/盎司。 从高...
10万吨改性项目!巴斯夫、金发... 【DT新材料】获悉,6月3日,沪市主板新股海阳科技将启动申购,上市在即! 资料显示,海阳科技前身为南...
湾财周报|大事记 比亚迪驳斥“... 一周大事记(5月26日-6月1日) 头条 比亚迪驳斥! 长城“车圈恒大论”是行业警示还是危言耸听?...
通源石油跌1.96%,成交额1... 5月30日,通源石油跌1.96%,成交额1.03亿元,换手率4.40%,总市值23.54亿元。 异动...
中国邮储银行浙江分行2025校... 点这里 ↑ 老满说高考 作者 l 老满 生涯规划师l 升学顾问l 拆书家 这是 老满说高考公众号 的...
公募基金规模首次突破33万亿元... 每经记者:肖芮冬 每经编辑:叶峰 天赐良基日报第654期 一、今日基金新闻速览 1、华润元大基金贾...
湾财周报 大事记 比亚迪驳斥“... 一周大事记(5月26日-6月1日)头条比亚迪驳斥!长城“车圈恒大论”是行业警示还是危言耸听?近日,关...
EL表达式JSTL标签库 EL表达式     EL:Expression Language 表达式语言     ...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
工信部、中汽协紧急发声!汽车“... 文/刘育英新一轮汽车价格战再起。近日,工信部、中汽协纷纷发声表示反对。工业和信息化部表示,将加大对汽...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
募资39亿,全亏光了,账上不到... 关于天然气,用户的感觉是价格一直在上涨,但很奇怪,不管怎么涨,天然气企业仍然亏,还亏得一塌糊涂。这是...
资阳房产评估公司 这是(tel-15828298733)整理的信息,希望能帮助到大家 在当今社会,随着经济的发展和城...
华桥汇利(中国)投资基金管理有... 今年第一季度,美国企业利润出现大幅下降,且面临着来自关税上升的持续压力,这一局面可能会在今年进一步加...
ESG 报告合规与鉴证:全球政... 在当下全球经济格局里,ESG(环境、社会和公司治理)已然成为衡量企业可持续发展能力的关键指标。随着全...