static char *run_failure_tests(catcierge_haar_prey_method_t prey_method) { int i; int j; catcierge_grb_t grb; catcierge_args_t *args = &grb.args; catcierge_grabber_init(&grb); catcierge_haar_matcher_args_init(&args->haar); args->saveimg = 0; args->matcher = "haar"; args->matcher_type = MATCHER_HAAR; args->ok_matches_needed = 3; args->haar.prey_method = prey_method; args->haar.prey_steps = 2; args->haar.cascade = CATCIERGE_CASCADE; #ifdef CATCIERGE_GUI_TESTS args->show = 1; #endif //args->save_steps = 1; //args->saveimg = 1; if (catcierge_matcher_init(&grb.matcher, (catcierge_matcher_args_t *)&args->haar)) { return "Failed to init catcierge lib!\n"; } catcierge_haar_matcher_print_settings(&args->haar); catcierge_set_state(&grb, catcierge_state_waiting); for (j = 10; j <= 14; j++) { catcierge_test_STATUS("Test series %d", j); // This is the initial image that obstructs the frame // and triggers the matching. load_test_image_and_run(&grb, j, 1); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); // Match against 4 pictures, and decide the lockout status. for (i = 1; i <= 4; i++) { load_test_image_and_run(&grb, j, i); } mu_assert("Expected LOCKOUT state", (grb.state == catcierge_state_lockout)); load_test_image_and_run(&grb, 1, 5); mu_assert("Expected WAITING state", (grb.state == catcierge_state_waiting)); } catcierge_matcher_destroy(&grb.matcher); catcierge_grabber_destroy(&grb); return NULL; }
static char *run_save_steps_test() { catcierge_grb_t grb; catcierge_args_t *args = &grb.args; catcierge_grabber_init(&grb); args->matcher_type = MATCHER_HAAR; args->ok_matches_needed = 3; catcierge_haar_matcher_args_init(&args->haar); args->haar.prey_method = PREY_METHOD_ADAPTIVE; args->haar.prey_steps = 2; args->haar.cascade = CATCIERGE_CASCADE; args->save_steps = 1; args->saveimg = 1; args->output_path = "./test_save_steps"; catcierge_make_path(args->output_path); if (catcierge_matcher_init(&grb.matcher, (catcierge_matcher_args_t *)&args->haar)) { return "Failed to init catcierge lib!\n"; } catcierge_test_STATUS("Test save steps"); catcierge_set_state(&grb, catcierge_state_waiting); // This is the initial image that obstructs the frame // and triggers the matching. load_test_image_and_run(&grb, 1, 1); // Some normal images. load_test_image_and_run(&grb, 10, 1); catcierge_test_STATUS("Step image count: %d", grb.match_group.matches[0].result.step_img_count); mu_assert("Expected 10 step images", grb.match_group.matches[0].result.step_img_count == 11); load_test_image_and_run(&grb, 10, 2); catcierge_test_STATUS("Step image count: %d", grb.match_group.matches[1].result.step_img_count); mu_assert("Expected 10 step images", grb.match_group.matches[1].result.step_img_count == 11); load_test_image_and_run(&grb, 6, 2); // Going out. catcierge_test_STATUS("Step image count: %d", grb.match_group.matches[2].result.step_img_count); mu_assert("Expected 4 step images", grb.match_group.matches[2].result.step_img_count == 4); mu_assert("Got NULL image for used step image", grb.match_group.matches[2].result.steps[2].img != NULL); mu_assert("Got non-NULL image for unused step image", grb.match_group.matches[2].result.steps[4].img == NULL); load_test_image_and_run(&grb, 10, 1); catcierge_test_STATUS("Step image count: %d", grb.match_group.matches[3].result.step_img_count); mu_assert("Expected 10 step images", grb.match_group.matches[3].result.step_img_count == 11); catcierge_matcher_destroy(&grb.matcher); catcierge_grabber_destroy(&grb); return NULL; }
static char *run_success_tests() { int i; int j; catcierge_grb_t grb; catcierge_args_t *args = &grb.args; catcierge_grabber_init(&grb); catcierge_args_init_vars(args); catcierge_haar_matcher_args_init(&args->haar); args->saveimg = 0; args->matcher_type = MATCHER_HAAR; args->haar.cascade = strdup(CATCIERGE_CASCADE); if (catcierge_matcher_init(&grb.matcher, (catcierge_matcher_args_t *)&args->haar)) { return "Failed to init catcierge lib!\n"; } catcierge_haar_matcher_print_settings(&args->haar); grb.running = 1; catcierge_set_state(&grb, catcierge_state_waiting); for (j = 6; j <= 9; j++) { catcierge_test_STATUS("Test series %d", j); // This is the initial image that obstructs the frame // and triggers the matching. load_test_image_and_run(&grb, j, 1); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); // Match against 4 pictures, and decide the lockout status. for (i = 1; i <= 4; i++) { load_test_image_and_run(&grb, j, i); } mu_assert("Expected KEEP OPEN state", (grb.state == catcierge_state_keepopen)); load_test_image_and_run(&grb, 1, 5); mu_assert("Expected WAITING state", (grb.state == catcierge_state_waiting)); } catcierge_matcher_destroy(&grb.matcher); catcierge_args_destroy_vars(args); catcierge_grabber_destroy(&grb); return NULL; }
// // Tests passing 1 initial image that triggers matching. // Then pass 4 images that should result in a successful match. // Finally if "obstruct" is set, a single image is passed that obstructs the frame. // After that we expect to go back to waiting. // static char *run_success_tests(int obstruct) { int i; int j; catcierge_grb_t grb; catcierge_args_t *args = &grb.args; catcierge_grabber_init(&grb); grb.running = 1; args->matcher = "template"; args->matcher_type = MATCHER_TEMPLATE; args->saveimg = 0; args->templ.match_flipped = 1; args->templ.match_threshold = 0.8; args->templ.snout_paths[0] = CATCIERGE_SNOUT1_PATH; args->templ.snout_count++; args->templ.snout_paths[1] = CATCIERGE_SNOUT2_PATH; args->templ.snout_count++; if (catcierge_matcher_init(&grb.matcher, (catcierge_matcher_args_t *)&args->templ)) { return "Failed to init catcierge lib!\n"; } catcierge_template_matcher_set_debug((catcierge_template_matcher_t *)grb.matcher, 0); catcierge_template_matcher_print_settings(&args->templ); catcierge_set_state(&grb, catcierge_state_waiting); // Give the state machine a series of known images // and make sure the states are as expected. for (j = 1; j <= 5; j++) { catcierge_test_STATUS("Test series %d", j); // This is the initial image that obstructs the frame // and triggers the matching. load_test_image_and_run(&grb, j, 1); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); // Match against 4 pictures, and decide the lockout status. for (i = 1; i <= 4; i++) { load_test_image_and_run(&grb, j, i); } mu_assert("Expected KEEP OPEN state", (grb.state == catcierge_state_keepopen)); if (obstruct) { // First obstruct the frame. load_test_image_and_run(&grb, j, 1); mu_assert("Expected KEEP OPEN state", (grb.state == catcierge_state_keepopen)); // And then clear it. load_test_image_and_run(&grb, 1, 5); mu_assert("Expected WAITING state", (grb.state == catcierge_state_waiting)); } else { // Give it a clear frame so that it will stop load_test_image_and_run(&grb, 1, 5); mu_assert("Expected WAITING state", (grb.state == catcierge_state_waiting)); } } catcierge_template_matcher_destroy(&grb.matcher); catcierge_grabber_destroy(&grb); return NULL; }
static char *run_failure_tests(int obstruct, catcierge_lockout_method_t lockout_method) { char *e = NULL; size_t i; catcierge_grb_t grb; catcierge_args_t *args = &grb.args; catcierge_grabber_init(&grb); grb.running = 1; args->saveimg = 0; args->lockout_method = lockout_method; args->lockout_time = 2; args->matcher = "template"; args->matcher_type = MATCHER_TEMPLATE; args->templ.match_flipped = 1; args->templ.match_threshold = 0.8; set_default_test_snouts(args); if (catcierge_matcher_init(&grb.matcher, (catcierge_matcher_args_t *)&args->templ)) { return "Failed to init catcierge lib!\n"; } catcierge_template_matcher_print_settings(&args->templ); catcierge_set_state(&grb, catcierge_state_waiting); // // Run the same twice so we're sure the timers work // several times properly. // for (i = 0; i < 2; i++) { // Obstruct the frame to begin matching. load_test_image_and_run(&grb, 1, 2); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); // Pass 4 frames (first ok, the rest not...) load_test_image_and_run(&grb, 1, 2); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); load_test_image_and_run(&grb, 1, 3); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); load_test_image_and_run(&grb, 1, 4); mu_assert("Expected MATCHING state", (grb.state == catcierge_state_matching)); load_test_image_and_run(&grb, 1, 4); mu_assert("Expected LOCKOUT state", (grb.state == catcierge_state_lockout)); catcierge_test_STATUS("Lockout state as expected"); // Test the lockout logic. if ((e = run_lockout_tests(&grb, obstruct, lockout_method))) { return e; } } catcierge_matcher_destroy(&grb.matcher); catcierge_grabber_destroy(&grb); return NULL; }
int main(int argc, char **argv) { int ret = 0; catcierge_matcher_t *matcher = NULL; char *img_paths[4096]; IplImage *imgs[4096]; size_t img_count = 0; IplImage *img = NULL; CvSize img_size; CvScalar match_color; int match_success = 0; double match_res = 0; int debug = 0; int i; int j; int show = 0; int save = 0; char *output_path = "output"; double match_threshold = 0.8; int success_count = 0; int preload = 0; int test_matchable = 0; const char *matcher_str = NULL; match_result_t result; clock_t start; clock_t end; catcierge_template_matcher_args_t args; catcierge_haar_matcher_args_t hargs; char *key = NULL; char *values[4096]; size_t value_count = 0; memset(&args, 0, sizeof(args)); memset(&result, 0, sizeof(result)); fprintf(stderr, "Catcierge Image match Tester (C) Joakim Soderberg 2013-2014\n"); if (argc < 4) { fprintf(stderr, "Usage: %s\n" " [--output [path]]\n" " [--debug]\n" " [--show]\n" " [--match_flipped <0|1>]\n" " [--threshold]\n" " [--preload]\n" " [--test_matchable]\n" " [--snout <snout images for template matching>]\n" " [--cascade <haar cascade xml>]\n" " --images <input images>\n" " --matcher <template|haar>\n", argv[0]); return -1; } catcierge_haar_matcher_args_init(&hargs); catcierge_template_matcher_args_init(&args); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--show")) { show = 1; continue; } else if (!strcmp(argv[i], "--output")) { save = 1; if ((i + 1) < argc) { if (strncmp(argv[i+1], "--", 2)) { i++; output_path = argv[i]; } } continue; } else if (!strcmp(argv[i], "--test_matchable") || !strcmp(argv[i], "--test_obstructed")) { test_matchable = 1; preload = 1; } else if (!strcmp(argv[i], "--debug")) { debug = 1; } else if (!strcmp(argv[i], "--images")) { while (((i + 1) < argc) && strncmp(argv[i+1], "--", 2)) { i++; img_paths[img_count] = argv[i]; img_count++; } } else if (!strcmp(argv[i], "--preload")) { if ((i + 1) < argc) { i++; preload = 1; continue; } } else if (!strcmp(argv[i], "--matcher")) { if ((i + 1) < argc) { if (strncmp(argv[i+1], "--", 2)) { i++; matcher_str = argv[i]; if (strcmp(matcher_str, "template") && strcmp(matcher_str, "haar")) { fprintf(stderr, "Invalid matcher type \"%s\"\n", matcher_str); return -1; } } } continue; } else if (!strncmp(argv[i], "--", 2)) { int j = i + 1; key = &argv[i][2]; memset(values, 0, value_count * sizeof(char *)); value_count = 0; // Look for values for the option. // Continue fetching values until we get another option // or there are no more options. while ((j < argc) && strncmp(argv[j], "--", 2)) { values[value_count] = argv[j]; value_count++; i++; j = i + 1; } if ((ret = parse_arg(&args, &hargs, key, values, value_count)) < 0) { fprintf(stderr, "Failed to parse command line arguments for \"%s\"\n", key); return ret; } } else { fprintf(stderr, "Unknown command line argument \"%s\"\n", argv[i]); return -1; } } if (!matcher_str) { fprintf(stderr, "You must specify a matcher type\n"); return -1; } if (!strcmp(matcher_str, "template") && (args.snout_count == 0)) { fprintf(stderr, "No snout image specified\n"); return -1; } if (!strcmp(matcher_str, "haar") && !hargs.cascade) { fprintf(stderr, "No haar cascade specified\n"); return -1; } if (img_count == 0) { fprintf(stderr, "No input image specified\n"); return -1; } // Create output directory. if (save) { catcierge_make_path("%s", output_path); } args.super.type = MATCHER_TEMPLATE; hargs.super.type = MATCHER_HAAR; if (catcierge_matcher_init(&matcher, (!strcmp(matcher_str, "template") ? (catcierge_matcher_args_t *)&args : (catcierge_matcher_args_t *)&hargs))) { fprintf(stderr, "Failed to init %s matcher.\n", matcher_str); return -1; } matcher->debug = debug; if (!matcher->is_obstructed) matcher->is_obstructed = catcierge_is_frame_obstructed; //catcierge_set_binary_thresholds(&ctx, 90, 200); // If we should preload the images or not // (Don't let file IO screw with benchmark) if (preload) { for (i = 0; i < (int)img_count; i++) { printf("Preload image %s\n", img_paths[i]); if (!(imgs[i] = cvLoadImage(img_paths[i], 1))) { fprintf(stderr, "Failed to load match image: %s\n", img_paths[i]); ret = -1; goto fail; } } } start = clock(); if (test_matchable) { for (i = 0; i < (int)img_count; i++) { // This tests if an image frame is clear or not (matchable). int frame_obstructed; if ((frame_obstructed = matcher->is_obstructed(matcher, imgs[i])) < 0) { fprintf(stderr, "Failed to detect check for matchability frame\n"); return -1; } printf("%s: Frame obstructed = %d\n", img_paths[i], frame_obstructed); if (show) { cvShowImage("image", imgs[i]); cvWaitKey(0); } } } else { for (i = 0; i < (int)img_count; i++) { match_success = 0; printf("---------------------------------------------------\n"); printf("%s:\n", img_paths[i]); if (preload) { img = imgs[i]; } else { if (!(img = cvLoadImage(img_paths[i], 1))) { fprintf(stderr, "Failed to load match image: %s\n", img_paths[i]); goto fail; } } img_size = cvGetSize(img); printf(" Image size: %dx%d\n", img_size.width, img_size.height); if ((match_res = matcher->match(matcher, img, &result, 0)) < 0) { fprintf(stderr, "Something went wrong when matching image: %s\n", img_paths[i]); catcierge_matcher_destroy(&matcher); return -1; } match_success = (match_res >= match_threshold); if (match_success) { printf(" Match (%s)! %f\n", catcierge_get_direction_str(result.direction), match_res); match_color = CV_RGB(0, 255, 0); success_count++; } else { printf(" No match! %f\n", match_res); match_color = CV_RGB(255, 0, 0); } if (show || save) { for (j = 0; j < (int)result.rect_count; j++) { printf("x: %d\n", result.match_rects[j].x); printf("y: %d\n", result.match_rects[j].y); printf("w: %d\n", result.match_rects[j].width); printf("h: %d\n", result.match_rects[j].height); cvRectangleR(img, result.match_rects[j], match_color, 1, 8, 0); } if (show) { cvShowImage("image", img); cvWaitKey(0); } if (save) { char out_file[PATH_MAX]; char tmp[PATH_MAX]; char *filename = tmp; char *ext; char *start; // Get the extension. strncpy(tmp, img_paths[i], sizeof(tmp)); ext = strrchr(tmp, '.'); *ext = '\0'; ext++; // And filename. filename = strrchr(tmp, '/'); start = strrchr(tmp, '\\'); if (start> filename) filename = start; filename++; snprintf(out_file, sizeof(out_file) - 1, "%s/match_%s__%s.%s", output_path, match_success ? "ok" : "fail", filename, ext); printf("Saving image \"%s\"\n", out_file); cvSaveImage(out_file, img, 0); } } cvReleaseImage(&img); } } end = clock(); if (!test_matchable) { printf("Note that this time isn't useful with --show\n"); printf("%d of %d successful! (%f seconds)\n", success_count, (int)img_count, (float)(end - start) / CLOCKS_PER_SEC); } fail: catcierge_matcher_destroy(&matcher); cvDestroyAllWindows(); return ret; }
int main(int argc, char **argv) { int ret = 0; catcierge_matcher_t *matcher = NULL; IplImage *img = NULL; CvSize img_size; CvScalar match_color; int match_success = 0; double match_res = 0; int i; int j; int success_count = 0; match_result_t result; clock_t start; clock_t end; catcierge_args_t args; memset(&args, 0, sizeof(args)); memset(&result, 0, sizeof(result)); fprintf(stderr, "Catcierge Image match Tester (C) Joakim Soderberg 2013-2016\n"); if (catcierge_args_init(&args, argv[0])) { fprintf(stderr, "Failed to init args\n"); return -1; } if (add_options(&args)) { fprintf(stderr, "Failed to init tester args\n"); ret = -1; goto fail; } if (catcierge_args_parse(&args, argc, argv)) { ret = -1; goto fail; } // Create output directory. if (ctx.save) { catcierge_make_path("%s", ctx.output_path); } if (catcierge_matcher_init(&matcher, catcierge_get_matcher_args(&args))) { fprintf(stderr, "\n\nFailed to %s init matcher\n\n", matcher->name); return -1; } matcher->debug = ctx.debug; if (!(ctx.imgs = calloc(ctx.img_count, sizeof(IplImage *)))) { fprintf(stderr, "Out of memory!\n"); ret = -1; goto fail; } // TODO: Move to function // If we should preload the images or not // (Don't let file IO screw with benchmark) if (ctx.preload) { for (i = 0; i < (int)ctx.img_count; i++) { printf("Preload image %s\n", ctx.img_paths[i]); if (!(ctx.imgs[i] = cvLoadImage(ctx.img_paths[i], 1))) { fprintf(stderr, "Failed to load match image: %s\n", ctx.img_paths[i]); ret = -1; goto fail; } } } start = clock(); if (ctx.test_matchable) { for (i = 0; i < (int)ctx.img_count; i++) { // This tests if an image frame is clear or not (matchable). int frame_obstructed; if ((frame_obstructed = matcher->is_obstructed(matcher, ctx.imgs[i])) < 0) { fprintf(stderr, "Failed to detect check for matchability frame\n"); return -1; } printf("%s: Frame obstructed = %d\n", ctx.img_paths[i], frame_obstructed); if (ctx.show) { cvShowImage("image", ctx.imgs[i]); cvWaitKey(0); } } } else { for (i = 0; i < (int)ctx.img_count; i++) { match_success = 0; printf("---------------------------------------------------\n"); printf("%s:\n", ctx.img_paths[i]); if (ctx.preload) { img = ctx.imgs[i]; } else { if (!(img = cvLoadImage(ctx.img_paths[i], 1))) { fprintf(stderr, "Failed to load match image: %s\n", ctx.img_paths[i]); goto fail; } } img_size = cvGetSize(img); printf(" Image size: %dx%d\n", img_size.width, img_size.height); if ((match_res = matcher->match(matcher, img, &result, 0)) < 0) { fprintf(stderr, "Something went wrong when matching image: %s\n", ctx.img_paths[i]); catcierge_matcher_destroy(&matcher); return -1; } match_success = (match_res >= args.templ.match_threshold); if (match_success) { printf(" Match (%s)! %f\n", catcierge_get_direction_str(result.direction), match_res); match_color = CV_RGB(0, 255, 0); success_count++; } else { printf(" No match! %f\n", match_res); match_color = CV_RGB(255, 0, 0); } if (ctx.show || ctx.save) { for (j = 0; j < (int)result.rect_count; j++) { printf("x: %d\n", result.match_rects[j].x); printf("y: %d\n", result.match_rects[j].y); printf("w: %d\n", result.match_rects[j].width); printf("h: %d\n", result.match_rects[j].height); cvRectangleR(img, result.match_rects[j], match_color, 1, 8, 0); } if (ctx.show) { cvShowImage("image", img); cvWaitKey(0); } if (ctx.save) { char out_file[PATH_MAX]; char tmp[PATH_MAX]; char *filename = tmp; char *ext; char *start; // Get the extension. strncpy(tmp, ctx.img_paths[i], sizeof(tmp)); ext = strrchr(tmp, '.'); *ext = '\0'; ext++; // And filename. filename = strrchr(tmp, '/'); start = strrchr(tmp, '\\'); if (start> filename) filename = start; filename++; snprintf(out_file, sizeof(out_file) - 1, "%s/match_%s__%s.%s", ctx.output_path, match_success ? "ok" : "fail", filename, ext); printf("Saving image \"%s\"\n", out_file); cvSaveImage(out_file, img, 0); } } cvReleaseImage(&img); } } end = clock(); if (!ctx.test_matchable) { if (ctx.show) { printf("Note that the duration is affected by using --show\n"); } printf("%d of %d successful! (%f seconds)\n", success_count, (int)ctx.img_count, (float)(end - start) / CLOCKS_PER_SEC); } fail: catcierge_matcher_destroy(&matcher); cvDestroyAllWindows(); return ret; }
int main(int argc, char **argv) { catcierge_args_t *args = &grb.args; fprintf(stderr, "\nCatcierge Grabber v" CATCIERGE_VERSION_STR " (" CATCIERGE_GIT_HASH_SHORT ""); // Was this built with changes in the git sources? #ifdef CATCIERGE_GIT_TAINTED fprintf(stderr, "-tainted"); #endif fprintf(stderr, ")\n(C) Joakim Soderberg 2013-2016\n\n"); fprintf(stderr, "Library versions:\n"); fprintf(stderr, " OpenCV v%d.%d.%d\n", CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION); #ifdef WITH_ZMQ fprintf(stderr, " CZMQ v%d.%d.%d\n", CZMQ_VERSION_MAJOR, CZMQ_VERSION_MINOR, CZMQ_VERSION_PATCH); #endif fprintf(stderr, "\n"); // TODO: Enable specifying pid path on command line. #ifndef _WIN32 pid_fd = create_pid_file(argv[0], PID_PATH, FD_CLOEXEC); #endif if (catcierge_grabber_init(&grb)) { fprintf(stderr, "Failed to init\n"); return -1; } if (catcierge_args_init(args, argv[0])) { fprintf(stderr, "Failed to init args\n"); return -1; } if (catcierge_args_parse(args, argc, argv)) { return -1; } if (args->nocolor) { catcierge_nocolor = 1; } catcierge_print_settings(args); setup_sig_handlers(); if (args->log_path) { if (!(grb.log_file = fopen(args->log_path, "a+"))) { CATERR("Failed to open log file \"%s\"\n", args->log_path); } } #ifdef RPI if (catcierge_setup_gpio(&grb)) { CATERR("Failed to setup GPIO pins\n"); return -1; } CATLOG("Initialized GPIO pins\n"); #endif // RPI assert((args->matcher_type == MATCHER_TEMPLATE) || (args->matcher_type == MATCHER_HAAR)); if (catcierge_matcher_init(&grb.matcher, catcierge_get_matcher_args(args))) { CATERR("Failed to init %s matcher\n", grb.matcher->name); return -1; } CATLOG("Initialized catcierge image recognition\n"); if (catcierge_output_init(&grb, &grb.output)) { CATERR("Failed to init output template system\n"); return -1; } if (catcierge_output_load_templates(&grb.output, args->inputs, args->input_count)) { CATERR("Failed to load output templates\n"); return -1; } CATLOG("Initialized output templates\n"); #ifdef WITH_RFID catcierge_init_rfid_readers(&grb); #endif catcierge_setup_camera(&grb); #ifdef WITH_ZMQ catcierge_zmq_init(&grb); #endif CATLOG("Starting detection!\n"); // TODO: Create a catcierge_grb_start(grb) function that does this instead. catcierge_fsm_start(&grb); // Run the program state machine. do { if (!catcierge_timer_isactive(&grb.frame_timer)) { catcierge_timer_start(&grb.frame_timer); } // Always feed the RFID readers. #ifdef WITH_RFID if ((args->rfid_inner_path || args->rfid_outer_path) && catcierge_rfid_ctx_service(&grb.rfid_ctx)) { CATERRFPS("Failed to service RFID readers\n"); } #endif // WITH_RFID grb.img = catcierge_get_frame(&grb); catcierge_run_state(&grb); catcierge_print_spinner(&grb); } while ( grb.running #ifdef WITH_ZMQ && !zctx_interrupted #endif ); catcierge_matcher_destroy(&grb.matcher); catcierge_output_destroy(&grb.output); catcierge_destroy_camera(&grb); #ifdef WITH_ZMQ catcierge_zmq_destroy(&grb); #endif catcierge_grabber_destroy(&grb); catcierge_args_destroy(&grb.args); if (grb.log_file) { fclose(grb.log_file); } #ifndef _WIN32 if (pid_fd > 0) { close(pid_fd); unlink(PID_PATH); } #endif return 0; }