#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int arg_count, char **arg_value) { char cli_option; char *process_directory = NULL; char *png_output_file_fullpath = "../out.png"; char *bin_output_file_fullpath = "../out.bin"; size_t closeup_pixel_count = 10; size_t minimum_mask_area_threshold = 500; size_t minimum_mask_perimeter_threshold = 0; bool_t suppress_outputs_b = FALSE; //----------------------------------------------- //-GET-COMMAND-LINE-ARGUMENTS-------------------- //----------------------------------------------- while ((cli_option = getopt(arg_count, arg_value, "d:b:p:n:sA:P:")) != -1) { switch (cli_option) { case 's': suppress_outputs_b = TRUE; break; case 'A': minimum_mask_area_threshold = atoi(optarg); break; case 'P': minimum_mask_perimeter_threshold = atoi(optarg); break; case 'd': if (!suppress_outputs_b) { printf("Parse Directory: %s\n", optarg); } process_directory = optarg; break; case 'b': if (!suppress_outputs_b) { printf("Bin File: %s\n", optarg); } bin_output_file_fullpath = optarg; break; case 'p': if (!suppress_outputs_b) { printf("PNG File: %s\n", optarg); } png_output_file_fullpath = optarg; break; case 'n': if (!suppress_outputs_b) { printf("Closeup Size: %d\n", atoi(optarg)); } closeup_pixel_count = atoi(optarg); break; case ':': if (!suppress_outputs_b) { printf("Option requires value\n"); } break; case '?': if (!suppress_outputs_b) { printf("Unknown option: %c\n", optopt); } break; } } for (; optind < arg_count; optind++) { if (!suppress_outputs_b) { printf("Extra arguments: %s\n", arg_value[optind]); } } TIME(ts_g_start); //----------------------------------------------- //-PROCESS-FILES-IN-DIRECTORY-------------------- //----------------------------------------------- char **file_list = NULL; MaskData_t starting_label = 1; Mask *masks_im = NULL; // Expect a directory to be passed as the first argument if (process_directory != NULL) { // Ensure the directory exists if (is_directory(process_directory)) { // List files in the ddirectory file_list = list_directory(process_directory); if (file_list != NULL) { for (size_t index = 0; file_list[index] != NULL; index++) { char *fname = file_list[index]; if (is_tif_ext(fname) == FALSE) { g_free(file_list[index]); continue; } // If we have a tiff file // 1. Convert to labels // 2. Find contiguous regions // 3. Combine with current total mask // 4. Free up allocations made in this process char *fpath = full_path(process_directory, fname); if (fpath == NULL) { g_free(file_list[index]); continue; } if (!suppress_outputs_b) { printf("Loading %s...\n", fpath); } //----------------------------------------------- //-PROCESS-TIFF-TO-LABELS------------------------ //----------------------------------------------- Mask *file_im = tif_to_labels(fpath, &starting_label); if (file_im == NULL) { g_free(fpath); g_free(file_list[index]); continue; } //----------------------------------------------- //-COMBINE-LABELS-TO-GLOBAL-MASK----------------- //----------------------------------------------- masks_im = combine_masks(masks_im, file_im); free_image_mask(file_im); g_free(fpath); g_free(file_list[index]); } g_free(file_list); } } } if (masks_im == NULL) { fprintf(stderr, "No masks found!\n"); return 1; } uint32_t width = (uint32_t)masks_im->width; uint32_t height = (uint32_t)masks_im->height; //----------------------------------------------- //-FIND-CONTIGUOUS-REGIONS----------------------- //----------------------------------------------- reduce_contiguous_regions(masks_im, &starting_label); if (!suppress_outputs_b) { printf("%u labels found\n", starting_label - 1); printf("Mask dimensions: %u %u\n", width, height); } //----------------------------------------------- //-FILTER-SMALL-REGIONS-OUT---------------------- //----------------------------------------------- TIME(ts_filter_start); filter_small_masks(masks_im, minimum_mask_area_threshold, minimum_mask_perimeter_threshold); TIME(ts_filter_end); if (!suppress_outputs_b) { printf("Removing small labels took %f ms\n", 1000 * diff_time(&ts_filter_end, &ts_filter_start)); } //----------------------------------------------- //-FIND-CONTIGUOUS-REGIONS----------------------- //----------------------------------------------- //--to-make-labels-span-1-to-n------------------- //----------------------------------------------- reduce_contiguous_regions(masks_im, &starting_label); if (!suppress_outputs_b) { printf("%u remaining labels found\n", starting_label - 1); printf("Mask dimensions: %u %u\n", width, height); } #ifdef AVL_INFO //----------------------------------------------- //-OPTIONAL:------------------------------------- //-GET-MASK-META-INFORMATION--------------------- //----------------------------------------------- AVLNode *root = NULL; root = get_mask_data(masks_im); if (!silent) { printf("Inorder traversal of AVL tree: "); print_label(root); printf("\n"); } free_avl_tree_nodes(root); #endif //----------------------------------------------- //-CLOSE-UP-SMALL-GAPS-BETWEEN-REGIONS----------- //----------------------------------------------- TIME(ts_start); closeup(masks_im, closeup_pixel_count); TIME(ts_end); if (!suppress_outputs_b) { printf("Closing (%lu) up took %f ms\n", closeup_pixel_count, 1000 * diff_time(&ts_end, &ts_start)); } //----------------------------------------------- //-END-OF-PROCESSING----------------------------- //----------------------------------------------- //----------------------------------------------- //-SAVE-MASK-AS-BINARY-AND-PNG------------------- //----------------------------------------------- if (masks_im != NULL) { Bitmap *bitmap = image_mask_data_to_bitmap(masks_im); if (bitmap != NULL) { save_png(bitmap, png_output_file_fullpath); g_free(bitmap); } write_array(bin_output_file_fullpath, masks_im->image[0], width * height * sizeof(MaskData_t)); free_image_mask(masks_im); } TIME(ts_g_end); if (!suppress_outputs_b) { printf("Finished in %f ms\n", 1000 * diff_time(&ts_g_end, &ts_g_start)); } printf("Outstanding allocations: %zu\n", g_outstanding_allocations()); return 0; }