From 4e4d82d2d3b3b759f8a50f9b8415dbefe6ea8a9e Mon Sep 17 00:00:00 2001 From: Leonid Kostrykin Date: Tue, 24 Sep 2024 13:17:43 +0200 Subject: [PATCH 1/3] Reduce run time of `build_label_adjacency_graph` function --- tools/colorize_labels/colorize_labels.py | 5 ++--- tools/colorize_labels/colorize_labels.xml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/colorize_labels/colorize_labels.py b/tools/colorize_labels/colorize_labels.py index 47de8c76..24e2d61b 100644 --- a/tools/colorize_labels/colorize_labels.py +++ b/tools/colorize_labels/colorize_labels.py @@ -6,7 +6,6 @@ import numpy as np import scipy.ndimage as ndi import skimage.io -import skimage.morphology as morph import skimage.util @@ -22,7 +21,6 @@ def color_hex_to_rgb_tuple(hex): def build_label_adjacency_graph(im, radius, bg_label): G = nx.Graph() - selem = morph.disk(radius) for label in np.unique(im): if label == bg_label: @@ -31,7 +29,7 @@ def build_label_adjacency_graph(im, radius, bg_label): G.add_node(label) cc = (im == label) - neighborhood = ndi.binary_dilation(cc, selem) + neighborhood = (ndi.distance_transform_edt(~cc) <= radius) adjacent_labels = np.unique(im[neighborhood]) for adjacent_label in adjacent_labels: @@ -62,6 +60,7 @@ def build_label_adjacency_graph(im, radius, bg_label): # Build adjacency graph of the labels G = build_label_adjacency_graph(im, args.radius, args.bg_label) + print('---') # Apply greedy coloring graph_coloring = nx.greedy_color(G) diff --git a/tools/colorize_labels/colorize_labels.xml b/tools/colorize_labels/colorize_labels.xml index b063b5e9..760918ef 100644 --- a/tools/colorize_labels/colorize_labels.xml +++ b/tools/colorize_labels/colorize_labels.xml @@ -4,7 +4,7 @@ creators.xml tests.xml 3.2.1 - 2 + 3 From 39529ed85f664ed4d3fcc580636a3cd8b636c0e6 Mon Sep 17 00:00:00 2001 From: Leonid Kostrykin Date: Tue, 24 Sep 2024 13:22:21 +0200 Subject: [PATCH 2/3] Add failing test case --- tools/colorize_labels/colorize_labels.xml | 12 ++++++++++++ tools/colorize_labels/test-data/input3.tif | Bin 0 -> 540014 bytes 2 files changed, 12 insertions(+) create mode 100644 tools/colorize_labels/test-data/input3.tif diff --git a/tools/colorize_labels/colorize_labels.xml b/tools/colorize_labels/colorize_labels.xml index 760918ef..061d5944 100644 --- a/tools/colorize_labels/colorize_labels.xml +++ b/tools/colorize_labels/colorize_labels.xml @@ -43,6 +43,7 @@ + @@ -52,6 +53,7 @@ + @@ -61,6 +63,16 @@ + + + + + + + + + + diff --git a/tools/colorize_labels/test-data/input3.tif b/tools/colorize_labels/test-data/input3.tif new file mode 100644 index 0000000000000000000000000000000000000000..df9155b7be195b81d87cb8f7cc027c47298eced8 GIT binary patch literal 540014 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 Date: Tue, 24 Sep 2024 14:02:32 +0200 Subject: [PATCH 3/3] Use variable-length color maps to fix previously failing test --- tools/colorize_labels/colorize_labels.py | 18 ++++++++++++++---- tools/colorize_labels/test-data/output1.png | Bin 98 -> 104 bytes tools/colorize_labels/test-data/output2.png | Bin 826 -> 771 bytes tools/colorize_labels/test-data/output3.png | Bin 0 -> 12986 bytes 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tools/colorize_labels/test-data/output3.png diff --git a/tools/colorize_labels/colorize_labels.py b/tools/colorize_labels/colorize_labels.py index 24e2d61b..409b4195 100644 --- a/tools/colorize_labels/colorize_labels.py +++ b/tools/colorize_labels/colorize_labels.py @@ -1,7 +1,7 @@ import argparse import giatools.io -import matplotlib.colors as mpl +import matplotlib.pyplot as plt import networkx as nx import numpy as np import scipy.ndimage as ndi @@ -43,6 +43,18 @@ def build_label_adjacency_graph(im, radius, bg_label): return G +def get_n_unique_mpl_colors(n, colormap='jet', cyclic=False): + """ + Yields `n` unique colors from the given `colormap`. + + Set `cyclic` to `True` if the `colormap` is cyclic. + """ + cmap = plt.get_cmap(colormap) + m = n if cyclic else n - 1 + for i in range(n): + yield np.multiply(255, cmap(i / m)) + + if __name__ == '__main__': parser = argparse.ArgumentParser() @@ -60,14 +72,13 @@ def build_label_adjacency_graph(im, radius, bg_label): # Build adjacency graph of the labels G = build_label_adjacency_graph(im, args.radius, args.bg_label) - print('---') # Apply greedy coloring graph_coloring = nx.greedy_color(G) unique_colors = frozenset(graph_coloring.values()) # Assign colors to nodes based on the greedy coloring - graph_color_to_mpl_color = dict(zip(unique_colors, mpl.TABLEAU_COLORS.values())) + graph_color_to_mpl_color = dict(zip(unique_colors, get_n_unique_mpl_colors(len(unique_colors)))) node_colors = [graph_color_to_mpl_color[graph_coloring[n]] for n in G.nodes()] # Render result @@ -76,7 +87,6 @@ def build_label_adjacency_graph(im, radius, bg_label): for label, label_color in zip(G.nodes(), node_colors): cc = (im == label) - label_color = color_hex_to_rgb_tuple(label_color) for ch in range(3): result[:, :, ch][cc] = label_color[ch] diff --git a/tools/colorize_labels/test-data/output1.png b/tools/colorize_labels/test-data/output1.png index 5a226afd15fa128513b4c505105618225d20dec0..b70b94f2cecf0aee9b4e0394a1f389edd2ec0c89 100644 GIT binary patch delta 73 zcmYewn4sdK@9E+gQZXmFr>iT;fvJaw=j(}@X)9LT)~I1)YfC*HA}Jy9N>XZJ&5B8> bJV3y}Rm^_z=eM=Z3_#%N>gTe~DWM4f0}&eE delta 67 zcmc~unxJB*>FMGaQZXmFr>iT;fl0?bHSp)P{^<)pNJ>a3c*zyGIQ|S!UBv?g49;^n U+RvU6Uc>+dp00i_>zopr06NGQEC2ui diff --git a/tools/colorize_labels/test-data/output2.png b/tools/colorize_labels/test-data/output2.png index d089928b72b00cdf768dcfd5c3058fbe832e4f0a..006ead0b441beaa5b77c9e75caf5ee56b0f56ad9 100644 GIT binary patch delta 748 zcmV3*MYJSuQsfbg>qCu2R%*?FUnFT4b%mqrHXY*oDby^?&gO0H&vn{y-wO9>-ox zUc=?B{!BXLb!0_;SCK78SdN4f-Cur_!s3UD#yQc8^X4&l{zHNwZ59Od+54a*8ZK`q zGiSbVqUp2^>#Oj&xw1)MDb;K(n#^3)Uz*JG?jIOOR+S z`-%Q}P`i>=&m@iC`Z4_*0qfWCfW=sbmDSUbEKLx1%Yv@$jR^q$;8;o~h?|krTByeB z!;96=xEIJTQD!s5T5R9pY$hj&S9`M(zvT50zx|SZL4WFnoXv#d^J;4<+M5zeU4I5V zRx1+#gmpsA1dJ2AFgZCg3k8=6$Lh%BW%f27&Zta&1_0|tnyUsVm{RmId#g-9vz+M^ z)VpaeoO>x5Agnd~7W~M~2=t7}JJIKD@+M9f8FBo|D=ea#nfI$`OiQ$7`Bj6`(+4E#uWIFtR~A--eh(pu88rA$fCY>BG;_h$ z9-fJ-*Pg6wSznqa9e(j24hWmg1QTNnvexOT*Pc`xU0}eB9;ZQA;~&r90nNGPo9~;1 znM17wkTvI)$$!(TSaM|Dt9>KS>tq`AH?dfHw5O3F?F5iT*oh&|8uT}fTQXZOanPDfYWM%ex_?TbTK7N_T zni@Di-v3&-O=A*d+?(zLBJHo$oP$nut$b1b`f2zb&m_p0Gx((aH8hez3MD>2gRlab zxI~=r${Fp6VhkoOPPTsN@rW5KB9qYW;)Y(F*-r8tW9&lVmU1^?=c8kBGUNf2)tP2N zk&|Y*On(TGd2LlzkCImoKiX=9H0coPaxQUhTdhS)NB}uYe!;|GCq^U_K(;+DGdZxB zos8#6wC;mWrZBm&Y)sY^8llYZM`w*ch$u_zn>nji zTPDqAcA^sb|Gf-Y3KOAKj4AMyjM9N+w38PZzJKWekWFC$zN59*0aY8_YNIPx17^OpY)jH?Av(Nx0%mZt{Q(>*~-B=olJ)8CE>}ePIR{RMI6NUw=gv~S5VuH ilO0i7wl2+R1N;xZbs1jjU?{Z!0000Xq@TVM45 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 S{HuRb0NNV*>eXsCq5lUX!UClL literal 0 HcmV?d00001