将获取pose 服务拆分为两个服务

简单拆分

要将该代码拆分为两个服务,我们需要创建两个FastAPI应用。第一个服务(我们可以称之为ImageCaptureService)将负责捕获视频流中的图像,并将图像数据发送到第二个服务(我们可以称之为PoseEstimationService)。第二个服务将接收图像数据,使用MediaPipe处理图像以获取姿态数据,并将结果返回给客户端。
以下是拆分后的两个服务的基本结构:

ImageCaptureService

from fastapi import FastAPI, HTTPException
import cv2
app = FastAPI()
# 初始化摄像头
cap = cv2.VideoCapture("q888.mp4")
@app.get("/image")
def get_image():
    # 从摄像头读取一帧
    success, image = cap.read()
    if not success:
        raise HTTPException(status_code=500, detail="Failed to capture image")
    # 将图像转换为JPEG格式以进行传输
    ret, buffer = cv2.imencode('.jpg', image)
    image_data = buffer.tobytes()
    return {"image_data": image_data}
if __name__ == "__main__":
    # 运行服务,这里只是示例,实际部署时需要根据实际情况配置
    uvicorn.run(app, host="0.0.0.0", port=8001)

PoseEstimationService

from fastapi import FastAPI, HTTPException
import cv2
import mediapipe as mp
from pydantic import BaseModel
import requests
app = FastAPI()
# 创建一个模型来序列化姿态数据
class PoseData(BaseModel):
    landmarks: list
# 初始化MediaPipe的姿态估计模型
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()
@app.post("/pose")
def get_pose(image_data: bytes):
    # 将接收到的图像数据转换为图像
    image = cv2.imdecode(np.frombuffer(image_data, np.uint8), cv2.IMREAD_COLOR)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 处理图像以获取姿态数据
    results = pose.process(image)
    # 如果没有检测到姿态,返回错误
    if not results.pose_landmarks:
        raise HTTPException(status_code=404, detail="No pose detected")
    # 获取所有地标的位置和ID
    landmarks = []
    for landmark in results.pose_landmarks.landmark:
        landmarks.append({
            'x': landmark.x,
            'y': landmark.y,
            'z': landmark.z,
            'visibility': landmark.visibility
        })
    # 返回姿态数据
    return PoseData(landmarks=landmarks)
if __name__ == "__main__":
    # 运行服务,这里只是示例,实际部署时需要根据实际情况配置
    uvicorn.run(app, host="0.0.0.0", port=8002)

请注意,为了实现两个服务之间的通信,ImageCaptureService需要发送HTTP请求到PoseEstimationService。这可以通过requests库实现,但是在上述代码中,为了简洁起见,我没有包含这部分代码。以下是如何在ImageCaptureService中发送请求到PoseEstimationService的示例:

# 在ImageCaptureService中
@app.get("/pose")
def get_pose():
    response = requests.get("http://poseestimationservice:8002/image")
    if response.status_code == 200:
        image_data = response.json()['image_data']
        # 发送图像数据到PoseEstimationService
        pose_response = requests.post("http://poseestimationservice:8002/pose", json={"image_data": image_data})
        return pose_response.json()
    else:
        raise HTTPException(status_code=500, detail="Failed to get image from PoseEstimationService")

这里需要注意的是,服务之间的通信应该使用服务名作为主机名,而不是IP地址,这通常在容器化部署(如Kubernetes)中使用服务发现机制来实现。此外,requests库通常不用于在FastAPI应用内部进行异步HTTP请求,但在本例中为了简单起见,我们使用它来展示如何发送请求。在生产环境中,应该使用异步HTTP客户端,如httpx

同时并行

要让get_pose函数同时异步请求多个get_pose_data函数,你可以使用asyncio.gather来并发运行多个协程。以下是如何修改get_pose函数以并发执行多个get_pose_data请求的示例:

from fastapi import FastAPI, HTTPException
import cv2
import numpy as np
import asyncio
import httpx
app = FastAPI()
# 初始化摄像头
cap = cv2.VideoCapture("q888.mp4")
# 异步函数,用于获取姿态数据
async def get_pose_data(image_data: bytes) -> Any:
    async with httpx.AsyncClient() as client:
        response = await client.post("http://poseestimationservice:8002/pose", json={"image_data": image_data})
        if response.status_code == 200:
            return response.json()
        else:
            raise HTTPException(status_code=500, detail="Failed to get pose data from PoseEstimationService")
@app.get("/poses", response_model=list)
async def get_poses():
    # 获取多个图像数据
    image_data_list = []
    for _ in range(5):  # 假设我们同时处理5个图像
        image_data = get_image()
        image_data_list.append(image_data)
    # 使用 asyncio.gather 并发执行多个 get_pose_data 协程
    pose_data_tasks = [get_pose_data(image_data) for image_data in image_data_list]
    pose_data_list = await asyncio.gather(*pose_data_tasks)
    return pose_data_list
def get_image():
    # 从摄像头读取一帧
    success, image = cap.read()
    if not success:
        raise HTTPException(status_code=500, detail="Failed to capture image")
    # 将图像转换为JPEG格式以进行传输
    ret, buffer = cv2.imencode('.jpg', image)
    image_data = buffer.tobytes()
    return image_data
if __name__ == "__main__":
    # 运行服务,这里只是示例,实际部署时需要根据实际情况配置
    uvicorn.run(app, host="0.0.0.0", port=8001)

在这个示例中,get_poses函数现在获取多个图像数据(这里假设5个),并为每个图像数据创建一个get_pose_data协程。然后,使用asyncio.gather来并发执行这些协程。asyncio.gather将等待所有协程完成,并返回它们的返回值列表。
这样,get_poses函数将同时异步地请求多个get_pose_data,并且当所有请求都完成后,将返回一个包含所有结果的列表。
请注意,get_image函数是同步的,因此在这个例子中,我们连续调用它5次来获取5个图像。在实际应用中,你可能希望以某种异步方式获取图像,以避免阻塞事件循环。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 04:30:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 04:30:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 04:30:04       58 阅读
  4. Python语言-面向对象

    2024-07-14 04:30:04       69 阅读

热门阅读

  1. TCP/IP 原理、实现方式与优缺点

    2024-07-14 04:30:04       24 阅读
  2. 知识图谱数据库基本知识

    2024-07-14 04:30:04       16 阅读
  3. 【“码上”大模型简介】

    2024-07-14 04:30:04       23 阅读
  4. 在Spring Boot项目中集成分布式追踪系统

    2024-07-14 04:30:04       29 阅读
  5. 小程序中用于跳转页面的5个api是什么和区别

    2024-07-14 04:30:04       23 阅读
  6. GitHub每日最火火火项目(7.13)

    2024-07-14 04:30:04       20 阅读
  7. QTextEdit 设置宽度

    2024-07-14 04:30:04       25 阅读
  8. redis 夺命21问

    2024-07-14 04:30:04       20 阅读
  9. Gitlab介绍

    2024-07-14 04:30:04       17 阅读
  10. 变分法笔记2

    2024-07-14 04:30:04       21 阅读
  11. 爬虫:Sentry-Span参数逆向

    2024-07-14 04:30:04       20 阅读
  12. android 嵌套webview,软键盘遮挡输入框

    2024-07-14 04:30:04       23 阅读