Analysis of a binary image¶
This tutorial explains how to analyze a 2D binary image by persistent homology. You learn the following topics in this tutorial.
- How to compute a PD (Persistence Diagram) from a image
- How to visualize the PD
- How to output birth-death pairs in the text format
- How to apply basic inverse analysis called birth pixels and death pixels
- How to use high-level inverse analysis called optimal volume
The PD is computed from a filtration constructed by signed distance transform. This means that the black area in the binary image is shrinked and expanded and HomCloud captures the information of the appearance and disappearance of connected components and holes. Please see Section 2.3 in https://arxiv.org/abs/1706.10082 .
How to compute a PD¶
The example image file is binary-image.png
. First, we display the image.
display < binary-image.png
The following command computes a PD.
python3 -m homcloud.pict.binarize_nd -T picture2d -m black-base -t 128 -s -o binary-image.pdgm binary-image.png
Then, binary-image.pdgm
is generated.
The meaning of the options are explained below:
-T picture2d
- The input data is 2D and stored a signle image file- You can use other formats such as text data (
text2d
) or numpy's npy format (npy
).
- You can use other formats such as text data (
-m black-base
- The black area is analyzed. If you want to analyze the white area, please use-m white-base
instead.-t 128
- The threshold of black and white.-D
- You should always use this option.-I
- Useful additional information is appended to a PD file-o binary-image.pdgm
- The output file name is binary-image.pdgm-s
The black area is shrinked and expanded.- If this option is not given, The area is only expanded
- I recommend that this option is always used.
How to visualize a PD¶
We learn how to visualize a PD. Now the 0th PD is visualized.
plot_PD
is used in the same way as pointclouds.
The following command plots a 0th PD.
-d 0
- The 0th PD is plotted-l
- The colorbar is log-scaled-o binary-image-pd0.png
- The output file name
python3 -m homcloud.plot_PD -d 0 -l --aspect equal binary-image.pdgm -o binary-image-pd0.png
display < binary-image-pd0.png
Some small points appear in the figure. In fact, we use the manhattan distance for the computation
and all birth times and death times are integer values for that reason. Therefore
the resolution is too fine for the visualization. Now we adjust the resolution.
The options -x "[-20.5:7.5]" -X 28
changes the range and the number of bins.
The size of each bin is adjusted to 1x1 and the center of each bin is adjusted to an integer point.
python3 -m homcloud.plot_PD -d 0 -l -x "[-20.5:7.5]" -X 28 --aspect equal binary-image.pdgm -o binary-image-pd0.png
display < binary-image-pd0.png
How to output the birth-death pairs into a text file¶
The way is the same as pointcloud case. The following command saves the pairs into binary-image-pd0.txt
.
python3 -m homcloud.dump_diagram -d 0 -S no binary-image.pdgm -o binary-image-pd0.txt
head binary-image-pd0.txt
-19.0 -18.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -18.0 -17.0 -16.0 -15.0
Birth pixels and death pixels¶
From the above PD, you see that many birth-death pairs are concentrated at (-5, -4). Now we try to analyze these pairs. We use birth pixels and death pixels. Please see Section 2.3 in https://arxiv.org/abs/1706.10082 . In this paper, birth/death pixels are called birth/death positions.
The following command outputs the pixels. The option -S yes
switches on the output.
python3 -m homcloud.dump_diagram -d 0 -S yes binary-image.pdgm
-19.0 -18.0 (57,121) (56,121) -18.0 -17.0 (47,112) (46,112) -18.0 -17.0 (48,113) (47,113) -18.0 -17.0 (49,114) (48,114) -18.0 -17.0 (50,115) (49,115) -18.0 -17.0 (51,116) (50,116) -18.0 -17.0 (52,117) (51,117) -18.0 -17.0 (53,118) (52,118) -18.0 -17.0 (46,111) (53,119) -16.0 -15.0 (73,111) (72,112) -16.0 -15.0 (74,110) (73,110) -14.0 -13.0 (40,112) (40,111) -14.0 -13.0 (83,113) (82,113) -14.0 -13.0 (84,114) (83,114) -14.0 -13.0 (85,115) (84,115) -14.0 -13.0 (86,116) (85,116) -14.0 -13.0 (87,117) (86,117) -14.0 -13.0 (88,118) (87,118) -14.0 -13.0 (89,119) (88,119) -14.0 -13.0 (90,120) (89,120) -14.0 -13.0 (91,121) (90,121) -14.0 -13.0 (92,122) (91,122) -13.0 -12.0 (37,114) (37,113) -11.0 -10.0 (9,112) (8,112) -9.0 -8.0 (75,98) (74,98) -9.0 -8.0 (74,97) (75,99) -8.0 -7.0 (47,96) (46,100) -8.0 -7.0 (50,94) (49,94) -8.0 -7.0 (71,95) (71,96) -7.0 -6.0 (48,34) (47,34) -7.0 -6.0 (68,93) (68,94) -6.0 -5.0 (26,55) (25,55) -6.0 -5.0 (28,105) (28,106) -6.0 -5.0 (36,30) (36,31) -6.0 -5.0 (51,27) (50,27) -6.0 -5.0 (51,36) (50,36) -6.0 -5.0 (52,26) (51,26) -6.0 -5.0 (53,25) (52,25) -6.0 -5.0 (54,24) (53,24) -6.0 -5.0 (55,23) (54,23) -6.0 -5.0 (56,22) (55,22) -6.0 -5.0 (57,21) (56,21) -6.0 -5.0 (58,20) (57,20) -6.0 -5.0 (59,12) (58,12) -6.0 -5.0 (59,19) (58,19) -6.0 -5.0 (58,11) (59,13) -7.0 -5.0 (62,15) (59,18) -6.0 -5.0 (103,31) (102,31) -6.0 -5.0 (104,32) (103,32) -5.0 -4.0 (9,35) (8,35) -5.0 -4.0 (10,36) (9,36) -5.0 -4.0 (11,37) (10,37) -5.0 -4.0 (18,45) (17,45) -5.0 -4.0 (19,46) (18,46) -5.0 -4.0 (20,48) (19,48) -5.0 -4.0 (21,49) (20,49) -6.0 -4.0 (25,54) (21,50) -5.0 -4.0 (25,103) (24,103) -11.0 -4.0 (7,111) (25,104) -5.0 -4.0 (28,17) (27,17) -5.0 -4.0 (30,58) (29,58) -5.0 -4.0 (31,23) (30,23) -5.0 -4.0 (32,25) (31,25) -5.0 -4.0 (27,15) (32,26) -5.0 -4.0 (44,79) (43,79) -5.0 -4.0 (49,1) (48,1) -5.0 -4.0 (50,3) (49,3) -5.0 -4.0 (48,0) (50,4) -5.0 -4.0 (73,81) (72,81) -5.0 -4.0 (75,82) (74,82) -5.0 -4.0 (82,85) (81,85) -8.0 -4.0 (44,32) (82,23) -5.0 -4.0 (84,86) (83,86) -5.0 -4.0 (86,87) (85,87) -5.0 -4.0 (87,67) (86,67) -5.0 -4.0 (87,88) (86,88) -5.0 -4.0 (91,69) (90,69) -5.0 -4.0 (92,48) (91,48) -5.0 -4.0 (93,70) (92,70) -5.0 -4.0 (94,49) (93,49) -5.0 -4.0 (94,71) (93,71) -5.0 -4.0 (94,95) (93,95) -5.0 -4.0 (95,50) (94,50) -6.0 -4.0 (98,74) (94,72) -5.0 -4.0 (96,51) (95,51) -5.0 -4.0 (99,53) (98,53) -5.0 -4.0 (42,80) (99,108) -5.0 -4.0 (102,79) (101,79) -5.0 -4.0 (103,81) (102,81) -5.0 -4.0 (104,83) (103,83) -5.0 -4.0 (105,84) (104,84) -5.0 -4.0 (106,85) (105,85) -5.0 -4.0 (108,35) (107,35) -5.0 -4.0 (109,36) (108,36) -5.0 -4.0 (111,37) (110,37) -5.0 -4.0 (112,38) (111,38) -5.0 -4.0 (112,64) (111,64) -5.0 -4.0 (114,39) (113,39) -5.0 -4.0 (115,40) (114,40) -5.0 -4.0 (116,67) (115,67) -5.0 -4.0 (117,41) (116,41) -5.0 -4.0 (117,68) (116,68) -5.0 -4.0 (118,42) (117,42) -5.0 -4.0 (119,98) (118,98) -5.0 -4.0 (120,70) (119,70) -6.0 -4.0 (127,105) (119,99) -6.0 -4.0 (127,49) (120,44) -5.0 -4.0 (121,71) (120,71) -5.0 -4.0 (124,73) (123,73) -6.0 5.0 (4,29) (47,69) -15.0 6.0 (99,20) (67,50)
The first column has birth times, the second column has death times, the third column has birth pixels, and the fourth column has death pixels.
Please note that each coordinate is ordered by (y, x). This is because numpy's indexing rule.
We extract all birth/death pixels for the pairs (-5, -4). We use pipe and grep command.
python3 -m homcloud.dump_diagram -d 0 -S yes binary-image.pdgm | grep "^-5.0 -4.0"
-5.0 -4.0 (9,35) (8,35) -5.0 -4.0 (10,36) (9,36) -5.0 -4.0 (11,37) (10,37) -5.0 -4.0 (18,45) (17,45) -5.0 -4.0 (19,46) (18,46) -5.0 -4.0 (20,48) (19,48) -5.0 -4.0 (21,49) (20,49) -5.0 -4.0 (25,103) (24,103) -5.0 -4.0 (28,17) (27,17) -5.0 -4.0 (30,58) (29,58) -5.0 -4.0 (31,23) (30,23) -5.0 -4.0 (32,25) (31,25) -5.0 -4.0 (27,15) (32,26) -5.0 -4.0 (44,79) (43,79) -5.0 -4.0 (49,1) (48,1) -5.0 -4.0 (50,3) (49,3) -5.0 -4.0 (48,0) (50,4) -5.0 -4.0 (73,81) (72,81) -5.0 -4.0 (75,82) (74,82) -5.0 -4.0 (82,85) (81,85) -5.0 -4.0 (84,86) (83,86) -5.0 -4.0 (86,87) (85,87) -5.0 -4.0 (87,67) (86,67) -5.0 -4.0 (87,88) (86,88) -5.0 -4.0 (91,69) (90,69) -5.0 -4.0 (92,48) (91,48) -5.0 -4.0 (93,70) (92,70) -5.0 -4.0 (94,49) (93,49) -5.0 -4.0 (94,71) (93,71) -5.0 -4.0 (94,95) (93,95) -5.0 -4.0 (95,50) (94,50) -5.0 -4.0 (96,51) (95,51) -5.0 -4.0 (99,53) (98,53) -5.0 -4.0 (42,80) (99,108) -5.0 -4.0 (102,79) (101,79) -5.0 -4.0 (103,81) (102,81) -5.0 -4.0 (104,83) (103,83) -5.0 -4.0 (105,84) (104,84) -5.0 -4.0 (106,85) (105,85) -5.0 -4.0 (108,35) (107,35) -5.0 -4.0 (109,36) (108,36) -5.0 -4.0 (111,37) (110,37) -5.0 -4.0 (112,38) (111,38) -5.0 -4.0 (112,64) (111,64) -5.0 -4.0 (114,39) (113,39) -5.0 -4.0 (115,40) (114,40) -5.0 -4.0 (116,67) (115,67) -5.0 -4.0 (117,41) (116,41) -5.0 -4.0 (117,68) (116,68) -5.0 -4.0 (118,42) (117,42) -5.0 -4.0 (119,98) (118,98) -5.0 -4.0 (120,70) (119,70) -5.0 -4.0 (121,71) (120,71) -5.0 -4.0 (124,73) (123,73)
It looks good! For 0th PD, the death pixels are more important since the pixels are located in the center of
the structures, so we show these death pixels on the input image.
view_index_pict
module is available for visualization.
python3 -m homcloud.view_index_pict -d 0 -B -f "birth == -5" -f "death == -4" --no-label \
binary-image.png binary-image.pdgm -o binary-image-markers.png
display < binary-image-markers.png
-d 0
- The degree of homology-B
- Birth pixels are shown-f "birth == -5" -f "death == -4"
- We can filter birth-death pairs by their birth time and death time. You can use equalities and inequalities. For example, if-f "birth >= -3" -f "birth <= -1"
is given, all birth-death pairs whose birth time is more than and equal to -3 and less than and equal to -1.--no-label
- It means that only pixels are shown. If this option is not specified, birth/death times are also shown to the image.binary-image.png binary-image.pdgm
- You can specify the image file and the PD file.-o binary-image-markers.png
- Output file name There are many other options.
Some red points are shown on the black road. This means that the pairs (-5, -4) correspond the black road strucures whose width is about 8 pixels to 10 pixels.
Powerful invese analysis¶
Each pair in 0th PD corresponds a connected component (an island), but the death pixel of the pair can only visualize one pixel in the island. Although the birth/death pixels are easy to use and their computation cost is quite cheap, the information is a little. We want to see the whole islands. We can see such islands by using HomCloud.
pict.tree
module computes the structures and pict.show_volume_2d
module visualizes them.
python3 -m homcloud.pict.tree -m black-base -s -t 128 -T picture2d binary-image.png -o binary-image-tree.pdgm
The following shows some options of homcloud.pict.tree
. The meanings of -m
, -T
, -t
, -s
options are the same
as homcloud.pict.binarize_nd
.
You should specifies the output file name by -o
option.
The extension is usually .pdgm
, in common with persistence diagrams.
We visualize the result by pict.show_volume_2d
module.
-d 0 -f "birth == -5" -f "death == -4"
is the same asview_index_pict
.-B
shows birth pixels.--volume
is required to visualize the islands.--alpha 0.5
specifies the alpha value of the volume. You can use the value less than 1 and more than 0.- The image file, pdgm file, and the output file are specified by
binary-image.png binary-image-tree.pdgm -o binary-image-volumes.png
python3 -m homcloud.pict.show_volume_2d -d 0 -f "birth == -5" -f "death == -4" -B --volume --alpha 0.5 \
binary-image.png binary-image-tree.pdgm -o binary-image-volumes.png
display < binary-image-volumes.png
In the above figure, a narrow red areas appear in the black roads. The light red area shows the computed area, and the strong red points are birth-pixels.
You get better understandings from the analysis by pict.tree
.
The tutorial finishes here.