diff options
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | include/lib/seg/mask_data.h | 6 | ||||
-rw-r--r-- | include/lib/seg/util.h | 11 | ||||
-rw-r--r-- | include/snippets/raylib_block.c | 93 | ||||
-rwxr-xr-x | run.sh | 2 | ||||
-rw-r--r-- | sample_data/small/small.tif | bin | 0 -> 4374 bytes | |||
-rw-r--r-- | src/lib/seg/mask_data.c | 37 | ||||
-rw-r--r-- | src/lib/seg/util.c | 93 | ||||
-rw-r--r-- | src/main.c | 329 |
10 files changed, 362 insertions, 231 deletions
@@ -1,5 +1,5 @@ PKGS=libtiff-4 libpng -#PKGS+=raylib +DEFINES= EXE=prog BUILD_DIR=build/ OBJ_DIR=$(BUILD_DIR)obj/ @@ -11,6 +11,19 @@ OBJS=$(OBJS_sub:.c=.o) OBJ_DIRS_sub=$(shell find $(SRC_DIR) -type d) OBJ_DIRS=$(subst $(SRC_DIR),$(OBJ_DIR),$(OBJ_DIRS_sub)) +# Include raylib if we want a visual experience +ifdef RAYLIB +$(info Visual Experience Selected) +PKGS+=raylib +DEFINES+=-DVISUAL +endif + +# Dump AVL tree info? +ifdef AVL_INFO +$(info Including AVL Dump) +DEFINES+=-DAVL_INFO +endif + ifeq ($(shell uname -s),Linux) PKGCONF=pkgconf endif @@ -21,6 +34,8 @@ endif CFLAGS= CFLAGS+=$(shell $(PKGCONF) --cflags $(PKGS)) CFLAGS+=-I$(INC_DIR) +CFLAGS+=$(DEFINES) +CFLAGS+=-Wall LDFLAGS= LDFLAGS+=$(shell $(PKGCONF) --libs $(PKGS)) @@ -3,3 +3,8 @@ ```sh for file in data/HT-*/; do ./run.sh `basename $file`; done ``` + +```sh +mkdir -p output/small/ +./build/prog sample_data/small output/small/small.bin output/small/small.png +``` diff --git a/include/lib/seg/mask_data.h b/include/lib/seg/mask_data.h index f2803e6..8e2ae3a 100644 --- a/include/lib/seg/mask_data.h +++ b/include/lib/seg/mask_data.h @@ -56,4 +56,10 @@ bool_t in_uint16_t_tree(struct AVLNode* root, uint16_t value); // Assumption: Contiguous labeling struct AVLNode* get_small_labels(struct AVLNode* removal_tree, struct AVLNode* label_tree, size_t min_area, size_t min_perimeter); +// Get mask label data +struct AVLNode* get_mask_data(uint16_t* masks, uint32_t width, uint32_t height); + +// Filter out small masks in mask +void filter_small_masks(uint16_t* masks, uint32_t width, uint32_t height, size_t min_area, size_t min_perimeter); + #endif diff --git a/include/lib/seg/util.h b/include/lib/seg/util.h index fcafff6..c54b0e0 100644 --- a/include/lib/seg/util.h +++ b/include/lib/seg/util.h @@ -13,13 +13,13 @@ size_t xy_to_coord(size_t x, size_t y, uint32_t width, uint32_t height); bool_t is_on_mask_boundary(uint16_t* mask, uint32_t width, uint32_t height, size_t x, size_t y); // Dilate masks by one 4-connected pixel -uint16_t* dilate(uint16_t* mask, uint32_t width, uint32_t height); +void dilate(uint16_t** mask, uint32_t width, uint32_t height); // Erode masks by one 4-connected pixel -uint16_t* erode(uint16_t* mask, uint32_t width, uint32_t height); +void erode(uint16_t** mask, uint32_t width, uint32_t height); // Close up masks by N-pixels -uint16_t* closeup(uint16_t* mask, uint32_t width, uint32_t height, size_t count); +void closeup(uint16_t** mask, uint32_t width, uint32_t height, size_t count); // Combine Label Masks // For all empty spaces in the destination, put the extra label if it exists @@ -34,4 +34,9 @@ uint16_t* tif_to_labels(char* tif_file_name, uint32_t *width, uint32_t *height, // Convert mask to bitmap struct bitmap_t* uint16_to_bitmap(uint16_t* buffer, uint32_t width, uint32_t height); +// Reduce a mask to the contiguous regions +// Automatically update pointer to contiguous mask +// Freeing previous mask +void reduce_contiguous_regions(uint16_t** masks_p, uint32_t width, uint32_t height, uint16_t* total_labels); + #endif diff --git a/include/snippets/raylib_block.c b/include/snippets/raylib_block.c new file mode 100644 index 0000000..ef81fd2 --- /dev/null +++ b/include/snippets/raylib_block.c @@ -0,0 +1,93 @@ + //----------------------------------------------- + //-RAYLIB-INIT----------------------------------- + //----------------------------------------------- + SetTraceLogLevel(LOG_ERROR); + SetConfigFlags(FLAG_WINDOW_RESIZABLE); + const char* gui_title = "Image Manip - Useful for segmentations!"; + InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, gui_title); + + //----------------------------------------------- + // (When treating this as RGBA, last bits should ensure opaque) + // This assumes 4096 (2^12) > labels + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + /// RGBA channels: Move labels to RGB + masks[x + y*width] <<= 4; + masks[x + y*width] |= 0x000F; + } + } + //----------------------------------------------- + + //----------------------------------------------- + //-RAYLIB-IMAGE-STRUCTURING---------------------- + //----------------------------------------------- + Image RaylibImage; + RaylibImage.width = width; + RaylibImage.height = height; + RaylibImage.mipmaps = 1; + // Use Contiguous Labels + RaylibImage.data = masks; + RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4; + //----------------------------------------------- + + // Image to a Texture + Texture2D RaylibTexture = LoadTextureFromImage(RaylibImage); + + // Scale the image to the viewport + /// Source Rectangle: Original Size + Rectangle sourceRec = { 0.0f, 0.0f, (float)width, (float)height }; + /// Destination Rectangle: Transformed Size + Rectangle destRec = { 0.0f, 0.0f, (float)SCREEN_WIDTH, (float)(SCREEN_HEIGHT-OFFSET) }; + /// Location to begin drawing + Vector2 origin = { (float)0, (float)-OFFSET }; + + // Raylib boilerplate + SetTargetFPS(60); + Camera2D camera = { 0 }; + camera.zoom = 1.0f; + + // GUI Loop + while (!WindowShouldClose()) { + //----------------------------------------------- + //-DRAWING--------------------------------------- + //----------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + BeginMode2D(camera); + EndMode2D(); + DrawText("Image Manip", 0, 0, OFFSET, DARKGRAY); + DrawTexturePro(RaylibTexture, sourceRec, destRec, origin, (float)0, + RAYWHITE); + /* + uint32_t x = 0x49, y = 0x4A; + uint32_t dx = 0x69 - x, dy = 0x6E - y; + x = (SCREEN_WIDTH*x)/width; + y = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*y)/height; + dx = (SCREEN_WIDTH*dx)/width; + dy = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*dy)/height; + DrawRectangleGradientH(x, y, dx, dy, BLUE, PURPLE); + */ + EndDrawing(); + //----------------------------------------------- + } + + //----------------------------------------------- + //-SAVE-MASK-AS-BINARY-AND-PNG------------------- + //----------------------------------------------- + if (masks != NULL) { + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + /// Restore labels from RGBA + masks[x + y*width] &= 0xFFF0; + masks[x + y*width] >>= 4; + } + } + struct bitmap_t* bitmap = uint16_to_bitmap(masks, width, height); + if (bitmap != NULL) { + save_png(bitmap, png_file); + free(bitmap); + } + write_array(bin_file, masks, width*height*sizeof(uint16_t)); + free(masks); + } + CloseWindow(); @@ -1,4 +1,4 @@ #!/bin/sh SOURCE="$1" mkdir -p output/${SOURCE} -./build/prog data/${SOURCE} output/${SOURCE}/${SOURCE}.bin output/${SOURCE}/${SOURCE}.png +./build/prog -s -d data/${SOURCE} -b output/${SOURCE}/${SOURCE}.bin -p output/${SOURCE}/${SOURCE}.png diff --git a/sample_data/small/small.tif b/sample_data/small/small.tif Binary files differnew file mode 100644 index 0000000..4d93c8d --- /dev/null +++ b/sample_data/small/small.tif diff --git a/src/lib/seg/mask_data.c b/src/lib/seg/mask_data.c index 2f3a51a..8c4b037 100644 --- a/src/lib/seg/mask_data.c +++ b/src/lib/seg/mask_data.c @@ -1,4 +1,5 @@ #include <lib/seg/mask_data.h> +#include <lib/seg/util.h> #include <stdio.h> @@ -224,3 +225,39 @@ struct AVLNode* get_small_labels(struct AVLNode* removal_tree, struct AVLNode* l } return return_tree; } + +// Get mask label data +struct AVLNode* get_mask_data(uint16_t* masks, uint32_t width, uint32_t height) +{ + struct AVLNode* root = NULL; + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + size_t coord = x + y*width; + if (masks[coord] != 0) { + root = increase_label_area_alloc(root, masks[coord]); + if (is_on_mask_boundary(masks, width, height, x, y)) { + increase_label_perimeter(root, masks[coord]); + } + } + } + } + return root; +} + +// Filter out small masks in mask +void filter_small_masks(uint16_t* masks, uint32_t width, uint32_t height, size_t min_area, size_t min_perimeter) +{ + struct AVLNode* root = get_mask_data(masks, width, height); + struct AVLNode* small_label_tree = NULL; + small_label_tree = get_small_labels(NULL, root, min_area, min_perimeter); + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + size_t coord = x + y*width; + if (in_uint16_t_tree(small_label_tree, masks[coord])) { + masks[coord] = 0; + } + } + } + free_avl_tree(small_label_tree); + free_avl_tree_nodes(root); +} diff --git a/src/lib/seg/util.c b/src/lib/seg/util.c index 10b8fa8..8a5f5e5 100644 --- a/src/lib/seg/util.c +++ b/src/lib/seg/util.c @@ -1,4 +1,4 @@ -#include <lib/seg/util.h> + #include <lib/seg/util.h> #include <lib/algo/flood_fill.h> #include <lib/png.h> #include <tiffio.h> @@ -7,6 +7,12 @@ #include <stdlib.h> #include <string.h> +// Suppress Tiff Warnings +void TiffDummyHandler(const char* module, const char* fmt, va_list ap) +{ + // ignore errors and warnings (or handle them your own way) +} + // Convert x,y coords to linear coordinate size_t xy_to_coord(size_t x, size_t y, uint32_t width, uint32_t height) { @@ -51,7 +57,7 @@ bool_t is_on_mask_boundary(uint16_t* mask, uint32_t width, uint32_t height, size } // Dilate masks by one 4-connected pixel -uint16_t* dilate(uint16_t* mask, uint32_t width, uint32_t height) +uint16_t* _dilate(uint16_t* mask, uint32_t width, uint32_t height) { uint16_t *new_mask = (uint16_t*)calloc(width*height,sizeof(uint16_t)); for (size_t y = 0; y < height; y++) { @@ -95,8 +101,18 @@ uint16_t* dilate(uint16_t* mask, uint32_t width, uint32_t height) return new_mask; } +// Dilate masks by one 4-connected pixel +void dilate(uint16_t** mask, uint32_t width, uint32_t height) +{ + uint16_t *new_mask = _dilate(*mask, width, height); + if (new_mask != NULL) { + free(*mask); + *mask = new_mask; + } +} + // Erode masks by one 4-connected pixel -uint16_t* erode(uint16_t* mask, uint32_t width, uint32_t height) +uint16_t* _erode(uint16_t* mask, uint32_t width, uint32_t height) { uint16_t *new_mask = (uint16_t*)calloc(width*height,sizeof(uint16_t)); for (size_t y = 0; y < height; y++) { @@ -106,7 +122,6 @@ uint16_t* erode(uint16_t* mask, uint32_t width, uint32_t height) new_mask[current_position] = mask[current_position]; continue; } - bool_t erode = FALSE; size_t proposed_position; if (x != 0) { proposed_position = xy_to_coord(x-1, y, width, height); @@ -141,20 +156,26 @@ uint16_t* erode(uint16_t* mask, uint32_t width, uint32_t height) return new_mask; } +// Erode masks by one 4-connected pixel +void erode(uint16_t** mask, uint32_t width, uint32_t height) +{ + uint16_t *new_mask = _erode(*mask, width, height); + if (new_mask != NULL) { + free(*mask); + *mask = new_mask; + } +} + // Close up masks by N-pixels -uint16_t* closeup(uint16_t* mask, uint32_t width, uint32_t height, size_t num_pixels) +uint16_t* _closeup(uint16_t* mask, uint32_t width, uint32_t height, size_t num_pixels) { uint16_t *new_mask = (uint16_t*)calloc(width*height,sizeof(uint16_t)); memcpy(new_mask, mask, width*height*sizeof(uint16_t)); for (size_t count = 0; count < num_pixels; count++) { - uint16_t *new_labels = dilate(new_mask, width, height); - free(new_mask); - new_mask = new_labels; + dilate(&new_mask, width, height); } for (size_t count = 0; count < num_pixels; count++) { - uint16_t *new_labels = erode(new_mask, width, height); - free(new_mask); - new_mask = new_labels; + erode(&new_mask, width, height); } // Retain original mask at the very least for (size_t y = 0; y < height; y++) { @@ -170,6 +191,17 @@ uint16_t* closeup(uint16_t* mask, uint32_t width, uint32_t height, size_t num_pi return new_mask; } +// Close up masks by N-pixels +// Update pointer +void closeup(uint16_t** mask, uint32_t width, uint32_t height, size_t num_pixels) +{ + uint16_t *new_mask = _closeup(*mask, width, height, num_pixels); + if (new_mask != NULL) { + free(*mask); + *mask = new_mask; + } +} + // Combine Label Masks // For all empty spaces in the destination, put the extra label if it exists // Allocates an array if destination is unallocated @@ -194,6 +226,7 @@ uint16_t* combine_masks(uint16_t *destination, uint16_t *extra_labels, uint32_t // starting_label_p will be incremented for each label found in the image uint16_t* tif_to_labels(char* tif_file_name, uint32_t *width, uint32_t *height, uint16_t *starting_label_p) { + TIFFSetWarningHandler(TiffDummyHandler); //-TIFF-IMAGE-OPEN------------------------------- TIFF *tif = TIFFOpen(tif_file_name, "r"); if (!tif) { @@ -290,3 +323,41 @@ struct bitmap_t* uint16_to_bitmap(uint16_t* buffer, uint32_t width, uint32_t hei bitmap->height = (size_t)height; return bitmap; } + +// Reduce a mask to the contiguous regions +uint16_t* _reduce_contiguous_regions(uint16_t* masks, uint32_t width, uint32_t height, uint16_t* total_labels) +{ + uint16_t starting_label = 1; + uint16_t* new_masks = (uint16_t*)calloc(width*height, sizeof(uint16_t)); + if (new_masks == NULL) { + return NULL; + } + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + size_t coord = x + y*width; + uint8_t channels = 2; // uint16_t = 2*uint8_t + if (flood((uint8_t*)masks, new_masks, width, height, channels, x, y, &(((uint8_t*)masks)[coord*channels]), starting_label)) { + starting_label++; + } + } + } + if (total_labels != NULL) { + *total_labels = starting_label; + } + return new_masks; +} + +// Reduce a mask to the contiguous regions +// Automatically update pointer to contiguous mask +// Freeing previous mask +void reduce_contiguous_regions(uint16_t** masks_p, uint32_t width, uint32_t height, uint16_t* total_labels) +{ + if (masks_p == NULL) { + return; + } + uint16_t* new_masks = _reduce_contiguous_regions(*masks_p, width, height, total_labels); + if (new_masks != NULL) { + free(*masks_p); + *masks_p = new_masks; + } +} @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #ifdef VISUAL #include <raylib.h> @@ -22,36 +23,79 @@ #define N_DILATIONS 10 -#define MIN_AREA 200 -#define MIN_PERIMETER 50 +#define MIN_AREA 500 +#define MIN_PERIMETER 0 int main(int argc, char** argv) { + char opt; + char* directory = NULL; + char* png_file = "../out.png"; + char* bin_file = "../out.bin"; + bool_t silent = FALSE; + //----------------------------------------------- + //-GET-COMMAND-LINE-ARGUMENTS-------------------- + //----------------------------------------------- + while ((opt = getopt(argc, argv, "d:b:p:s")) != -1) { + switch (opt) { + case 's': + silent = TRUE; + break; + case 'd': + if (!silent) { + printf("Parse Directory: %s\n", optarg); + } + directory = optarg; + break; + case 'b': + if (!silent) { + printf("Bin File: %s\n", optarg); + } + bin_file = optarg; + break; + case 'p': + if (!silent) { + printf("PNG File: %s\n", optarg); + } + png_file = optarg; + break; + case ':': + if (!silent) { + printf("Option requires value\n"); + } + break; + case '?': + if (!silent) { + printf("Unknown option: %c\n", optopt); + } + break; + } + } + if (!silent) { + for (;optind < argc; optind++) { + printf("Extra arguments: %s\n", argv[optind]); + } + } TIME(ts_g_start); struct AVLNode* root = NULL; //----------------------------------------------- - //-LIST-FILES-IN-DIRECTORY----------------------- + //-PROCESS-FILES-IN-DIRECTORY-------------------- //----------------------------------------------- char** file_list = NULL; uint32_t width, height; uint16_t starting_label = 1; uint16_t *masks = NULL; // Expect a directory to be passed as the first argument - if (argc > 1) { + if (directory != NULL) { // Ensure the directory exists - if (is_directory(argv[1])) { + if (is_directory(directory)) { // List files in the ddirectory - file_list = list_directory(argv[1]); - if (file_list) { - size_t index = 0; - // For each file - while (1) { + file_list = list_directory(directory); + if (file_list != NULL) { + for (size_t index = 0; file_list[index] != NULL; index++) { char* fname = file_list[index]; - if (fname == NULL) { - break; - } if (is_tif_ext(fname) == FALSE) { - free(file_list[index++]); + free(file_list[index]); continue; } // If we have a tiff file @@ -59,22 +103,24 @@ int main(int argc, char** argv) // 2. Find contiguous regions // 3. Combine with current total mask // 4. Free up allocations made in this process - char* fpath = full_path(argv[1], fname); + char* fpath = full_path(directory, fname); if (fpath == NULL) { - free(file_list[index++]); + free(file_list[index]); continue; } - printf("Loading %s...\n", fpath); + if (!silent) { + printf("Loading %s...\n", fpath); + } uint16_t *file_labels = tif_to_labels(fpath, &width, &height, &starting_label); if (file_labels == NULL) { free(fpath); - free(file_list[index++]); + free(file_list[index]); continue; } masks = combine_masks(masks, file_labels, width, height); free(file_labels); free(fpath); - free(file_list[index++]); + free(file_list[index]); } free(file_list); } @@ -85,226 +131,79 @@ int main(int argc, char** argv) return 1; } - // Regenerate contiguous labels - starting_label = 1; - uint16_t* labels = (uint16_t*)calloc(width*height, sizeof(uint16_t)); - if (labels == NULL) { - fprintf(stderr, "Memory allocation error\n"); - free(masks); - } - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - size_t coord = x + y*width; - uint8_t channels = 2; - if (flood((uint8_t*)masks, labels, width, height, channels, x, y, &(((uint8_t*)masks)[coord*channels]), starting_label)) { - starting_label++; - } - } - } - uint16_t *temp = labels; - labels = masks; - masks = temp; - free(labels); - printf("%u labels found\n", starting_label-1); - printf("Mask dimensions: %u %u\n", width, height); - // Get the area/ perimeter of each label - root = NULL; - TIME(ts_info_start); - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - if (masks[x + y*width] != 0) { - root = increase_label_area_alloc(root, masks[x + y*width]); - if (is_on_mask_boundary(masks, width, height, x, y)) { - increase_label_perimeter(root, masks[x + y*width]); - } - } - } + //----------------------------------------------- + //-FIND-CONTIGUOUS-REGIONS----------------------- + //----------------------------------------------- + reduce_contiguous_regions(&masks, width, height, &starting_label); + if (!silent) { + printf("%u labels found\n", starting_label-1); + printf("Mask dimensions: %u %u\n", width, height); } - TIME(ts_info_end); - printf("Information retrieval took %f ms\n", 1000*diff_time(&ts_info_end, &ts_info_start)); -#ifdef AVL_INFO - printf("Inorder traversal of AVL tree: "); - print_label(root); - printf("\n"); -#endif TIME(ts_filter_start); - // Get the smallest labels - struct AVLNode* small_label_tree = NULL; - small_label_tree = get_small_labels(NULL, root, MIN_AREA, MIN_PERIMETER); - - // Remove the small labels - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - if (in_uint16_t_tree(small_label_tree, masks[x + y*width])) { - masks[x + y*width] = 0; - } - } - } + //----------------------------------------------- + //-FILTER-SMALL-REGIONS-OUT---------------------- + //----------------------------------------------- + filter_small_masks(masks, width, height, MIN_AREA, MIN_PERIMETER); TIME(ts_filter_end); - printf("Removing small labels took %f ms\n", 1000*diff_time(&ts_filter_end, &ts_filter_start)); - free_avl_tree(small_label_tree); - free_avl_tree_nodes(root); - - // Regenerate contiguous labels - starting_label = 1; - labels = (uint16_t*)calloc(width*height, sizeof(uint16_t)); - if (labels == NULL) { - fprintf(stderr, "Memory allocation error\n"); - free(masks); + if (!silent) { + printf("Removing small labels took %f ms\n", 1000*diff_time(&ts_filter_end, &ts_filter_start)); } - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - size_t coord = x + y*width; - uint8_t channels = 2; - if (flood((uint8_t*)masks, labels, width, height, channels, x, y, &(((uint8_t*)masks)[coord*channels]), starting_label)) { - starting_label++; - } - } - } - temp = labels; - labels = masks; - masks = temp; - free(labels); - printf("%u remaining labels found\n", starting_label-1); - printf("Mask dimensions: %u %u\n", width, height); - // Regenerate information after relabeling - root = NULL; - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - if (masks[x + y*width] != 0) { - root = increase_label_area_alloc(root, masks[x + y*width]); - if (is_on_mask_boundary(masks, width, height, x, y)) { - increase_label_perimeter(root, masks[x + y*width]); - } - } - } + //----------------------------------------------- + //-FIND-CONTIGUOUS-REGIONS----------------------- + //----------------------------------------------- + //--to-make-labels-span-1-to-n------------------- + //----------------------------------------------- + reduce_contiguous_regions(&masks, width, height, &starting_label); + if (!silent) { + printf("%u remaining labels found\n", starting_label-1); + printf("Mask dimensions: %u %u\n", width, height); } #ifdef AVL_INFO - printf("Inorder traversal of AVL tree: "); - print_label(root); - printf("\n"); -#endif + //----------------------------------------------- + //-OPTIONAL:------------------------------------- + //-GET-MASK-META-INFORMATION--------------------- + //----------------------------------------------- + root = get_mask_data(masks, width, height); + if (!silent) { + printf("Inorder traversal of AVL tree: "); + print_label(root); + printf("\n"); + } free_avl_tree_nodes(root); +#endif - uint16_t *new_labels; TIME(ts_start); - new_labels = closeup(masks, width, height, N_DILATIONS); - if (new_labels != NULL) { - free(masks); - masks = new_labels; - } - TIME(ts_end); - printf("Closing up took %f ms\n", 1000*diff_time(&ts_end, &ts_start)); - //----------------------------------------------- - -#ifdef VISUAL //----------------------------------------------- - //-RAYLIB-INIT + //-CLOSE-UP-SMALL-GAPS-BETWEEN-REGIONS----------- //----------------------------------------------- - SetTraceLogLevel(LOG_ERROR); - SetConfigFlags(FLAG_WINDOW_RESIZABLE); - const char* gui_title = "Image Manip - Useful for segmentations!"; - InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, gui_title); - - //----------------------------------------------- - // (When treating this as RGBA, last bits should ensure opaque) - // This assumes 4096 (2^12) > labels - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - /// RGBA channels: Move labels to RGB - masks[x + y*width] <<= 4; - masks[x + y*width] |= 0x000F; - } + closeup(&masks, width, height, N_DILATIONS); + TIME(ts_end); + if (!silent) { + printf("Closing up took %f ms\n", 1000*diff_time(&ts_end, &ts_start)); } //----------------------------------------------- - - //----------------------------------------------- - //-RAYLIB-IMAGE-STRUCTURING---------------------- - //----------------------------------------------- - Image RaylibImage; - RaylibImage.width = width; - RaylibImage.height = height; - RaylibImage.mipmaps = 1; - // Use Contiguous Labels - RaylibImage.data = masks; - RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4; + //-END-OF-PROCESSING----------------------------- //----------------------------------------------- - // Image to a Texture - Texture2D RaylibTexture = LoadTextureFromImage(RaylibImage); - - // Scale the image to the viewport - /// Source Rectangle: Original Size - Rectangle sourceRec = { 0.0f, 0.0f, (float)width, (float)height }; - /// Destination Rectangle: Transformed Size - Rectangle destRec = { 0.0f, 0.0f, (float)SCREEN_WIDTH, (float)(SCREEN_HEIGHT-OFFSET) }; - /// Location to begin drawing - Vector2 origin = { (float)0, (float)-OFFSET }; - - // Raylib boilerplate - SetTargetFPS(60); - Camera2D camera = { 0 }; - camera.zoom = 1.0f; - - // GUI Loop - while (!WindowShouldClose()) { - //----------------------------------------------- - //-DRAWING--------------------------------------- - //----------------------------------------------- - BeginDrawing(); - ClearBackground(RAYWHITE); - BeginMode2D(camera); - EndMode2D(); - DrawText("Image Manip", 0, 0, OFFSET, DARKGRAY); - DrawTexturePro(RaylibTexture, sourceRec, destRec, origin, (float)0, - RAYWHITE); - /* - uint32_t x = 0x49, y = 0x4A; - uint32_t dx = 0x69 - x, dy = 0x6E - y; - x = (SCREEN_WIDTH*x)/width; - y = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*y)/height; - dx = (SCREEN_WIDTH*dx)/width; - dy = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*dy)/height; - DrawRectangleGradientH(x, y, dx, dy, BLUE, PURPLE); - */ - EndDrawing(); - //----------------------------------------------- - } - - if (masks != NULL) { - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - /// Restore labels from RGBA - masks[x + y*width] &= 0xFFF0; - masks[x + y*width] >>= 4; - } - } - write_array("../out.bin", masks, width*height*sizeof(uint16_t)); - free(masks); - } - CloseWindow(); +#ifdef VISUAL +#include <snippets/raylib_block.c> #else + //----------------------------------------------- + //-SAVE-MASK-AS-BINARY-AND-PNG------------------- + //----------------------------------------------- if (masks != NULL) { struct bitmap_t* bitmap = uint16_to_bitmap(masks, width, height); - char* png_name = "../out.png"; - char* bin_name = "../out.bin"; if (bitmap != NULL) { - if (argc > 3) { - save_png(bitmap, argv[3]); - } else { - save_png(bitmap, png_name); - } + save_png(bitmap, png_file); free(bitmap); } - if (argc > 2) { - write_array(argv[2], masks, width*height*sizeof(uint16_t)); - } else { - write_array(bin_name, masks, width*height*sizeof(uint16_t)); - } + write_array(bin_file, masks, width*height*sizeof(uint16_t)); free(masks); } #endif TIME(ts_g_end); - printf("Finished in %f ms\n", 1000*diff_time(&ts_g_end, &ts_g_start)); + if (!silent) { + printf("Finished in %f ms\n", 1000*diff_time(&ts_g_end, &ts_g_start)); + } return 0; } |