Mercurial > repos > imgteam > colorize_labels
comparison colorize_labels.py @ 0:6f09b367cd9a draft default tip
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/colorize_labels commit 4344f548f365dba87c20188d6e3c2df8630d2313
author | imgteam |
---|---|
date | Tue, 24 Sep 2024 17:30:11 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6f09b367cd9a |
---|---|
1 import argparse | |
2 | |
3 import giatools.io | |
4 import matplotlib.pyplot as plt | |
5 import networkx as nx | |
6 import numpy as np | |
7 import scipy.ndimage as ndi | |
8 import skimage.io | |
9 import skimage.util | |
10 | |
11 | |
12 def color_hex_to_rgb_tuple(hex): | |
13 if hex.startswith('#'): | |
14 hex = hex[1:] | |
15 return ( | |
16 int(hex[0:2], 16), | |
17 int(hex[2:4], 16), | |
18 int(hex[4:6], 16), | |
19 ) | |
20 | |
21 | |
22 def build_label_adjacency_graph(im, radius, bg_label): | |
23 G = nx.Graph() | |
24 for label in np.unique(im): | |
25 | |
26 if label == bg_label: | |
27 continue | |
28 | |
29 G.add_node(label) | |
30 | |
31 cc = (im == label) | |
32 neighborhood = (ndi.distance_transform_edt(~cc) <= radius) | |
33 adjacent_labels = np.unique(im[neighborhood]) | |
34 | |
35 for adjacent_label in adjacent_labels: | |
36 | |
37 if adjacent_label == bg_label or adjacent_label <= label: | |
38 continue | |
39 | |
40 G.add_edge(label, adjacent_label) | |
41 G.add_edge(adjacent_label, label) | |
42 | |
43 return G | |
44 | |
45 | |
46 def get_n_unique_mpl_colors(n, colormap='jet', cyclic=False): | |
47 """ | |
48 Yields `n` unique colors from the given `colormap`. | |
49 | |
50 Set `cyclic` to `True` if the `colormap` is cyclic. | |
51 """ | |
52 cmap = plt.get_cmap(colormap) | |
53 m = n if cyclic else n - 1 | |
54 for i in range(n): | |
55 yield np.multiply(255, cmap(i / m)) | |
56 | |
57 | |
58 if __name__ == '__main__': | |
59 | |
60 parser = argparse.ArgumentParser() | |
61 parser.add_argument('input', type=str) | |
62 parser.add_argument('--bg_label', type=int) | |
63 parser.add_argument('--bg_color', type=str) | |
64 parser.add_argument('--radius', type=int) | |
65 parser.add_argument('--output', type=str) | |
66 args = parser.parse_args() | |
67 | |
68 # Load image and normalize | |
69 im = giatools.io.imread(args.input) | |
70 im = np.squeeze(im) | |
71 assert im.ndim == 2 | |
72 | |
73 # Build adjacency graph of the labels | |
74 G = build_label_adjacency_graph(im, args.radius, args.bg_label) | |
75 | |
76 # Apply greedy coloring | |
77 graph_coloring = nx.greedy_color(G) | |
78 unique_colors = frozenset(graph_coloring.values()) | |
79 | |
80 # Assign colors to nodes based on the greedy coloring | |
81 graph_color_to_mpl_color = dict(zip(unique_colors, get_n_unique_mpl_colors(len(unique_colors)))) | |
82 node_colors = [graph_color_to_mpl_color[graph_coloring[n]] for n in G.nodes()] | |
83 | |
84 # Render result | |
85 bg_color_rgb = color_hex_to_rgb_tuple(args.bg_color) | |
86 result = np.dstack([np.full(im.shape, bg_color_rgb[ch], np.uint8) for ch in range(3)]) | |
87 for label, label_color in zip(G.nodes(), node_colors): | |
88 | |
89 cc = (im == label) | |
90 for ch in range(3): | |
91 result[:, :, ch][cc] = label_color[ch] | |
92 | |
93 # Write result image | |
94 skimage.io.imsave(args.output, result) |