Вот функция поиска номеров из RKNN


typedef struct _BOX_RECT
{
int left;
int right;
int top;
int bottom;
} BOX_RECT;


typedef struct {
BOX_RECT box;
int id;
float p;
} box_t;


typedef struct __detect_result_t
{
char name[OBJ_NAME_MAX_SIZE];
BOX_RECT box;
float prop;
int id;
} detect_result_t;


typedef struct _detect_result_group_t
{
int id;
int count;
detect_result_t results[OBJ_NUMB_MAX_SIZE];
} detect_result_group_t;


void _FIND_NUMBER(detect_result_group_t grp, int thread_id, int queue)
{
/ --- разделяем «рамки номера» и «символы» --------------------- */
box_t plates [MAX_FRAME_OBJS];
box_t symbols[MAX_FRAME_OBJS];
size_t n_plate = 0, n_sym = 0;
//printf("\r\n\r\n\r\n----------\r\n");
for (int i = 0; i < grp->count; ++i) {
detect_result_t *r = &grp->results[i];


    box_t o = { r->box, r->id, r->prop };
		
    if (r->id == 0) {
				plates [n_plate] = o;
				n_plate++;
				  //printf("!! %c (%f) (%d-%d)\r\n",class_names[r->id][0],r->prop, r->box.left, r->box.right);
			} else {
			 if (r->prop < CONF_THRESHOLD || r->id >= (int)NUM_CLASSES) {
				 continue;
			 } else {
				  //printf("%c (%f) (%d-%d)\r\n",class_names[r->id][0],r->prop, r->box.left, r->box.right);
					symbols[n_sym] = o;
					n_sym++;
				 }
			}
}
//printf("-----0-----\r\n");
if (!n_plate || n_sym < MIN_SYMBOLS) {
			printf("					%d %s n_plate\n",thread_id, GLOBAL_TIME_PRINT());

		return;
	}

// --- для каждой рамки номера ---------------------------------- 
for (size_t pi = 0; pi < n_plate; ++pi)
{
    /* собрать символы, центр которых лежит внутри рамки */
    box_t in[MAX_FRAME_OBJS]; size_t in_cnt = 0;
    in[in_cnt++] = plates[pi];   /* сама рамка */

    for (size_t si = 0; si < n_sym; ++si) {
        box_t *s = &symbols[si];
        float cx = (s->box.left + s->box.right)/2.f;
        float cy = (s->box.top  + s->box.bottom)/2.f;
        if (cx >= plates[pi].box.left  && cx <= plates[pi].box.right &&
            cy >= plates[pi].box.top   && cy <= plates[pi].box.bottom)
            in[in_cnt++] = *s;
    }
    if (in_cnt < MIN_SYMBOLS + 1) {
				printf("					%d %s MIN_SYMBOLS\n",thread_id, GLOBAL_TIME_PRINT());
				continue;
			}

    /* сортировать по X для корректного чтения слева-направо */
    qsort(in, in_cnt, sizeof(box_t), cmp_center_x);
			//printf("-----1------\r\n");
    /* разложить на 1–2 строки */
    box_t row1[MAX_FRAME_OBJS], row2[MAX_FRAME_OBJS];
    size_t n1 = 0, n2 = 0;
    for (size_t k = 0; k < in_cnt; ++k) {
        if (in[k].id == 0) continue;          /* пропустить «plate» */

        if (!n1 || same_row(&in[k].box, &row1[n1-1].box)) {
				
            row1[n1++] = in[k];
					}
        else
            row2[n2++] = in[k];
    }
			//printf("-----2------\r\n");
    /* если две строки, row1 должна быть верхней */
    if (n2) {
        float y1 = (row1[0].box.top + row1[0].box.bottom)/2.f;
        float y2 = (row2[0].box.top + row2[0].box.bottom)/2.f;
        if (y1 > y2) {   /* поменять местами */
            box_t tmp[MAX_FRAME_OBJS]; size_t nt = n1;
            memcpy(tmp,  row1, sizeof(box_t)*n1);
            memcpy(row1, row2, sizeof(box_t)*n2);
            memcpy(row2, tmp,  sizeof(box_t)*nt);
            size_t ns = n1; n1 = n2; n2 = ns;
        }
    }

    /* собрать строку номера */
    char plate[MAX_PLATE_LEN]=""; size_t pos = 0;
    for (size_t i = 0; i < n1 && pos < MAX_PLATE_LEN-1; ++i) {
        plate[pos++] = class_names[row1[i].id][0];
					
				//	printf("%c (%f) (%d-%d)\r\n",class_names[row1[i].id][0], row1[i].p,  row1[i].box.left, row1[i].box.right);
           
			}
    for (size_t i = 0; i < n2 && pos < MAX_PLATE_LEN-1; ++i) {
        plate[pos++] = class_names[row2[i].id][0];
			}
    plate[pos] = '\0';
			

			if (pos < 7) {
				printf("					%s NO PLATE\n", GLOBAL_TIME_PRINT());
				continue;
			}

			printf("%d %s xx: %-11s  %d -> %d\r\n\r\n",thread_id, GLOBAL_TIME_PRINT(),  plate,  thread_id, queue);

}

}


рузальтат такой
C81810AAB1B1966


Надо поправить функцибию чтобы убирали дублки боксов