aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/seg/mask_data.c37
-rw-r--r--src/lib/seg/util.c93
2 files changed, 119 insertions, 11 deletions
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;
+ }
+}