#include "result_json.h" #include static const char* task_name(yolo_task_type_t task) { switch (task) { case YOLO_TASK_SEG: return "seg"; case YOLO_TASK_CLS: return "cls"; case YOLO_TASK_OBB: return "obb"; case YOLO_TASK_POSE: return "pose"; default: return "detect"; } } static void write_escaped(FILE* file, const char* text) { for (const unsigned char* cursor = (const unsigned char*)text; cursor && *cursor; ++cursor) { if (*cursor == '"' || *cursor == '\\') fputc('\\', file); if (*cursor >= 0x20) fputc(*cursor, file); } } int write_result_json(const char* path, const char* model_config, const yolo_result_list_t* report) { if (!path || !model_config || !report) return -1; FILE* file = fopen(path, "wb"); if (!file) return -2; fprintf(file, "{\n \"schemaVersion\": \"1\",\n \"model\": \""); write_escaped(file, model_config); fprintf(file, "\",\n \"task\": \"%s\",\n", task_name(report->task)); fprintf(file, " \"performance\": {\"preprocessMs\": %.3f, \"inferenceMs\": %.3f, \"postprocessMs\": %.3f, \"totalMs\": %.3f},\n", report->performance.preprocess_ms, report->performance.inference_ms, report->performance.postprocess_ms, report->performance.total_ms); fprintf(file, " \"results\": ["); for (int index = 0; index < report->count; ++index) { const yolo_result_t* result = &report->results[index]; fprintf(file, "%s\n {\"task\": \"%s\", \"classId\": %d, \"label\": \"", index ? "," : "", task_name(result->task), result->class_id); write_escaped(file, result->label); fprintf(file, "\", \"score\": %.6f", result->score); if (result->task != YOLO_TASK_CLS) { fprintf(file, ", \"bbox\": {\"x\": %.3f, \"y\": %.3f, \"width\": %.3f, \"height\": %.3f", result->bbox.x, result->bbox.y, result->bbox.width, result->bbox.height); if (result->bbox.has_angle) fprintf(file, ", \"angle\": %.6f", result->bbox.angle); fputc('}', file); } if (result->task == YOLO_TASK_SEG) { fprintf(file, ", \"maskBBox\": {\"x\": %.3f, \"y\": %.3f, \"width\": %.3f, \"height\": %.3f}", result->mask_bbox.x, result->mask_bbox.y, result->mask_bbox.width, result->mask_bbox.height); fprintf(file, ", \"mask\": {\"width\": %d, \"height\": %d, \"strideBytes\": %d, \"originX\": %d, \"originY\": %d}", result->mask_width, result->mask_height, result->mask_stride_bytes, result->mask_origin_x, result->mask_origin_y); } if (result->task == YOLO_TASK_POSE) { fputs(", \"keypoints\": [", file); for (int keypoint = 0; keypoint < result->keypoint_count; ++keypoint) { fprintf(file, "%s{\"x\": %.3f, \"y\": %.3f, \"score\": %.6f}", keypoint ? "," : "", result->keypoints[keypoint].x, result->keypoints[keypoint].y, result->keypoints[keypoint].score); } fputc(']', file); } fputc('}', file); } fprintf(file, "%s ]\n}\n", report->count ? "\n" : ""); fclose(file); return 0; }