基于SophonSDK的算法服务封装与打包参考流程(Python)

我们使用SophonSDK来移植算法和模型,并在X86主机的开发环境上封装和打包算法服务。这里以LPRNet车牌识别算法服务为例进行介绍。相关文件已上传至SOPHGO的demo目录下,主要流程包括以下几步:

1 封装算法服务

我们在x86文件下的main.py中封装了算法接口和HTTP服务。

1.1 算法封装

车牌识别算法比较简单,我们可以把整个算法流程封装到main.py中,并提供算法调用接口。

class LPRNet(object):
    ...
if __name__ == "__main__":
    lprnet = LPRNet()

如果算法比较复杂,涉及多个模型,我们可以把算法的相关代码放至x86文件夹下,在main.py中提供算法调用接口即可。

1.2 服务封装

我们需要在SimpleHTTPRequestHandler中的do_POST函数下定义访问地址、请求方式、返回码、返回信息、调用算法接口、返回结果等。

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    ......
    def do_POST(self):#ip:port/lprnet
        path = str(self.path)  # 获取请求的url
        if path == '/lprnet':
            content_length = int(self.headers['Content-Length'])
            body = self.rfile.read(content_length).decode('utf-8')
            print('body:',body)
            jsdata = json.loads(body)
            if 'image' not in jsdata:
                ret_json = {"Code":1,"Msg":"请求失败,未输入图片"}
                self.send_ret(ret_json)
                return
            image = jsdata['image']
            img = base64_to_cv2(image)
            if img is None:
                ret_json = {"Code":1,"Msg":"请求失败,图片读取失败"}
                self.send_ret(ret_json)
                return
            res = lprnet(img)[0]           
            ret_json = {"Code":0,"Msg":"请求成功","res":res}
            self.send_ret(ret_json)
        elif path == '/query':
            content_length = int(self.headers['Content-Length'])
            body = self.rfile.read(content_length).decode('utf-8')
            jsdata = json.loads(body)
            # if jsdata['name'] == 'font':
            ret_json = {'Code':0,'Msg':'请求成功','result':[{'url':'/lprnet','status':0}]}
            self.send_ret(ret_json)
        else:
            ret_json = {"Code":1,"Msg":"请求失败,url路径错误","res":''}
            self.send_ret(ret_json)

我们还需要设置HTTPServer的访问端口。

if __name__ == "__main__":
    lprnet = LPRNet()
    httpd = HTTPServer(('0.0.0.0', 9093), SimpleHTTPRequestHandler)
    httpd.serve_forever()

我们可以在main.sh中定义服务启动命令,并保存相关日志。

#!/bin/bash
python3 main.py >> log.txt 2>&1


1.3 服务测试

算法服务封装好后,我们可以在开发环境的容器中直接运行main.sh,启动服务。

然后在宿主机或其他连通的主机上调用该服务,主要修改访问的IP、端口、地址、请求值、获取返回值等,具体可参考test.py

python3 test.py


2 准备镜像文件

服务测试通过后,我们需要在开发环境的容器中,将服务所需的文件,包括环境链接库、sail包、代码、模型等,统一拷贝到指定文件夹,方便后续打包服务镜像。具体可参考assemble_x86.sh,需要视情况修改脚本中的文件路径。

./assemble_x86.sh


3 打包服务镜像

3.1 修改Dockerfile

包括安装所需的工具和依赖库、将镜像文件夹添加到镜像中、设置启动命令等等。

FROM debian:9
# 尽量将所有的工具安装放到本层,以减少size
# 不需要的工具尽量移除,调试工具可以在docker中runtime安装,没有必要预装
RUN apt -y update \
    # && add-apt-repository ppa:deadsnakes/ppa \
    && apt install -y python3 \
    && apt install -y python3-pip \
    && apt-get install ffmpeg libsm6 libxext6  -y
# Python依赖包在本层安装,并且请指明需要的版本号,以确保每次编译能编译出相同的镜像
RUN python3 -m pip install --upgrade pip \    
    && pip3 install pybind11 \    
    && pip3 install numpy \   
    && pip3 install requests \   
    && pip3 install Pillow \
    && pip3 install urllib3 \
    && pip3 install opencv-python
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 将镜像文件夹添加到镜像中
ADD x86  /avs_l1
# 安装sail包
RUN pip3 install /avs_l1/sophon-2.7.0-py3-none-any.whl
# 指定工作目录
WORKDIR /avs_l1
# 指定链接库路径
ENV LD_LIBRARY_PATH=.
# 设置启动命令
ENTRYPOINT ["./main.sh"]


3.2 打包服务镜像

然后,执行./build_docker_x86.sh进行服务镜像打包。需要进入到与镜像文件夹同级的目录中,主要修改dockerfile的相对路径、镜像名、镜像文件名。

# 进入到与镜像文件夹同级的目录中
cd ../../docker
# 创建docker镜像,通过-f指定dockerfile路径,-t指定镜像名
sudo docker build -f ../projects/lprnet_serve/Dockerfile_x86_sail -t avs_lprnet .
# 保存docker镜像,通过-o指定保存的文件名称
sudo docker save avs_lprnet -o avs_lprnet_x86.docker
# 修改镜像文件权限
sudo chmod 666 avs_lprnet_x86.docker
# 删除镜像
sudo docker rmi avs_lprnet


4 服务测试

第一步:加载服务镜像

docker load -i avs_lprnet_x86.docker
注意修改服务镜像路径。

第二步:创建镜像容器,启动服务

./run_docker.sh avs_lprnet:latest lprnet
注意修改镜像名(第1个参数)和容器名(第2个参数),可在脚本中自行更改容器端口映射。

第三步:服务调用与测试示例

sudo python3 test.py
注意修改测试脚本里面的测试图片路径、访问IP、端口、地址、请求值、获取返回值等。
————————————————
版权声明:本文为CSDN博主「weixin_44087610」的原创文章,遵循CC 4.0 BY-SA版权协议

你可能感兴趣的:(SOPHON,SDK常见问题,1024程序员节,算法,docker)