Ты — тестер и исправитель кода. Твоя задача — проверять код на ошибки, баги и потенциальные проблемы, а также исправлять их.
////

#include "app_param.h"
#include "rknn_api.h"

/*
-------------------------------------------
   Глобальные переменные для контекста и памяти
-------------------------------------------
*/
rknn_context ctx = 0;

rknn_input_output_num io_num = {0};
rknn_tensor_attr *input_attrs = NULL;
rknn_tensor_attr *output_attrs = NULL;

rknn_tensor_mem *input_mems[1] = {NULL};
rknn_tensor_mem **output_mems = NULL;

/* параметры модели и thresholds */
void *model_path = MODEL_PATH;
const float nms_threshold = NMS_THRESH;
const float box_conf_threshold = BOX_THRESH;


static inline int64_t getCurrentTimeUs()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000000 + tv.tv_usec;
}

static void dump_tensor_attr(rknn_tensor_attr *attr)
{
  char dims[128] = {0};
  uint32_t i;
  for (i = 0; i < attr->n_dims; ++i)
  {
    int idx = (int)strlen(dims);
    sprintf(&dims[idx], "%d%s", attr->dims[i], (i == attr->n_dims - 1) ? "" : ", ");
  }
	/*
  printf("  index=%d, name=%s, n_dims=%d, dims=[%s], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, "
         "zp=%d, scale=%f\n",
         attr->index, attr->name, attr->n_dims, dims, attr->n_elems, attr->size, get_format_string(attr->fmt),
         get_type_string(attr->type), get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
				 */
}

/*-------------------------------------------
   Инициализация RKNN
-------------------------------------------*/
int rknn_init_model()
{
  int ret;

  ret = rknn_init(&ctx, model_path, 0, 0, NULL);
  if (ret < 0)
  {
    printf("rknn_init fail! ret=%d\n", ret);
    return -1;
  }

  rknn_sdk_version sdk_ver;
  ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &sdk_ver, sizeof(sdk_ver));
  if (ret != RKNN_SUCC)
  {
    printf("rknn_query fail! ret=%d\n", ret);
    rknn_destroy(ctx);
    return -1;
  }
  //printf("rknn_api/rknnrt version: %s, driver version: %s\n", sdk_ver.api_version, sdk_ver.drv_version);

  ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
  if (ret != RKNN_SUCC)
  {
    printf("rknn_query fail! ret=%d\n", ret);
    rknn_destroy(ctx);
    return -1;
  }
  //printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output);

  //printf("input tensors:\n");
  input_attrs = (rknn_tensor_attr *)malloc(io_num.n_input * sizeof(rknn_tensor_attr));
  if (!input_attrs) {
    printf("malloc failed for input_attrs\n");
    rknn_destroy(ctx);
    return -1;
  }
  memset(input_attrs, 0, io_num.n_input * sizeof(rknn_tensor_attr));
  uint32_t i;
  for (i = 0; i < io_num.n_input; i++)
  {
    input_attrs[i].index = i;
    ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr));
    if (ret < 0)
    {
      printf("rknn_init error! ret=%d\n", ret);
      free(input_attrs);
      rknn_destroy(ctx);
      return -1;
    }
    dump_tensor_attr(&(input_attrs[i]));
  }

  //printf("output tensors:\n");
  output_attrs = (rknn_tensor_attr *)malloc(io_num.n_output * sizeof(rknn_tensor_attr));
  if (!output_attrs) {
    printf("malloc failed for output_attrs\n");
    free(input_attrs);
    rknn_destroy(ctx);
    return -1;
  }
  memset(output_attrs, 0, io_num.n_output * sizeof(rknn_tensor_attr));
  for (i = 0; i < io_num.n_output; i++)
  {
    output_attrs[i].index = i;
    ret = rknn_query(ctx, RKNN_QUERY_NATIVE_NHWC_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr));
    if (ret != RKNN_SUCC)
    {
      printf("rknn_query fail! ret=%d\n", ret);
      free(input_attrs);
      free(output_attrs);
      rknn_destroy(ctx);
      return -1;
    }
    dump_tensor_attr(&(output_attrs[i]));
  }

  rknn_custom_string custom_string;
  ret = rknn_query(ctx, RKNN_QUERY_CUSTOM_STRING, &custom_string, sizeof(custom_string));
  if (ret != RKNN_SUCC)
  {
    printf("rknn_query fail! ret=%d\n", ret);
    free(input_attrs);
    free(output_attrs);
    rknn_destroy(ctx);
    return -1;
  }
  //printf("custom string: %s\n", custom_string.string);

  // Prepare input tensor mem
  rknn_tensor_type input_type = RKNN_TENSOR_INT8;
  rknn_tensor_format input_layout = RKNN_TENSOR_NHWC;

  input_attrs[0].type = input_type;
  input_attrs[0].fmt = input_layout;

  input_mems[0] = rknn_create_mem(ctx, input_attrs[0].size_with_stride);
  if (!input_mems[0]) {
    printf("rknn_create_mem failed for input_mems[0]\n");
    free(input_attrs);
    free(output_attrs);
    rknn_destroy(ctx);
    return -1;
  }

  // Prepare output tensor mems
  output_mems = (rknn_tensor_mem **)malloc(io_num.n_output * sizeof(rknn_tensor_mem *));
  if (!output_mems) {
    printf("malloc failed for output_mems\n");
    free(input_attrs);
    free(output_attrs);
    rknn_destroy_mem(ctx, input_mems[0]);
    rknn_destroy(ctx);
    return -1;
  }

  for (i = 0; i < io_num.n_output; ++i)
  {
    output_mems[i] = rknn_create_mem(ctx, output_attrs[i].size_with_stride);
    if (!output_mems[i]) {
      printf("rknn_create_mem fail for output_mems[%d]\n", i);
      // Ошибка освобождения памяти тут
      for (uint32_t j = 0; j < i; ++j)
        rknn_destroy_mem(ctx, output_mems[j]);
      free(output_mems);
      free(input_attrs);
      free(output_attrs);
      rknn_destroy_mem(ctx, input_mems[0]);
      rknn_destroy(ctx);
      return -1;
    }
  }

  return 0;
}

/*-------------------------------------------
    Освобождение ресурсов RKNN
-------------------------------------------*/
void rknn_release()
{
  uint32_t i;

  if (input_mems[0]) rknn_destroy_mem(ctx, input_mems[0]);
  if (output_mems) {
    for (i = 0; i < io_num.n_output; ++i)
      rknn_destroy_mem(ctx, output_mems[i]);
    free(output_mems);
  }
  if (input_attrs) free(input_attrs);
  if (output_attrs) free(output_attrs);

  if (ctx) rknn_destroy(ctx);
}


//static char *labels[OBJ_CLASS_NUM];

const int anchor0[6] = {10, 13, 16, 30, 33, 23};
const int anchor1[6] = {30, 61, 62, 45, 59, 119};
const int anchor2[6] = {116, 90, 156, 198, 373, 326};

inline static int clamp(float val, int min, int max)
{
    return val > min ? (val < max ? val : max) : min;
}

char *readLine(FILE *fp, char *buffer, int *len)
{
    int ch;
    int i = 0;
    size_t buff_len = 0;

    buffer = (char *)malloc(buff_len + 1);
    if (!buffer)
        return NULL; // Out of memory

    while ((ch = fgetc(fp)) != '\n' && ch != EOF)
    {
        buff_len++;
        void *tmp = realloc(buffer, buff_len + 1);
        if (tmp == NULL)
        {
            free(buffer);
            return NULL; // Out of memory
        }
        buffer = (char *)tmp;

        buffer[i] = (char)ch;
        i++;
    }
    buffer[i] = '\0';

    *len = buff_len;

    // Detect end
    if (ch == EOF && (i == 0 || ferror(fp)))
    {
        free(buffer);
        return NULL;
    }
    return buffer;
}

int readLines(const char *fileName, char *lines[], int max_line)
{
    FILE *file = fopen(fileName, "r");
    if (!file) {
        return -1;
    }
    char *s = NULL;
    int i = 0;
    int n = 0;
    while ((s = readLine(file, s, &n)) != NULL)
    {
        lines[i++] = s;
        if (i >= max_line)
            break;
    }
    fclose(file);
    return i;
}

int loadLabelName(const char *locationFilename, char *label[])
{
    //printf("loadLabelName %s\n", locationFilename);
    int ret = readLines(locationFilename, label, OBJ_CLASS_NUM);
    return ret >= 0 ? 0 : -1;
}

static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1)
{
    float w = fmaxf(0.f, fminf(xmax0, xmax1) - fmaxf(xmin0, xmin1) + 1.0f);
    float h = fmaxf(0.f, fminf(ymax0, ymax1) - fmaxf(ymin0, ymin1) + 1.0f);
    float i = w * h;
    float u = (xmax0 - xmin0 + 1.0f) * (ymax0 - ymin0 + 1.0f) + (xmax1 - xmin1 + 1.0f) * (ymax1 - ymin1 + 1.0f) - i;
    return u <= 0.f ? 0.f : (i / u);
}

static int nms(int validCount, float *outputLocations, int *classIds, int *order, int filterId, float threshold)
{

  for (int i = 0; i < validCount; ++i)
    {
        if (order[i] == -1|| classIds[i] != filterId)
        {
            continue;
        }
        int n = order[i];
        for (int j = i + 1; j < validCount; ++j)
        {
            int m = order[j];
            if (m == -1 || classIds[i] != filterId)
            {
                continue;
            }
            float xmin0 = outputLocations[n * 4 + 0];
            float ymin0 = outputLocations[n * 4 + 1];
            float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2];
            float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3];

            float xmin1 = outputLocations[m * 4 + 0];
            float ymin1 = outputLocations[m * 4 + 1];
            float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2];
            float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3];

            float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1);

            if (iou > threshold)
            {
                order[j] = -1;
            }
        }
    }
    return 0;
}

static int quick_sort_indice_inverse(float *input, int left, int right, int *indices)
{
    int low = left, high = right;
    if (left >= right)
        return left;

    float key = input[left];
    int key_index = indices[left];

    while (low < high) {
        while (low < high && input[high] <= key)
            high--;
        input[low] = input[high];
        indices[low] = indices[high];

        while (low < high && input[low] >= key)
            low++;
        input[high] = input[low];
        indices[high] = indices[low];
    }
    input[low] = key;
    indices[low] = key_index;

    quick_sort_indice_inverse(input, left, low - 1, indices);
    quick_sort_indice_inverse(input, low + 1, right, indices);

    return low;
}
/*
static float sigmoid(float x)
{
    return 1.0f / (1.0f + expf(-x));
}

static float unsigmoid(float y)
{
    return -1.0f * logf((1.0f / y) - 1.0f);
}
*/
inline static int32_t __clip(float val, float min, float max)
{
    float f = val <= min ? min : (val >= max ? max : val);
    return (int32_t)f;
}

static int8_t qnt_f32_to_affine(float f32, int32_t zp, float scale)
{
    float dst_val = (f32 / scale) + zp;
    int8_t res = (int8_t)__clip(dst_val, -128, 127);
    return res;
}

static float deqnt_affine_to_f32(int8_t qnt, int32_t zp, float scale)
{
    return ((float)qnt - (float)zp) * scale;
}

// process_native_nhwc переписан без vector, с указателями и malloc/free не нужен, т.к. push_back заменён на простое увеличение массива через индексы

static int process_native_nhwc(
	int8_t *input, 
	int *anchor, 
	int grid_h, 
	int grid_w, 
//	int height, 
//	int width, 
	int stride,
	float *boxes, 
	float *boxScores, 
	int *classId,
	float threshold, 
	int32_t zp, 
	float scale,
	int *box_count, 
	int max_box_num
)
{
    int validCount = 0;
    int8_t thres_i8 = qnt_f32_to_affine(threshold, zp, scale);

    int anchor_per_branch = 3;
    int align_c = PROP_BOX_SIZE * anchor_per_branch;

    for (int h=0; h < grid_h; h++){
        for (int w=0; w < grid_w; w++){
            for (int a=0; a < anchor_per_branch; a++){
                int hw_offset = h*grid_w*align_c + w*align_c + a*PROP_BOX_SIZE;
                int8_t *hw_ptr = input + hw_offset;
                int8_t box_confidence = hw_ptr[4];
                
                if (box_confidence >= thres_i8){
                    int8_t maxClassProbs = hw_ptr[5];
                    int maxClassId = 0;
                    for (int k = 1; k < OBJ_CLASS_NUM; ++k)
                    {
                        int8_t prob = hw_ptr[5 + k];
                        if (prob > maxClassProbs)
                        {
                            maxClassId = k;
                            maxClassProbs = prob;
                        }
                    }

                    float box_conf_f32 = deqnt_affine_to_f32(box_confidence, zp, scale);
                    float class_prob_f32 = deqnt_affine_to_f32(maxClassProbs, zp, scale);
                    float limit_score = box_conf_f32* class_prob_f32;

                    if (limit_score > threshold){
                        if (*box_count >= max_box_num)
                            return validCount; // превышение емкости массивов

                        float box_x, box_y, box_w, box_h;

                        box_x = deqnt_affine_to_f32(hw_ptr[0], zp, scale) * 2.0f - 0.5f;
                        box_y = deqnt_affine_to_f32(hw_ptr[1], zp, scale) * 2.0f - 0.5f;
                        box_w = deqnt_affine_to_f32(hw_ptr[2], zp, scale) * 2.0f;
                        box_h = deqnt_affine_to_f32(hw_ptr[3], zp, scale) * 2.0f;
                        box_w = box_w * box_w;
                        box_h = box_h * box_h;

                        box_x = (box_x + w) * (float)stride;
                        box_y = (box_y + h) * (float)stride;
                        box_w *= (float)anchor[a * 2];
                        box_h *= (float)anchor[a * 2 + 1];

                        box_x -= (box_w / 2.0f);
                        box_y -= (box_h / 2.0f);

                        int idx = (*box_count) * 4;
                        boxes[idx + 0] = box_x;
                        boxes[idx + 1] = box_y;
                        boxes[idx + 2] = box_w;
                        boxes[idx + 3] = box_h;
                        boxScores[*box_count] = limit_score;
                        classId[*box_count] = maxClassId;
                        (*box_count)++;
                        validCount++;
                    }
                }
            }
        }
    }
    return validCount;
}


int post_process(int8_t *input0, int8_t *input1, int8_t *input2, int model_in_h, int model_in_w,
                 float conf_threshold, float nms_threshold, float scale_w, float scale_h,
                 int32_t *qnt_zps, float *qnt_scales,
                 detect_result_group_t *group)
{
	    /*
    static int init = -1;

    if (init == -1)
    {
        int ret = 0;
        ret = loadLabelName(LABEL_NALE_TXT_PATH, labels);
        if (ret < 0)
        {
            return -1;
        }

        init = 0;
    }
  
    init = 0;
		  */
    memset(group, 0, sizeof(detect_result_group_t));

    // Определить максимально ожидаемое число детекций, например OBJ_NUMB_MAX_SIZE или можно больше для промежуточных массивов
    int max_detections = OBJ_NUMB_MAX_SIZE * 10;// с запасом

    float *filterBoxes = (float *)malloc(sizeof(float) * max_detections * 4);
    float *objProbs = (float *)malloc(sizeof(float) * max_detections);
    int *classId = (int *)malloc(sizeof(int) * max_detections);
    if (!filterBoxes || !objProbs || !classId){
        if(filterBoxes) free(filterBoxes);
        if(objProbs) free(objProbs);
        if(classId) free(classId);
        return -1;
    }

    int box_count = 0;

    // stride 8
    int stride0 = 8;
    int grid_h0 = model_in_h / stride0;
    int grid_w0 = model_in_w / stride0;
    int validCount0 = 0;
    validCount0 = process_native_nhwc(
			input0, 
			(int *)anchor0, 
			grid_h0, 
			grid_w0, 
//			model_in_h, 
//			model_in_w,
			stride0, 
			filterBoxes, 
			objProbs, 
			classId, 
			conf_threshold, 
			qnt_zps[0], 
			qnt_scales[0],
			&box_count, 
			max_detections
		);

    // stride 16
    int stride1 = 16;
    int grid_h1 = model_in_h / stride1;
    int grid_w1 = model_in_w / stride1;
    int validCount1 = 0;
    validCount1 = process_native_nhwc(
			input1, 
			(int *)anchor1, 
			grid_h1, 
			grid_w1, 
//			model_in_h,
//			model_in_w,
			stride1, 
			filterBoxes, 
			objProbs, 
			classId, 
			conf_threshold,
			qnt_zps[1], 
			qnt_scales[1],
			&box_count, 
			max_detections
		);

    // stride 32
    int stride2 = 32;
    int grid_h2 = model_in_h / stride2;
    int grid_w2 = model_in_w / stride2;
    int validCount2 = 0;
    validCount2 = process_native_nhwc(
			input2, 
			(int *)anchor2, 
			grid_h2, 
			grid_w2, 
//			model_in_h, 
//			model_in_w,
			stride2, 
			filterBoxes, 
			objProbs, 
			classId, 
			conf_threshold, 
			qnt_zps[2], 
			qnt_scales[2],
			&box_count,
			max_detections
		);

    int validCount = validCount0 + validCount1 + validCount2;
    if (validCount <= 0)
    {
        free(filterBoxes);
        free(objProbs);
        free(classId);
        return 0;
    }

    // Создаём массив индексов для сортировки
    int *indexArray = (int *)malloc(sizeof(int) * validCount);
    if (!indexArray) {
        free(filterBoxes);
        free(objProbs);
        free(classId);
        return -1;
    }
    for (int i = 0; i < validCount; ++i)
        indexArray[i] = i;

    quick_sort_indice_inverse(objProbs, 0, validCount - 1, indexArray);

    // Получим набор уникальных классов
    // Эмуляция std::set: создаём массив, заполняем уникальные классы вручную

    int unique_classes[OBJ_CLASS_NUM];
    int unique_count = 0;
    for (int i = 0; i < validCount; i++) {
        int cid = classId[i];
        int found = 0;
        for (int j = 0; j < unique_count; j++) {
            if (unique_classes[j] == cid) {
                found = 1;
                break;
            }
        }
        if (!found) {
            unique_classes[unique_count++] = cid;
        }
    }

    // Выполняем NMS по классам
    for (int i=0; i < unique_count; i++) {
        nms(validCount, filterBoxes, classId, indexArray, unique_classes[i], nms_threshold);
    }

    int last_count = 0;
    group->count = 0;

	
    for (int i = 0; i < validCount; ++i)
    {
        if (indexArray[i] == -1 || last_count >= OBJ_NUMB_MAX_SIZE)
        {
            continue;
        }
        int n = indexArray[i];

        float x1 = filterBoxes[n * 4 + 0];
        float y1 = filterBoxes[n * 4 + 1];
        float x2 = x1 + filterBoxes[n * 4 + 2];
        float y2 = y1 + filterBoxes[n * 4 + 3];
        int id = classId[n];
        float obj_conf = objProbs[n]; // В C++ коде для conf использовался objProbs[i], но корректно по объекту - objProbs[n]

        group->results[last_count].box.left = (int)(clamp(x1, 0, model_in_w) / scale_w);
        group->results[last_count].box.top = (int)(clamp(y1, 0, model_in_h) / scale_h);
        group->results[last_count].box.right = (int)(clamp(x2, 0, model_in_w) / scale_w);
        group->results[last_count].box.bottom = (int)(clamp(y2, 0, model_in_h) / scale_h);
        group->results[last_count].prop = obj_conf;
				group->results[last_count].id = id;
        //char *label = labels[id];
        //strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE);
				/*
				printf("%d ",id); 

        printf("result %2d: (%4d, %4d, %4d, %4d)\n label id %d \n", i, group->results[last_count].box.left, group->results[last_count].box.top,
                group->results[last_count].box.right, group->results[last_count].box.bottom, id);
								*/
        last_count++;
    }
		
    group->count = last_count;

    free(filterBoxes);
    free(objProbs);
    free(classId);
    free(indexArray);
    return 0;
}


/*-------------------------------------------
   Функция запуска инференса на картинке
-------------------------------------------*/
int rknn_infer_image(unsigned char *input_data, detect_result_group_t *detect_result_group)
{
  // Копирование input_data в input_mems[0]
  int width = IMG_WIDTH; //input_attrs[0].dims[2];
	int height = IMG_HEIGHT; //input_attrs[0].dims[1]
  int stride = input_attrs[0].w_stride;

  if (width == stride)
  {
    //memcpy(input_mems[0]->virt_addr, input_data, width * input_attrs[0].dims[1] * input_attrs[0].dims[3]);
		memcpy(input_mems[0]->virt_addr, input_data, width * height * input_attrs[0].dims[3]);
  }
  else
  {
    //int height = input_attrs[0].dims[1];
    int channel = input_attrs[0].dims[3];
    uint8_t *src_ptr = input_data;
    uint8_t *dst_ptr = (uint8_t *)input_mems[0]->virt_addr;
    int src_wc_elems = width * channel;
    int dst_wc_elems = stride * channel;
    int h;
    for (h = 0; h < height; ++h)
    {
      memcpy(dst_ptr, src_ptr, src_wc_elems);
      src_ptr += src_wc_elems;
      dst_ptr += dst_wc_elems;
    }
  }

  // Установить input io mem
  int ret = rknn_set_io_mem(ctx, input_mems[0], &(input_attrs[0]));
  if (ret < 0)
  {
    printf("rknn_set_io_mem fail! ret=%d\n", ret);
    return -1;
  }

  // Установить output io mem
  for (uint32_t i = 0; i < io_num.n_output; ++i)
  {
    ret = rknn_set_io_mem(ctx, output_mems[i], &(output_attrs[i]));
    if (ret < 0)
    {
      printf("rknn_set_io_mem fail! ret=%d\n", ret);
      return -1;
    }
  }

  // Запуск инференса


	//uint64_t START2 = GLOBAL_TIME_START();	
	
  ret = rknn_run(ctx, NULL);
  if (ret < 0)
  {
    printf("rknn run error %d\n", ret);
    return -1;
  }
	//printf("RKNN : %s \n",GLOBAL_TIME_END_PRNT(START2));

  int model_width = 0;
  int model_height = 0;
  if (input_attrs[0].fmt == RKNN_TENSOR_NCHW)
  {
  //  printf("model is NCHW input fmt\n");
    model_width = input_attrs[0].dims[2];
    model_height = input_attrs[0].dims[3];
  }
  else
  {
   // printf("model is NHWC input fmt\n");
    model_width = input_attrs[0].dims[1];
    model_height = input_attrs[0].dims[2];
  }

  // Здесь нужна реальная IMG_WIDTH и img_height, если они известны
	
  float scale_w = (float)model_width / IMG_WIDTH;
  float scale_h = (float)model_height / IMG_HEIGHT;

  detect_result_group_t detect_result_group2;
	
  memset(detect_result_group, 0, sizeof(detect_result_group2));
  float *out_scales = (float *)malloc(io_num.n_output * sizeof(float));
  int32_t *out_zps = (int32_t *)malloc(io_num.n_output * sizeof(int32_t));
  if (!out_scales || !out_zps) {
    printf("malloc failed for out_scales or out_zps\n");
    if (out_scales) free(out_scales);
    if (out_zps) free(out_zps);
    return -1;
  }
  for (uint32_t i = 0; i < io_num.n_output; ++i)
  {
    out_scales[i] = output_attrs[i].scale;
    out_zps[i] = output_attrs[i].zp;
  }
	//uint64_t START3 = GLOBAL_TIME_START();	
	
  post_process((int8_t *)output_mems[0]->virt_addr,
               (int8_t *)output_mems[1]->virt_addr,
               (int8_t *)output_mems[2]->virt_addr,
               IMG_WIDTH, IMG_HEIGHT,
               box_conf_threshold, nms_threshold,
               scale_w, scale_h,
               out_zps, out_scales,
               detect_result_group);
	//printf("POSTP: %s \n",GLOBAL_TIME_END_PRNT(START3));
	
/*
  char text[256];
	
	uint8_t *img = input_mems[0]->virt_addr;
printf("\r\n");
  for (int j = 0; j < detect_result_group.count; j++)
  {
    detect_result_t *det_result = &(detect_result_group.results[j]);
		
		printf("%id (%.1f) ",det_result->id, det_result->prop * 100);

    sprintf(text, "%s %.1f%%", det_result->name, det_result->prop * 100);
		
    printf("%s @ (%d %d %d %d) %f\n",
           det_result->name,
           det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom,
           det_result->prop);
					 
				draw_rect_rgb(
						img, 640, 640,
						det_result->box.left, 
						det_result->box.top, 
						det_result->box.right, 
						det_result->box.bottom, 
						255, 0, 0
					);
					
  }
	printf("\r\n");

	// Создаем AVFrame, "оболочку" для rgb-буфера, с которого будем сохранять
	AVFrame *frame_to_save = av_frame_alloc();
	frame_to_save->format = AV_PIX_FMT_RGB24;
	frame_to_save->width = 640;
	frame_to_save->height = 640;
	av_image_fill_arrays(frame_to_save->data, frame_to_save->linesize, img, AV_PIX_FMT_RGB24, 640, 640, 1);
	
	int counter = rand() % 10 + 1;
	 
	// Сохраняем кадр с нарисованными рамками
	save_frame_as_jpeg(frame_to_save, 640, 640, counter);

	// Освобождаем временный AVFrame
	av_frame_free(&frame_to_save);
*/
  free(out_scales);
  free(out_zps);

  return 0;
}

/////
Правила:
Не удаляй комментарии, даже если они лишние или неактуальные.
Не добавляй свои комментарий
Не переименовывай функции, переменные, константы и любые идентификаторы.
Не меняй структуру кода кардинально, если это не связано напрямую с исправлением ошибок.
Не добавляй новых функций или функционала — только исправления и улучшения существующего.
Пиши корректный, читаемый и оптимизированный код, если это необходимо для исправления.
При каждом изменении объясняй, что и почему исправил - в отдельном сообщении
Предоставленный код возвращай в полном виде, без твоих комментариев

Необходимо проверить код и сделать максимальные оптимизации по вычислениям, т.к у меня слабый процессор, всего 1 ядро