#include "bmp_loader.h" #include "result_json.h" #include "yolo_runtime.h" #include "mask_dilation.h" #include #include #include #include static const char* value_after(int argc, char** argv, const char* option) { for (int index = 1; index + 1 < argc; ++index) if (strcmp(argv[index], option) == 0) return argv[index + 1]; return NULL; } int main(int argc, char** argv) { int dilation_radius=0; if(parse_mask_dilation(argc,argv,&dilation_radius)!=0) {fprintf(stderr,"Invalid --mask-dilation: integer 0..100 required\n");return 2;} const char* config = value_after(argc, argv, "--config"); const char* image_path = value_after(argc, argv, "--image"); const char* json_path = value_after(argc, argv, "--json"); const char* geometry_name = value_after(argc, argv, "--seg-geometry"); if (!config || !image_path || !json_path) { fprintf(stderr, "Usage: %s --config model.yaml --image sample.bmp --json result.json [--seg-geometry rect|circle|mean|fit] [--rgb-mask] [--mask-dilation 0..100] [--roi-lt L T | --roi-whlt W H L T]\n", argv[0]); return 2; } if(geometry_name && strcmp(geometry_name,"rect") && strcmp(geometry_name,"circle") && strcmp(geometry_name,"mean") && strcmp(geometry_name,"fit")) return 2; if (yolo_runtime_get_abi_version() != YOLO_RUNTIME_ABI_VERSION) return 3; unsigned char* pixels = NULL; int width = 0, height = 0; if (load_bmp_rgb(image_path, &pixels, &width, &height) != 0) return 4; yolo_error_info_v1_t error = {sizeof(error), YOLO_ERROR_INFO_VERSION}; yolo_runtime_t* runtime = NULL; if (yolo_runtime_create(config, &runtime, &error) != YOLO_STATUS_OK || !runtime) { fprintf(stderr, "Create failed: %s\n", error.message); free_bmp_rgb(pixels); return 5; } yolo_runtime_info_v1_t info = {sizeof(info), YOLO_RUNTIME_INFO_VERSION}; if (yolo_runtime_get_info(runtime, &info) != YOLO_STATUS_OK) return 6; if(dilation_radius && info.task!=YOLO_TASK_SEG) {yolo_runtime_destroy(runtime);free_bmp_rgb(pixels);return 2;} yolo_image_view_v1_t image = {sizeof(image), YOLO_IMAGE_VIEW_ABI_VERSION}; image.data = pixels; image.width = width; image.height = height; image.row_stride_bytes = width * 3; image.pixel_format = YOLO_PIXEL_FORMAT_RGB888; yolo_infer_options_v1_t options = {sizeof(options), YOLO_INFER_OPTIONS_VERSION}; options.seg_geometry_mode = info.task == YOLO_TASK_SEG ? (geometry_name && strcmp(geometry_name, "circle") == 0 ? YOLO_SEG_GEOMETRY_MIN_ENCLOSING_CIRCLE : (geometry_name && strcmp(geometry_name,"mean")==0 ? YOLO_SEG_GEOMETRY_MEAN_DIAMETER_CIRCLE : (geometry_name && strcmp(geometry_name,"fit")==0 ? YOLO_SEG_GEOMETRY_ROBUST_FIT_CIRCLE : YOLO_SEG_GEOMETRY_MIN_AREA_RECT))) : YOLO_SEG_GEOMETRY_NONE; /* ROI 默认数据:W=800(宽)、H=736(高)、L=0(左)、T=0(上),单位为原图像素。 默认初始化填写结构体大小、版本并清零保留字段,ABI 5 的字段顺序不变。 */ yolo_roi_v1_t roi = yolo_roi_default(); int roi_values[4] = {0}; const int roi_mode = parse_example_roi_args(argc, argv, roi_values); int has_roi = roi_mode; if (roi_mode == 1) { /* 只提供 L、T:保留默认宽高 800×736,只修改左上角位置。 */ roi.x = roi_values[0]; /* L:例如 --roi-lt 217 738 中的 217。 */ roi.y = roi_values[1]; /* T:例如 --roi-lt 217 738 中的 738。 */ } else if (roi_mode == 2) { /* 完整指定 W、H、L、T;例如 --roi-whlt 771 609 217 738。 */ roi = yolo_roi_from_whlt(roi_values[0], roi_values[1], roi_values[2], roi_values[3]); } else if (roi_mode == 0) { /* 未传 ROI 参数时读取模型 roi_info.txt;不存在则全图推理, 不会因为默认初始化而自动裁剪为 800×736。 */ has_roi = load_model_roi(config, width, height, &roi); } /* ROI 越界或宽高非正时由推理接口报错,不自动裁边。 */ if (has_roi < 0) { fprintf(stderr, "Invalid ROI arguments, roi_info.txt or source image dimensions\n"); yolo_runtime_destroy(runtime); free_bmp_rgb(pixels); return 7; } if (has_roi) printf("ROI W=%d H=%d L=%d T=%d\n", roi.width, roi.height, roi.x, roi.y); yolo_result_set_t* results = NULL; error = (yolo_error_info_v1_t){sizeof(error), YOLO_ERROR_INFO_VERSION}; const yolo_status_t status = yolo_runtime_infer_image_roi(runtime, &image, has_roi ? &roi : NULL, &options, &results, &error); if (status != YOLO_STATUS_OK || !results) { fprintf(stderr, "Inference failed: %s\n", error.message); yolo_runtime_destroy(runtime); free_bmp_rgb(pixels); return 7; } uint32_t count = 0; yolo_result_set_get_count(results, &count); printf("task=%d results=%u\n", info.task, count); yolo_mask_view_v1_t masks[255]; unsigned char* owned_masks[255]={0}; memset(masks,0,sizeof(masks)); const yolo_roi_v1_t region=has_roi?roi:yolo_roi_from_whlt(width,height,0,0); int mask_status=0; /* Seg always demonstrates in-memory RGB IDs; --rgb-mask remains accepted. */ if(info.task==YOLO_TASK_SEG) { if(count>255) {fprintf(stderr,"RGB supports at most 255 instances\n");mask_status=-1;} for(uint32_t i=0;iINT_MAX || bytes>SIZE_MAX) mask_status=-1; if(mask_status==0) { rgb=(unsigned char*)malloc((size_t)bytes); if(!rgb) mask_status=-1; } if(mask_status==0) { error=(yolo_error_info_v1_t){sizeof(error),YOLO_ERROR_INFO_VERSION}; if(yolo_masks_compose_rgb_ids(masks,count,width,height,rgb,(int32_t)stride,bytes,&error)!=YOLO_STATUS_OK) { fprintf(stderr,"RGB mask failed: %s\n",error.message);mask_status=-1; } else { uint64_t foreground=0,instance_pixels[256]={0}; for(int y=0;y