| 17 | #include <cstring> |
| 18 | |
| 19 | int main(int argc, char** argv) { |
| 20 | if (argc < 3) { |
| 21 | fprintf(stderr, "Usage: %s <sam2_model.ggml> <image.jpg>\n", argv[0]); |
| 22 | return 1; |
| 23 | } |
| 24 | |
| 25 | sam3_params p; |
| 26 | p.model_path = argv[1]; |
| 27 | p.n_threads = 4; |
| 28 | p.use_gpu = false; |
| 29 | |
| 30 | auto model = sam3_load_model(p); |
| 31 | if (!model) { fprintf(stderr, "FAIL: cannot load model\n"); return 1; } |
| 32 | |
| 33 | // Must be a SAM2 model |
| 34 | auto mt = sam3_get_model_type(*model); |
| 35 | if (mt != SAM3_MODEL_SAM2) { |
| 36 | fprintf(stderr, "SKIP: not a SAM2 model (type=%d)\n", mt); |
| 37 | return 0; |
| 38 | } |
| 39 | |
| 40 | auto state = sam3_create_state(*model, p); |
| 41 | if (!state) { fprintf(stderr, "FAIL: cannot create state\n"); return 1; } |
| 42 | |
| 43 | // Load and encode image |
| 44 | auto image = sam3_load_image(argv[2]); |
| 45 | if (image.data.empty()) { fprintf(stderr, "FAIL: cannot load image\n"); return 1; } |
| 46 | fprintf(stderr, "Image: %dx%d\n", image.width, image.height); |
| 47 | |
| 48 | if (!sam3_encode_image(*state, *model, image)) { |
| 49 | fprintf(stderr, "FAIL: image encoding failed\n"); |
| 50 | return 1; |
| 51 | } |
| 52 | |
| 53 | // Run PVS with a point at the center of the image |
| 54 | float cx = image.width / 2.0f; |
| 55 | float cy = image.height / 2.0f; |
| 56 | fprintf(stderr, "Point: (%.0f, %.0f)\n", cx, cy); |
| 57 | |
| 58 | sam3_pvs_params pvs; |
| 59 | pvs.pos_points.push_back({cx, cy}); |
| 60 | pvs.multimask = false; // single mask — same as GUI default |
| 61 | |
| 62 | auto result = sam3_segment_pvs(*state, *model, pvs); |
| 63 | |
| 64 | // ── Test 1: Must produce exactly 1 detection ── |
| 65 | if (result.detections.empty()) { |
| 66 | fprintf(stderr, "FAIL: no detections returned\n"); |
| 67 | return 1; |
| 68 | } |
| 69 | fprintf(stderr, "Detections: %zu\n", result.detections.size()); |
| 70 | |
| 71 | auto& det = result.detections[0]; |
| 72 | fprintf(stderr, "Mask 0: iou=%.4f, mask=%dx%d\n", |
| 73 | det.iou_score, det.mask.width, det.mask.height); |
| 74 | |
| 75 | // ── Test 2: IoU score must be reasonable (> 0.1) ── |
| 76 | // A garbage PE grid produces IoU near 0 or random values |
nothing calls this directly
no test coverage detected