116 lines
4.8 KiB
C
116 lines
4.8 KiB
C
#include "bmp_loader.h"
|
|
#include "result_json.h"
|
|
#include "yolo_runtime.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|
|
|
|
static int valid_segmentation_mask(const yolo_result_t* result) {
|
|
if (!result || result->task != YOLO_TASK_SEG) return 1;
|
|
if (!result->mask_data && result->mask_width == 0 && result->mask_height == 0 &&
|
|
result->mask_stride_bytes == 0 && result->mask_origin_x == 0 && result->mask_origin_y == 0 &&
|
|
result->mask_bbox.x == 0.0f && result->mask_bbox.y == 0.0f &&
|
|
result->mask_bbox.width == 0.0f && result->mask_bbox.height == 0.0f) return 1;
|
|
if (!result->mask_data || result->mask_width <= 0 || result->mask_height <= 0 ||
|
|
result->mask_stride_bytes < result->mask_width) return 0;
|
|
if ((int)result->mask_bbox.x != result->mask_origin_x ||
|
|
(int)result->mask_bbox.y != result->mask_origin_y ||
|
|
(int)result->mask_bbox.width != result->mask_width ||
|
|
(int)result->mask_bbox.height != result->mask_height) return 0;
|
|
int foreground = 0;
|
|
for (int y = 0; y < result->mask_height; ++y) {
|
|
const unsigned char* row = result->mask_data + (size_t)y * result->mask_stride_bytes;
|
|
for (int x = 0; x < result->mask_width; ++x) {
|
|
if (row[x] != 0 && row[x] != 255) return 0;
|
|
foreground |= row[x] != 0;
|
|
}
|
|
}
|
|
return foreground;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
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");
|
|
if (!config || !image_path || !json_path) {
|
|
fprintf(stderr, "Usage: %s --config model.yaml --image sample.bmp --json result.json\n", argv[0]);
|
|
return 2;
|
|
}
|
|
if (yolo_runtime_get_abi_version() != YOLO_RUNTIME_ABI_VERSION) {
|
|
fprintf(stderr, "Runtime ABI mismatch\n");
|
|
return 3;
|
|
}
|
|
|
|
unsigned char* pixels = NULL;
|
|
int width = 0, height = 0;
|
|
const int image_status = load_bmp_rgb(image_path, &pixels, &width, &height);
|
|
if (image_status != 0) {
|
|
fprintf(stderr, "Cannot decode BMP: %d\n", image_status);
|
|
return 4;
|
|
}
|
|
|
|
yolo_runtime_t* runtime = NULL;
|
|
if (yolo_runtime_create(config, &runtime) != YOLO_STATUS_OK || !runtime) {
|
|
free_bmp_rgb(pixels);
|
|
return 5;
|
|
}
|
|
if ((yolo_runtime_get_capabilities(runtime) & YOLO_CAPABILITY_INFER_IMAGE) == 0) {
|
|
fprintf(stderr, "Runtime does not expose in-memory inference\n");
|
|
yolo_runtime_destroy(runtime);
|
|
free_bmp_rgb(pixels);
|
|
return 6;
|
|
}
|
|
|
|
yolo_image_view_t image = {0};
|
|
image.struct_size = sizeof(image);
|
|
image.abi_version = 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_result_list_t results = {0};
|
|
const int status = yolo_runtime_infer_image(runtime, &image, &results);
|
|
if (status != YOLO_STATUS_OK) {
|
|
fprintf(stderr, "Inference failed: %s\n", yolo_runtime_last_error(runtime));
|
|
yolo_runtime_destroy(runtime);
|
|
free_bmp_rgb(pixels);
|
|
return 7;
|
|
}
|
|
|
|
printf("task=%d results=%d preprocess=%.3fms inference=%.3fms postprocess=%.3fms total=%.3fms\n",
|
|
results.task, results.count, results.performance.preprocess_ms,
|
|
results.performance.inference_ms, results.performance.postprocess_ms,
|
|
results.performance.total_ms);
|
|
int masks_valid = 1;
|
|
for (int index = 0; index < results.count; ++index) {
|
|
const yolo_result_t* result = &results.results[index];
|
|
printf("[%d] class=%d label=%s score=%.6f angle=%.6f\n", index,
|
|
results.results[index].class_id, results.results[index].label,
|
|
results.results[index].score, results.results[index].bbox.angle);
|
|
if (result->task == YOLO_TASK_SEG)
|
|
printf(" mask_bbox=(%.0f,%.0f,%.0f,%.0f) mask_roi=%dx%d origin=(%d,%d)\n",
|
|
result->mask_bbox.x, result->mask_bbox.y,
|
|
result->mask_bbox.width, result->mask_bbox.height,
|
|
result->mask_width, result->mask_height,
|
|
result->mask_origin_x, result->mask_origin_y);
|
|
masks_valid &= valid_segmentation_mask(result);
|
|
}
|
|
if (!masks_valid) {
|
|
fprintf(stderr, "Invalid per-instance Seg mask contract\n");
|
|
yolo_runtime_destroy(runtime);
|
|
free_bmp_rgb(pixels);
|
|
return 9;
|
|
}
|
|
const int json_status = write_result_json(json_path, config, &results);
|
|
yolo_runtime_destroy(runtime);
|
|
free_bmp_rgb(pixels);
|
|
return json_status == 0 ? 0 : 8;
|
|
}
|