Implementación del modelo PaddlePadle-YOLOE basado en OpenVINO: implementación 4.Python

1. Instalación ambiental

 La versión 2022.1 del kit de herramientas OpenVINO TM se lanzó oficialmente el 22 de marzo de 2022. En comparación con las versiones anteriores, se han producido importantes innovaciones: proporciona funciones API de preprocesamiento, API de front-end ONNX y complementos de dispositivos AUTO, y admite la lectura directa de modelo de hélice voladora La inferencia admite el cambio dinámico de la forma del modelo, lo que promueve en gran medida la aplicación de diferentes redes. El 23 de septiembre de 2022, se lanzó OpenVINO TM Toolkit versión 2022.2, ajustando 2022.1 para incluir soporte para las últimas CPU y GPU discretas de Intel para permitir aún más innovaciones y oportunidades de IA.

 Aquí se selecciona la versión OpenVINO TM 2022.2. Para la versión Python, podemos usar directamente el comando PIP para instalarla. Se recomienda utilizar Anaconda para crear un entorno virtual para la instalación. Para la última versión, ingrese el siguiente comando directamente en el entorno virtual creado para instalar:

// 更新pip
python -m pip install --upgrade pip
// 安装
pip install openvino-dev[ONNX,tensorflow2]==2022.2.0

 Si hay un error al descargar el paquete de instalación o la red durante el proceso de instalación, puede volver a ejecutar el comando de instalación y continuar con la instalación anterior.

2. Cree una clase de razonamiento Predictor

from openvino.runtime import Core
class Predictor:
    """
    OpenVINO 模型推理器
    """
    def __init__(self, model_path):
        ie_core = Core()
        model = ie_core.read_model(model=model_path)
        self.compiled_model = ie_core.compile_model(model=model, device_name="CPU")
    def get_inputs_name(self, num):
        return self.compiled_model.input(num)
    
    def get_outputs_name(self, num):
        return self.compiled_model.output(num)
    
    def predict(self, input_data):
        return self.compiled_model([input_data])
        

 Dado que aquí solo se realiza el razonamiento del modelo PP-YOLOE, la clase Predictor simplemente se encapsula: incluye principalmente una función de inicialización, que es responsable de leer el modelo local y cargarlo en el dispositivo especificado; la función de obtener la entrada y salida nombres y la función de predicción del modelo.

3. Método de procesamiento de datos

3.1 Preprocesamiento de imágenes de entrada

def process_image(input_image, size):
    """输入图片与处理方法,按照PP-Yoloe模型要求预处理图片数据

    Args:
        input_image (uint8): 输入图片矩阵
        size (int): 模型输入大小

    Returns:
        float32: 返回处理后的图片矩阵数据
    """
    max_len = max(input_image.shape)
    img = np.zeros([max_len,max_len,3],np.uint8)
    img[0:input_image.shape[0],0:input_image.shape[1]] = input_image # 将图片放到正方形背景中
    img = cv.cvtColor(img,cv.COLOR_BGR2RGB)  # BGR转RGB
    img = cv.resize(img, (size, size), cv.INTER_NEAREST) # 缩放图片
    img = np.transpose(img,[2, 0, 1]) # 转换格式
    img = img / 255.0 # 归一化
    img = np.expand_dims(img,0) # 增加维度
    return img

 De acuerdo con los requisitos de entrada del modelo PP-YOLOE, los datos de la imagen se procesan, incluyendo principalmente la conversión del canal de la imagen, el escalado de la imagen, la matriz de transformación, la normalización de los datos y el aumento de las dimensiones de la matriz. De acuerdo con la configuración de entrada del modelo PP-YOLOE, el método de normalización consiste en dividir directamente los puntos de píxeles entre 255 e integrar los datos de entrada entre 0 y 1 para acelerar el cálculo del modelo. El formato ONNX del modelo PP-YOLOE solo admite la inferencia de bath_size = 1, por lo que al final, la dimensión de la matriz de datos se puede aumentar directamente en una dimensión.

3.2 Procesamiento de salida del modelo

def process_result(box_results, conf_results):
    """按照PP-Yolove模型输出要求,处理数据,非极大值抑制,提取预测结果

    Args:
        box_results (float32): 预测框预测结果
        conf_results (float32): 置信度预测结果
    Returns:
        float: 预测框
        float: 分数
        int: 类别
    """
    conf_results = np.transpose(conf_results,[0, 2, 1]) # 转置
    # 设置输出形状
    box_results =box_results.reshape(8400,4) 
    conf_results = conf_results.reshape(8400,80)
    scores = []
    classes = []
    boxes = []
    for i in range(8400):
        conf = conf_results[i,:] # 预测分数
        score = np.max(conf) # 获取类别
        # 筛选较小的预测类别
        if score > 0.5:
            classes.append(np.argmax(conf)) 
            scores.append(score) 
            boxes.append(box_results[i,:])
    scores = np.array(scores)
    boxes = np.array(boxes)
    # 非极大值抑制筛选重复的预测结果
    indexs = tf.image.non_max_suppression(boxes,scores,len(scores),0.25,0.35)
    # 处理非极大值抑制后的结果
    result_box = []
    result_score = []
    result_class = []
    for i, index in enumerate(indexs):
        result_score.append(scores[index])
        result_box.append(boxes[index,:])
        result_class.append(classes[index])
    # 返沪结果转为矩阵
    return np.array(result_box),np.array(result_score),np.array(result_class)

 Dado que el PP-YOLOE que utilizamos ha sido recortado por nosotros, la salida del modelo son los datos de resultado no procesados. Hay dos nodos de salida del modelo, uno es la salida del marco de predicción y el otro es la salida del valor de confianza. , por lo que es necesario ajustar la salida más adelante y procesar los resultados.

 La forma de salida del resultado de confianza es [1, 80, 8400], y el 80 real representa el valor de confianza de 80 categorías correspondientes a un resultado de predicción, y 8400 significa que hay 8400 resultados de predicción; y el resultado de salida de la predicción El cuadro es [1, 8400, 4], correspondiente al marco de predicción de 8400 resultados de predicción, donde 4 representa las coordenadas horizontales y verticales del vértice superior izquierdo y el vértice inferior derecho del marco de predicción.

 Por tanto, el procesamiento de resultados incluye principalmente los siguientes aspectos:

  • Se transpone el resultado de confianza y se extraen la categoría con el mayor resultado de predicción, la puntuación de predicción y el cuadro de predicción correspondiente;
  • La supresión no máxima extrae cuadros y categorías predichos.

3.3 Dibujar resultados de predicción

def draw_box(image, boxes, scores, classes, lables):
    """将预测结果绘制到图像上

    Args:
        image (uint8): 原图片
        boxes (float32): 预测框
        scores (float32): 分数
        classes (int): 类别
        lables (str): 标签

    Returns:
        uint8: 标注好的图片
    """
    scale = max(image.shape) / 640.0 # 缩放比例
    for i in range(len(classes)):
        box = boxes[i,:]

        x1 = int(box[0] * scale)
        y1 = int(box[1] * scale)
        x2 = int(box[2] * scale)
        y2 = int(box[3] * scale)
        
        lable = lables[classes[i]]
        score = scores[i]
        cv.rectangle(image, (x1, y1), (x2, y2), (0,0,255), 2, cv.LINE_8)
        cv.putText(image,lable+":"+str(score),(x1,y1-10),cv.FONT_HERSHEY_SIMPLEX, 0.55, (0, 0, 255), 2)
        
    return image

 Después del procesamiento de resultados en el paso anterior, finalmente se obtienen el marco de predicción, la puntuación y la categoría, y finalmente el resultado de la predicción se dibuja en la imagen a través de OpenCV, que consta principalmente de dos pasos: dibujar un marco de predicción y escribir la puntuación y la categoría.

4. Razonamiento modelo

    '''-------------------1. 导入相关信息 ----------------------'''
    # yoloe_model_path = "E:/Text_Model/pp-yoloe/ppyoloe_plus_crn_s_80e_coco.onnx"
    yoloe_model_path = "E:/Text_Model/pp-yoloe/ppyoloe_plus_crn_s_80e_coco.xml"
    image_path = "E:/Text_dataset/YOLOv5/0001.jpg"
    lable_path = "E:/Git_space/基于OpenVINO部署PP-YOLOE模型/model/lable.txt";
    '''-------------------2. 创建模型预测器 ----------------------'''
    predictor = Predictor(model_path = yoloe_model_path)
    '''-------------------3. 预处理模型输入数据 ----------------------'''
    image = cv.imread(image_path)
    input_image = process_image(image, 640)
    '''-------------------4. 模型推理 ----------------------'''
    results = predictor.predict(input_data=input_image)
    '''-------------------5. 后处理预测结果 ----------------------'''
    boxes_name = predictor.get_outputs_name(0)
    conf_name = predictor.get_outputs_name(1)
    
    boxes, scores, classes = process_result(box_results=results[boxes_name], conf_results=results[conf_name]) # 处理结果
    lables = read_lable(lable_path=lable_path) # 读取lable
    result_image = draw_box(image=image, boxes=boxes, scores=scores, classes=classes, lables=lables) # 绘制结果
    cv.imshow("result",result_image)
    cv.waitKey(0)

 De acuerdo con el proceso de inferencia del modelo, finalmente llame a la clase de inferencia del modelo para su implementación:

  • Importar información relacionada: define principalmente la dirección del modelo, la dirección de la imagen a predecir y el archivo de categoría;
  • Cree un predictor de modelo: inicialice principalmente la clase de predicción, lea el modelo local, aquí puede leer el modelo ONNX y el modelo IR en dos formatos;
  • Preprocesamiento de imágenes: llame al método de procesamiento de imágenes definido para convertir datos de imágenes locales en datos para la inferencia del modelo;
  • Razonamiento del modelo: cargue los datos de la imagen procesada en el modelo y obtenga los resultados del razonamiento del modelo;
  • Resultados del modelo de proceso: principalmente llamando al método de procesamiento de resultados. Si se requiere visualización, los resultados de la predicción se pueden dibujar en imágenes.

Acho que você gosta

Origin blog.csdn.net/grape_yan/article/details/127576236
Recomendado
Clasificación