AI 模型 - 服务部署 (FastDeploy 及其 VisualDL(可视化部署))-- 吸烟检测(目标检测)
清汉 2024-08-09 17:31:03 阅读 100
FastDeploy 及其 VisualDL(可视化部署)
1. Docker 安装1.1 容器内操作
2. VisualDL 可视化部署2.1 PPYOLOE 模型,部署示例 -- 吸烟检测
3. 远程调用3.1 Java 调用 - HTTP3.2 Python 调用 - HTTP3.3 Python 调用 - GRPC3.4 调用成功
1. Docker 安装
CPU版本
docker-compose.yml
<code>version: '4.0'
services:
paddle_serving_cpu:
image: registry.baidubce.com/paddlepaddle/fastdeploy:1.0.7-cpu-only-21.10
container_name: fastdeploy
ports:
- 9393:8080
command: bash
tty: true
working_dir: /root
# 挂载目录
volumes:
- /var/data/FastDeploy/root:/root
1.1 容器内操作
安装 VisualDL 2.5.0 ,此版本界面如下。
注意:不同版本之间界面会有差异功能也有差异。
python -m pip install visualdl==2.5.0
git 示例
<code>git clone https://github.com/PaddlePaddle/FastDeploy.git
从指定目录启动,FastDeploy 项目下的 examples 目录
cd FastDeploy/examples
visualdl --host 0.0.0.0 --port 8080
2. VisualDL 可视化部署
2.1 PPYOLOE 模型,部署示例 – 吸烟检测
载入模型库
注意:这里的只是提供调用模型的结构,如前处理、后处理等…
FastDeploy/examples/vision/detection/paddledetection/serving/models
将训练好的模型,按照以下规则分别放入文件夹。
如果没有自己训练的模型也可以下载一个预训练模型-吸烟
目录 | 文件 | 备注 |
---|---|---|
models/preprocess/1 | infer_cfg.yml | 配置文件 |
models/runtime/1 | model.pdmodel | 模型 |
models/runtime/1 | model.pdiparams |
将ppdet和runtime目录下的ppyoloe配置文件重命名成标准的config名字
<code>cp models/ppdet/ppyoloe_config.pbtxt models/ppdet/config.pbtxt
cp models/runtime/ppyoloe_runtime_config.pbtxt models/runtime/config.pbtxt
# 注意: 由于mask_rcnn模型多一个输出,需要将后处理目录(models/postprocess)中的mask_config.pbtxt重命名为config.pbtxt
cp models/postprocess/mask_config.pbtxt models/postprocess/config.pbtxt
配置模型
注意 这里根据自己机器的实际情况配置,由于本文使用的CPU版本的 FastDeploy 且也没有 GPU ,所以有关 GPU 的配置一概不选。
启动服务
提供HTTP\GRPC服务
3. 远程调用
3.1 Java 调用 - HTTP
<code>package cn.nhd.fsl.controller.test;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.squareup.okhttp.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class FastDeploy {
public static void main(String[] args) throws IOException {
int[][][] ints = readImagePath("D:\\code\\fastdeploy\\pythonProject1\\image\\OIP1.jpg");
// 这里 640, 640,填写图片实际的像素尺寸
// 也可以直接获取图片尺寸大小,这里懒得改了
JSONObject json = generateJson(640, 640, ints);
String s = fastDeployConnect(json.toJSONString());
System.out.println(s);
// 使用Fastjson解析JSON字符串
JSONObject jsonObject = JSON.parseObject(s);
// 访问outputs对象
JSONArray outputsArray = jsonObject.getJSONArray("outputs");
JSONObject jsonObject1 = outputsArray.getJSONObject(0);
JSONArray data = jsonObject1.getJSONArray("data");
String dataStr = data.getString(0);
JSONObject dataJson = JSON.parseObject(dataStr);
JSONArray scores = dataJson.getJSONArray("scores");
String scoresStr = scores.getString(0);
double score = Double.parseDouble(scoresStr);
// 阈值,超过阈值的认为是吸烟行为。范围 0 ~ 1
if (score > 0.5) {
System.out.println("异常行为");
} else {
System.out.println("正常行为");
}
}
/**
* 返回图片的RGB三维数组
* @param path 图片路径
* @return
* @throws IOException
*/
public static int[][][] readImagePath(String path) throws IOException {
BufferedImage image = ImageIO.read(new File(path));
int height = image.getHeight();
int width = image.getWidth();
int[][][] rgbArray = new int[height][width][3];
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int pixel = image.getRGB(col, row);
rgbArray[row][col][0] = (pixel >> 16) & 0xff; // R
rgbArray[row][col][1] = (pixel >> 8) & 0xff; // G
rgbArray[row][col][2] = pixel & 0xff; // B
}
}
return rgbArray;
}
/**
* 生成json对象,懒得搞一堆对应的类了
* @param imgHeight
* @param imgWidth
* @param rgbArray
* @return
*/
public static JSONObject generateJson(int imgHeight, int imgWidth, int[][][] rgbArray) {
JSONObject jsonObject = new JSONObject();
JSONArray inputArray = new JSONArray();
JSONObject inputObject = new JSONObject();
JSONArray shapeArray = new JSONArray();
shapeArray.add(1);
shapeArray.add(imgHeight);
shapeArray.add(imgWidth);
shapeArray.add(3);
JSONArray dataArray=new JSONArray();
JSONArray datajsonArray = JSONArray.parseArray(JSONArray.toJSONString(rgbArray));
dataArray.add(datajsonArray);
inputObject.put("name", "INPUT");
inputObject.put("shape", shapeArray);
inputObject.put("datatype", "UINT8");
inputObject.put("data", dataArray);
inputArray.add(inputObject);
jsonObject.put("inputs", inputArray);
return jsonObject;
}
/**
* 连接新方式部署的ocr服务
*
* @param jsonParamStr
* @return
*/
public static String fastDeployConnect(String jsonParamStr) throws IOException {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, jsonParamStr);
// 填写实际的地址
Request request = new Request.Builder()
.url("http://{IP}:{接口}/v2/models/ppdet/versions/1/infer")
.post(body)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String str = response.body().string();
return str;
}
}
3.2 Python 调用 - HTTP
from PIL import Image, ImageDraw
import numpy as np
import json
import requests
img_path = 'D:\\code\\fastdeploy\pythonProject1\image\\OIP1.jpg'
# 打开图片文件
img = Image.open(img_path)
# 检查图片是否已经是RGB格式
if img.mode != 'RGB':
# 将图片转换为RGB格式
img_rgb = img.convert('RGB')
else:
# 图片已经是RGB格式,无需转换
img_rgb = img
# 修改图片尺寸为 640x640
# 也可不用修改,但对应的入参,要填入图片实际尺寸
#"shape": [
# 1,
# 640,
# 640,
# 3
# ]
img_resized = img_rgb.resize((640, 640))
# 将图片解析成 RGB 三维数组
img_array = np.array(img_resized)
# 确保数据类型为 float32
# img_array = img_array.astype(np.float32)
# 定义请求的URL
url = 'http://{IP}:{接口}}/v2/models/ppdet/versions/1/infer'
# 初始化请求体的数据结构
data1 = {
"inputs": [
{
"name": "INPUT",
"datatype": "UINT8",
"shape": [
1,
640,
640,
3
],
"data": img_array.tolist()
}
]
}
# 将字典转换为JSON字符串
json_data = json.dumps(data)
# 发送POST请求
response = requests.post(url, headers={ 'Content-Type': 'application/json'}, data=json_data)
# 打印响应内容
print(response.text)
3.3 Python 调用 - GRPC
import logging
import numpy as np
import time
from typing import Optional
import cv2
import json
from tritonclient import utils as client_utils
from tritonclient.grpc import InferenceServerClient, InferInput, InferRequestedOutput, service_pb2_grpc, service_pb2
LOGGER = logging.getLogger("run_inference_on_triton")
class SyncGRPCTritonRunner:
DEFAULT_MAX_RESP_WAIT_S = 120
def __init__(
self,
server_url: str,
model_name: str,
model_version: str,
*,
verbose=False,
resp_wait_s: Optional[float] = None, ):
self._server_url = server_url
self._model_name = model_name
self._model_version = model_version
self._verbose = verbose
self._response_wait_t = self.DEFAULT_MAX_RESP_WAIT_S if resp_wait_s is None else resp_wait_s
self._client = InferenceServerClient(
self._server_url, verbose=self._verbose)
error = self._verify_triton_state(self._client)
if error:
raise RuntimeError(
f"Could not communicate to Triton Server: { error}")
LOGGER.debug(
f"Triton server { self._server_url} and model { self._model_name}:{ self._model_version} "
f"are up and ready!")
model_config = self._client.get_model_config(self._model_name,
self._model_version)
model_metadata = self._client.get_model_metadata(self._model_name,
self._model_version)
LOGGER.info(f"Model config { model_config}")
LOGGER.info(f"Model metadata { model_metadata}")
for tm in model_metadata.inputs:
print("tm:", tm)
self._inputs = { tm.name: tm for tm in model_metadata.inputs}
self._input_names = list(self._inputs)
self._outputs = { tm.name: tm for tm in model_metadata.outputs}
self._output_names = list(self._outputs)
self._outputs_req = [
InferRequestedOutput(name) for name in self._outputs
]
def Run(self, inputs):
"""
Args:
inputs: list, Each value corresponds to an input name of self._input_names
Returns:
results: dict, {name : numpy.array}
"""
infer_inputs = []
for idx, data in enumerate(inputs):
infer_input = InferInput(self._input_names[idx], data.shape,
"FP32")
infer_input.set_data_from_numpy(data)
infer_inputs.append(infer_input)
infer_input1 = InferInput(self._input_names[1], [1, 2],
"FP32")
data = np.array([[1, 1]], dtype=np.float32)
infer_input1.set_data_from_numpy(data)
infer_inputs.append(infer_input1)
results = self._client.infer(
model_name=self._model_name,
model_version=self._model_version,
inputs=infer_inputs,
outputs=self._outputs_req,
client_timeout=self._response_wait_t, )
results = { name: results.as_numpy(name) for name in self._output_names}
return results
def _verify_triton_state(self, triton_client):
if not triton_client.is_server_live():
return f"Triton server { self._server_url} is not live"
elif not triton_client.is_server_ready():
return f"Triton server { self._server_url} is not ready"
elif not triton_client.is_model_ready(self._model_name,
self._model_version):
return f"Model { self._model_name}:{ self._model_version} is not ready"
return None
if __name__ == "__main__":
model_name = "ppdet"
model_version = "1"
url = "{IP}:{接口}"
runner = SyncGRPCTritonRunner(url, model_name, model_version)
im = cv2.imread("D:\code\\fastdeploy\pythonProject1\image\OIP1.jpg")
im = np.transpose(im, (2, 0, 1)) # 转换通道顺序
im = np.array([im, ])
im = im.astype(np.float32)
for i in range(1):
for i in range(1):
result = runner.Run([im, ])
for name, values in result.items():
print("output_name:", name)
# values is batch
for value in values:
value = json.loads(value)
print(value['boxes'])
3.4 调用成功
后台监控
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。