【山东大学软件学院 21 级项目实训】前端推理实现

引言

下面展示的是我们在智能车运行过程中的前端推理实现,通过摄像头捕捉图像并实时进行推理处理。本部分记录了前端推理实现的详细步骤和代码示例。

前端推理实现

前端推理程序是智能车实时处理图像数据的重要部分,通过调用后台推理服务,实现对图像的实时分析与处理。以下是前端推理实现的代码。

  1. 导入必要的库 首先,我们需要导入相关库:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import zmq
import cv2
import numpy as np
import time
import json
import subprocess
import os, sys
# 添加上两层目录
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) 
​
import psutil
from log_info import logger
  • zmq 用于网络通信。

  • cv2 用于图像处理。

  • numpy 用于数组操作。

  • time 用于时间控制。

  • json 用于处理JSON格式的数据。

  • subprocess 用于执行系统命令。

  • ossys 用于操作系统相关功能。

  • psutil 用于获取系统进程信息。

  • logger 用于记录日志。

  1. 辅助函数 定义一些辅助函数,用于获取ZMQ客户端和Python进程信息:

def get_zmp_client(port):
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    res = socket.connect(f"tcp://127.0.0.1:{port}")
    return socket
​
def get_python_processes():
    python_processes = []
    for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
        try:
            if 'python' in proc.info['name'].lower() and len(proc.info['cmdline']) > 1 and len(proc.info['cmdline'][1]) < 100:
                info = [proc.info['pid'], proc.info['cmdline'][1]]
                python_processes.append(info)
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return python_processes
  1. 定义Bbox类 编写 Bbox 类,用于处理边界框的转换和归一化:

class Bbox:
    def __init__(self, box=None, rect=None, size=[640, 480]) -> None:
        self.size = np.array(size) / 2
        self.size_concat = np.concatenate((self.size, self.size))
​
        if box is not None:
            box_np = np.array(box)
            if (np.abs(box_np) < 2).all():
                self.box_normalise = box_np
                self.box = self.denormalise(box_np, self.size)
            else:
                self.box = box_np
                self.box_normalise = self.normalise(box_np, self.size)
            self.rect = self.box_to_rect(self.box, self.size)
        elif rect is not None:
            self.rect = np.array(rect)
            self.box = self.rect_to_box(self.rect, self.size)
            self.box_normalise = self.normalise(self.box, self.size)
    
    def get_rect(self):
        return self.rect
    
    def get_box(self):
        return self.box
​
    @staticmethod
    def normalise(box, size):
        return box / np.concatenate((size, size))
    
    @staticmethod
    def denormalise(box_nor, size):
        return (box_nor * np.concatenate((size, size))).astype(np.int32)
​
    @staticmethod
    def rect_to_box(rect, size):
        pt_tl = rect[:2]
        pt_br = rect[2:]
        pt_center = (pt_tl + pt_br) / 2 - size
        box_wd = pt_br - pt_tl
        return np.concatenate((pt_center, box_wd)).astype(np.int32)
​
    @staticmethod
    def box_to_rect(box, size):
        pt_center = box[:2]
        box_wd = box[2:]
        pt_tl = (size + pt_center - box_wd / 2).astype(np.int32)
        pt_br = (size + pt_center + box_wd / 2).astype(np.int32)
        rect = np.concatenate((pt_tl, pt_br))
        max_size = np.concatenate((size, size))*2
        np.clip(rect, 0, max_size, out=rect)
        return rect
  1. 定义客户端接口类 编写 ClintInterface 类,用于与后台推理服务进行通信:

class ClintInterface:
    configs = [
            {'name':'lane', 'infer_type': 'LaneInfer', 'params': [], 'port':5001, 'img_size':[128, 128]},
            {'name':'task', 'infer_type': 'YoloeInfer', 'params': ['task_model3'], 'port':5002, 'img_size':[416, 416]},
            {'name':'front', 'infer_type':'YoloeInfer', 'params': ['front_model2'], 'port':5003, 'img_size':[416, 416]},
            {'name':'ocr', 'infer_type':'OCRReco', 'params': [], 'port':5004,'img_size':None},
            {'name':'humattr', 'infer_type':'HummanAtrr', 'params': [], 'port':5005, 'img_size':None},
            {'name':'mot', 'infer_type':'MotHuman', 'params': [], 'port':5006, 'img_size':None}
            ]
    
    def __init__(self, name):
        logger.info("{}连接服务器...".format(name))
        model_cfg = self.get_config(name)
        self.img_size = model_cfg['img_size']
        self.client = self.get_zmp_client(model_cfg['port'])
        
        infer_back_end_file = "infer_back_end.py"
        self.check_back_python(infer_back_end_file)
​
        flag = False
        while True:
            if self.get_state():
                if flag:
                    logger.info("")
                break
            print('.', end='', flush=True)
            time.sleep(1)
            flag = True
        logger.info("{}连接服务器成功".format(name))
    
    def check_back_python(self, file_name):
        dir_file = os.path.abspath(os.path.dirname(__file__))
        file_path = os.path.join(dir_file, file_name)
        if not os.path.exists(file_path):
            raise Exception("后台脚本文件不存在")
        py_lists = get_python_processes()
        for py_iter in py_lists:
            if file_name in py_iter[1]:
                return
        else:
            logger.info("开启{}脚本, 后台运行中, 请等待".format(file_name))
            cmd_str = 'python3 ' + file_path + ' &'
            subprocess.Popen(cmd_str, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            time.sleep(1)
​
    def get_config(self, name):
        for conf in self.configs:
            if conf['name'] == name:
                return conf
            
    @staticmethod
    def get_zmp_client(port):
        context = zmq.Context()
        socket = context.socket(zmq.REQ)
        res = socket.connect(f"tcp://127.0.0.1:{port}")
        return socket
    
    def __call__(self, *args, **kwds):
        return self.get_infer(*args, **kwds)
    
    def get_state(self):
        data = bytes('ATATA', encoding='utf-8')
        self.client.send(data)
        response = self.client.recv()
        response = json.loads(response)
        return response
    
    def get_infer(self, img):
        if self.img_size is not None:
            img = cv2.resize(img, self.img_size)
        img = cv2.imencode('.jpg', img)[1].tobytes()
        data = bytes('image', encoding='utf-8') + img
        self.client.send(data)
        response = self.client.recv()
        response = json.loads(response)
        return response
  1. 主函数 编写主函数,启动前端推理客户端:

def main_client():
    from camera import Camera
    cap = Camera(2, 640, 480)
    infer_client = ClintInterface("ocr")
    last_time = time.time()
    while True:
        img = cap.read()
        dets_ret = infer_client.get_infer(img[300:, 200:460])
        print(dets_ret)
        cv2.imshow("img", img)
        key = cv2.waitKey(1)
        if key == ord('q'):
            break
        fps = 1 / (time.time() - last_time)
        last_time = time.time()
        print("fps:", fps)
    cap.close()
    cv2.destroyAllWindows()
  1. 停止进程函数 编写停止进程的函数:

def stop_process(py_str):
    py_lists = get_python_processes()
    for py_procees in py_lists:
        pid_id, py_name = py_procees[0], py_procees[1]
        if py_str in py
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值