STM32N6 NPU Deployment — Politecnico di Milano  1.0
Documentation for Neural Network Deployment on STM32N6 NPU - Politecnico di Milano 2024-2025
gen_h_file.py
Go to the documentation of this file.
1 # /*---------------------------------------------------------------------------------------------
2 # * Copyright (c) 2023 STMicroelectronics.
3 # * All rights reserved.
4 # *
5 # * This software is licensed under terms that can be found in the LICENSE file in
6 # * the root directory of this software component.
7 # * If no LICENSE file comes with this software, it is provided AS-IS.
8 # *--------------------------------------------------------------------------------------------*/
9 
10 import ssl
11 
12 ssl._create_default_https_context = ssl._create_unverified_context
13 
14 import os
15 from hydra.core.hydra_config import HydraConfig
16 from omegaconf import DictConfig
17 import numpy as np
18 import tensorflow as tf
19 
20 from common.utils import aspect_ratio_dict, color_mode_n6_dict
21 
22 
23 def gen_h_user_file_n6(config: DictConfig = None, quantized_model_path: str = None) -> None:
24  """
25  Generates a C header file containing user configuration for the AI model.
26 
27  Args:
28  config: A configuration object containing user configuration for the AI model.
29  quantized_model_path: The path to the quantized model file.
30 
31  """
32  class Flags:
33  def __init__(self, **entries):
34  self.__dict__.update(entries)
35 
36  params = Flags(**config)
37  interpreter_quant = tf.lite.Interpreter(model_path=quantized_model_path)
38  input_details = interpreter_quant.get_input_details()[0]
39  output_details = interpreter_quant.get_output_details()[0]
40  input_shape = input_details['shape']
41 
42  path = os.path.join(HydraConfig.get().runtime.output_dir, "C_header/")
43 
44  try:
45  os.mkdir(path)
46  except OSError as error:
47  print(error)
48 
49 
50 
51  with open(os.path.join(path, "app_config.h"), "wt") as f:
52  f.write("/**\n")
53  f.write("******************************************************************************\n")
54  f.write("* @file app_config.h\n")
55  f.write("* @author GPM Application Team\n")
56  f.write("*\n")
57  f.write("******************************************************************************\n")
58  f.write("* @attention\n")
59  f.write("*\n")
60  f.write("* Copyright (c) 2023 STMicroelectronics.\n")
61  f.write("* All rights reserved.\n")
62  f.write("*\n")
63  f.write("* This software is licensed under terms that can be found in the LICENSE file\n")
64  f.write("* in the root directory of this software component.\n")
65  f.write("* If no LICENSE file comes with this software, it is provided AS-IS.\n")
66  f.write("*\n")
67  f.write("******************************************************************************\n")
68  f.write("*/\n\n")
69  f.write("/* --------------- Generated code ----------------- */\n")
70  f.write("#ifndef APP_CONFIG\n")
71  f.write("#define APP_CONFIG\n\n")
72  f.write('#include "arm_math.h"\n\n')
73  f.write("#define USE_DCACHE\n\n")
74  f.write("/*Defines: CMW_MIRRORFLIP_NONE; CMW_MIRRORFLIP_FLIP; CMW_MIRRORFLIP_MIRROR; CMW_MIRRORFLIP_FLIP_MIRROR;*/\n")
75  f.write("#define CAMERA_FLIP CMW_MIRRORFLIP_NONE\n\n")
76  f.write("")
77  f.write("#define ASPECT_RATIO_CROP (1) /* Crop both pipes to nn input aspect ratio; Original aspect ratio kept */\n")
78  f.write("#define ASPECT_RATIO_FIT (2) /* Resize both pipe to NN input aspect ratio; Original aspect ratio not kept */\n")
79  f.write("#define ASPECT_RATIO_FULLSCREEN (3) /* Resize camera image to NN input size and display a fullscreen image */\n")
80  f.write("#define ASPECT_RATIO_MODE {}\n".format(aspect_ratio_dict[params.preprocessing.resizing.aspect_ratio]))
81  f.write("\n")
82 
83  f.write("/* Postprocessing type configuration */\n")
84 
85  if params.general.model_type == "heatmaps_spe":
86  f.write("#define POSTPROCESS_TYPE POSTPROCESS_SPE_MOVENET_UF\n\n")
87  elif params.general.model_type == "yolo_mpe":
88  f.write("#define POSTPROCESS_TYPE POSTPROCESS_MPE_YOLO_V8_UF\n\n")
89  else:
90  raise ValueError("Please select one supported post-processing option: heatmaps_spe or yolo_mpe.")
91 
92  f.write("#define NN_HEIGHT ({})\n".format(int(input_shape[1])))
93  f.write("#define NN_WIDTH ({})\n".format(int(input_shape[2])))
94  f.write("#define NN_BPP 3")
95  f.write("\n\n")
96  f.write("#define COLOR_BGR (0)\n")
97  f.write("#define COLOR_RGB (1)\n")
98  f.write("#define COLOR_MODE {}\n".format(color_mode_n6_dict[params.preprocessing.color_mode]))
99 
100  if params.general.model_type == "heatmaps_spe":
101  f.write("\n/* Post processing values */\n")
102  f.write("#define AI_POSE_PP_CONF_THRESHOLD ({})\n".format(float(params.postprocessing.kpts_conf_thresh)))
103  f.write("#define AI_POSE_PP_POSE_KEYPOINTS_NB ({})\n".format(int(output_details['shape'][3])))
104  f.write("#define AI_SPE_MOVENET_POSTPROC_HEATMAP_WIDTH (NN_WIDTH/4)\n")
105  f.write("#define AI_SPE_MOVENET_POSTPROC_HEATMAP_HEIGHT (NN_HEIGHT/4)\n")
106  f.write("#define AI_SPE_MOVENET_POSTPROC_NB_KEYPOINTS (AI_POSE_PP_POSE_KEYPOINTS_NB) /* Only 13 and 17 keypoints are supported for the skeleton reconstruction */\n\n")
107  elif params.general.model_type == "yolo_mpe":
108  out_shape = output_details["shape"]
109  nb_kpt = (out_shape[1]-5)/3
110  f.write("\n/* Post processing values */\n")
111  f.write("#define AI_MPE_YOLOV8_PP_NB_CLASSES (1)\n")
112  f.write("#define AI_MPE_YOLOV8_PP_TOTAL_BOXES ({})\n".format(int(out_shape[2])))
113  f.write("#define AI_MPE_YOLOV8_PP_MAX_BOXES_LIMIT ({})\n".format(int(params.postprocessing.max_detection_boxes)))
114  f.write("#define AI_MPE_YOLOV8_PP_IOU_THRESHOLD ({})\n".format(float(params.postprocessing.NMS_thresh)))
115  f.write("#define AI_MPE_YOLOV8_PP_CONF_THRESHOLD ({})\n\n".format(float(params.postprocessing.confidence_thresh)))
116 
117  f.write("#define AI_POSE_PP_CONF_THRESHOLD ({})\n".format(float(params.postprocessing.kpts_conf_thresh)))
118  f.write("#define AI_POSE_PP_POSE_KEYPOINTS_NB ({})\n".format(int(nb_kpt)))
119  else:
120  raise ValueError(f"model_type not supported: {params.general.model_type}")
121  f.write('/* Display */\n')
122  f.write('#define WELCOME_MSG_0 "Single/multi pose estimation - Hand landmark"\n')
123  f.write('#define WELCOME_MSG_1 "{}"\n'.format(os.path.basename(params.general.model_path)))
124  if config.deployment.hardware_setup.board == 'NUCLEO-N657X0-Q':
125  f.write('#define WELCOME_MSG_2 ((char *[2]) {"Model Running in STM32 MCU", "internal memory"})')
126  else:
127  f.write('#define WELCOME_MSG_2 "{}"\n'.format("Model Running in STM32 MCU internal memory"))
128  f.write("\n")
129  f.write("#endif /* APP_CONFIG */\n")
130 
131 
None gen_h_user_file_n6(DictConfig config=None, str quantized_model_path=None)
Definition: gen_h_file.py:23