Skip to main content

Connected components on discrete and continuous multilabel 3D and 2D images. Handles 26, 18, and 6 connected variants; periodic boundaries (4, 8, & 6).

Project description

PyPI version DOI

cc3d: Connected Components on Multilabel 3D Images

Binary and multilabel connected components. (a) A binary image (foreground white,  background black) (b) 4-connected CCL of binary image (c) 8-connected CCL of binary image (d) A multilabel image (e) 4-connected CCL of multilabel image (f) 8-connected CCL of multilabel image
Fig. 1. Binary and Multilabel Connected Components Labeling (CCL) 2D images are shown for simplicity. Black is the background color (zero). (a) A binary image (foreground white, background black) (b) 4-connected CCL of binary image (c) 8-connected CCL of binary image (d) A multilabel image (e) 4-connected CCL of multilabel image (f) 8-connected CCL of multilabel image.

Continuous value connected components (top) A three tone grayscale image with signed additive low magnitude noise (bottom) Extracted components using continuous value CCL with a delta value greater than the noise magnitude but smaller than the difference between tones
Fig. 2. Continuous Value Connected Components Labeling (CCL) (top) A three tone grayscale image with signed additive low magnitude noise (bottom) Extracted components using continuous value CCL with a delta value greater than the noise magnitude but smaller than the difference between tones

cc3d is an implementation of connected components in three dimensions using a 26, 18, or 6-connected neighborhood in 3D or 4 and 8-connected in 2D. This package uses a 3D variant of the two pass method by Rosenfeld and Pflatz augmented with Union-Find and a decision tree based on the 2D 8-connected work of Wu, Otoo, and Suzuki. This implementation is compatible with images containing many different labels, not just binary images. It also supports continuously valued images such as grayscale microscope images with an algorithm that joins together nearby values.

I wrote this package because I was working on densely labeled 3D biomedical images of brain tissue (e.g. 512x512x512 voxels). Other off the shelf implementations I reviewed were limited to binary images. This rendered these other packages too slow for my use case as it required masking each label and running the connected components algorithm once each time. For reference, there are often between hundreds to thousands of labels in a given volume. The benefit of this package is that it labels all connected components in one shot, improving performance by one or more orders of magnitude.

In general, binary images are much more common (usually resulting from image thresholding), but multi-label images crop up in instance segmentation and semantic labeling as a classifier may label touching clusters of adjacent pixels differently. If a gap between different labels is guaranteed, then the problem degenerates into the binary version.

Check out benchmarks to see a comparison with SciPy on a few different tasks.

Python pip Installaction

If compatible binaries are available for your platform, installation is particularly simple.

pip install connected-components-3d

If compatible binaries are not available, you can install from source as follows.

Requires a C++ compiler.

pip install numpy
pip install connected-components-3d --no-binary :all:

Occasionally, you may appear to successfully install cc3d, but on import you'll see an error that includes: numpy.ufunc size changed, may indicate binary incompatibility. You can either try upgrading numpy or compiling cc3d from source in this case.

Python Manual Installation

Requires a C++ compiler.

pip install -r requirements.txt
python setup.py develop

Python Use

The following functions are available with examples below:

  • Connected Component Labeling (CCL)
  • Calculating centroids, bounding boxes, and voxel counts
  • Removal of small objects ("dust") (or large objects)
  • Extraction of k largest objects
  • Fast extraction of all objects one-by-one
  • Calculation of contact surface area and contact network
  • Extraction and coloring of a per voxel connectivity graph
import cc3d
import numpy as np

labels_in = np.ones((512, 512, 512), dtype=np.int32)
labels_out = cc3d.connected_components(labels_in) # 26-connected

connectivity = 6 # only 4,8 (2D) and 26, 18, and 6 (3D) are allowed
labels_out = cc3d.connected_components(labels_in, connectivity=connectivity)

# By default, cc3d works on multivalued labelings, but sometimes you want
# to treat a grayscale image as a binary image directly. It is also possible
# to process binary images more effectively. Binary image specific optimizations 
# are not implemented yet though, but may be in the future.
labels_out = cc3d.connected_components(labels_in, binary_image=True)
# same as above, but less efficient
labels_out = cc3d.connected_components(labels_in > 0) 

# If you need the borders to wrap around (e.g. for simulations, world maps)
# specify periodic_boundary=True, currently only supported for
# 4 and 8 (2d) and 6 (3d) connectivities.
labels_out = cc3d.connected_components(
  labels_in, connectivity=connectivity, periodic_boundary=True
)

# If you need a particular dtype you can specify np.uint16, np.uint32, or np.uint64
# You can go bigger, not smaller, than the default which is selected
# to be the smallest that can be safely used. This can save you the copy
# operation needed by labels_out.astype(...).
labels_out = cc3d.connected_components(labels_in, out_dtype=np.uint64)

# If you're working with continuously valued images like microscopy
# images you can use cc3d to perform a very rough segmentation. 
# If delta = 0, standard high speed processing. If delta > 0, then
# neighbor voxel values <= delta are considered the same component.
# The algorithm can be 2-10x slower though. Zero is considered
# background and will not join to any other voxel.
labels_out = cc3d.connected_components(labels_in, delta=10)

# If you're working with an image that's larger than memory you can
# use mmapped files. The input and output files can be used independently.
# In this case an array labels.bin that is 5000x5000x2000 voxels and uint32_t
# in Fortran order is computed and the results are written to out.bin in Fortran
# order. You can find the properties of the file (shape, dtype, order) by inspecting
# labels_out.
labels_in = np.memmap("labels.bin", order="F", dtype=np.uint32, shape=(5000, 5000, 2000))
labels_out = cc3d.connected_components(labels_in, out_file="out.bin")

# Here's another strategy that you can use for huge files that won't even
# take up any disk space. Provide any iterator to this function that produces
# thick z sections of the input array that are in sequential order.
# The output is a highly compressed CrackleArray that is still random access.
# See: https://github.com/seung-lab/crackle
# You need to pip install connected-components-3d[stack] to get the extra modules.
def sections(labels_in):
  """
  A generator that produces thick Z slices
  of an image
  """
  for z in range(0, labels_in.shape[2], 100):
    yield labels_in[:,:,z:z+100]

# You can access compressed_labels_out using array notation
compressed_labels_out = cc3d.connected_components_stack(sections(labels))
# convert to numpy array, probably a big mistake since
# you probably expected it was going to blow up RAM
cc_labels = compressed_labels_out.numpy()
# if you don't like hanging onto this exotic format, you 
# can write it as a numpy array to disk in a memory efficient way.
compressed_labels_out.save("example.npy.gz")
# or hang onto it
compressed_labels_out.save("example.ckl")


# You can extract the number of labels (which is also the maximum 
# label value) like so:
labels_out, N = cc3d.connected_components(labels_in, return_N=True) # free
# -- OR -- 
labels_out = cc3d.connected_components(labels_in) 
N = np.max(labels_out) # costs a full read

# You can extract individual components using numpy operators
# This approach is slow, but makes a mutable copy.
for segid in range(1, N+1):
  extracted_image = labels_out * (labels_out == segid)
  process(extracted_image) # stand in for whatever you'd like to do

# If a read-only image is ok, this approach is MUCH faster
# if the image has many contiguous regions. A random image 
# can be slower. binary=True yields binary images instead
# of numbered images.
for label, image in cc3d.each(labels_out, binary=False, in_place=True):
  process(image) # stand in for whatever you'd like to do

# Image statistics like voxel counts, bounding boxes, and centroids.
stats = cc3d.statistics(labels_out)

# Remove dust from the input image. Removes objects with
# fewer than `threshold` voxels.
labels_out = cc3d.dust(
  labels_in, threshold=100, 
  connectivity=26, in_place=False
)
# Removes objects with >= `threshold` voxels.
labels_out = cc3d.dust(labels_in, threshold=100, invert=True)
# Removes objects with < `threshold[0]` voxels and >= threshold[1] 
labels_out = cc3d.dust(labels_in, threshold=[50,100])
# Removes objects with >= `threshold[0]` voxels and < threshold[1] 
labels_out = cc3d.dust(labels_in, threshold=[50,100], invert=True)

# Get a labeling of the k largest objects in the image.
# The output will be relabeled from 1 to N.
labels_out, N = cc3d.largest_k(
  labels_in, k=10, 
  connectivity=26, delta=0,
  return_N=True,
)
labels_in *= (labels_out > 0) # to get original labels

# Compute the contact surface area between all labels.
# Only face contacts are counted as edges and corners
# have zero area. To get a simple count of all contacting
# voxels, set `surface_area=False`. 
# { (1,2): 16 } aka { (label_1, label_2): contact surface area }
surface_per_contact = cc3d.contacts(
  labels_out, connectivity=connectivity,
  surface_area=True, anisotropy=(4,4,40)
)
# same as set(surface_per_contact.keys())
edges = cc3d.region_graph(labels_out, connectivity=connectivity)

# You can also generate a voxel connectivty graph that encodes
# which directions are passable from a given voxel as a bitfield.
# This could also be seen as a method of eroding voxels fractionally
# based on their label adjacencies.
# See help(cc3d.voxel_connectivity_graph) for details.
graph = cc3d.voxel_connectivity_graph(labels, connectivity=connectivity)

# ...and turn it back into labeled values (probably
# not exactly the same ones). Note: this function currently
# assumes an undirected graph, so single voxel alterations are
# likely to go awry.
new_labels = cc3d.color_connectivity_graph(graph, connectivity=connectivity)

Note: C and Fortran order arrays will be processed in row major and column major order respectively, so the numbering of labels will be "transposed". The scare quotes are there because the dimensions of the array will not change.

C++ Use

#include "cc3d.hpp"

// 3d array represented as 1d array
int* labels = new int[512*512*512](); 

uint32_t* cc_labels = cc3d::connected_components3d<int>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512
);

// The default template parameter for output type is uint32_t
uint64_t* cc_labels = cc3d::connected_components3d<int, uint64_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512
);

uint16_t* cc_labels = cc3d::connected_components3d<int, uint16_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*connectivity=*/18 // default is 26 connected
);

size_t N = 0;
uint16_t* cc_labels = cc3d::connected_components3d<int, uint16_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*connectivity=*/26, /*N=*/N // writes number of labels to N
);

#include "cc3d_continuous.hpp"

// For handling grayscale images. Note that the difference
// is the addition of the "delta" argument.
uint16_t* cc_labels = cc3d::connected_components3d<int, uint16_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*delta=*/10, /*connectivity=*/6 // default is 26 connected
);

#include "cc3d_graphs.hpp"

// edges is [ e11, e12, e21, e22, ... ]
std::vector<uint64_t> edges = cc3d::extract_region_graph<uint64_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*connectivity=*/18 // default is 26 connected
);

// graph is a series of bitfields that describe inter-voxel
// connectivity based on adjacent labels. See "cc3d_graphs.hpp"
// for details on the bitfield. 
uint32_t* graph = extract_voxel_connectivity_graph<T>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*connectivity=*/6 // default is 26 connected
);

26-Connected CCL Algorithm

The algorithm contained in this package is an elaboration into 3D images of the 2D image connected components algorithm described by Rosenfeld and Pflatz (RP) in 1968 [1] (which is well illustrated by this youtube video) using an equivalency list implemented as Tarjan's Union-Find disjoint set with path compression and balancing [2] and augmented with a decision tree based on work by Wu, Otoo, and Suzuki (WOS), an approach commonly known as Scan plus Array-based Union-Find (SAUF). [3] The description below describes the 26-connected algorithm, but once you understand it, deriving 18 and 6 are simple. However, we recently made some changes that warrant further discursion on 6-connected.

First Principles in 2D

In RP's 4-connected two-pass method for binary 2D images, the algorithm raster scans and every time it first encounters a foreground pixel (the pixels to its top and left are background), it marks it with a new label. If there is a preexisting label in its neighborhood, it uses that label instead. Whenever two labels are adjacent, it records they are equivalent so that they can be relabeled consistently in the second pass. This equivalency table can be constructed in several ways, but some popular approaches are Union-Find with path compression with balancing by rank and Selkow's algorithm (which can avoid pipeline stalls). [4] However, Selkow's algorithm is designed for two trees of depth two, appropriate for binary images. We would like to process multiple labels at the same time, making Union-Find preferable.

In the second pass, the pixels are relabeled using the equivalency table. Union-Find establishes one label as the root label of a tree, and the root is considered the representative label. Each pixel is then labeled with the representative label. Union-Find is therefore appropriate for representing disjoint sets. Path compression with balancing radically reduces the height of the tree, which accelerates the second pass.

WOS approached the problem of accelerating 8-connected 2D connected components on binary images. 8-connected labeling is achieved by extending RP's forward pass mask to the top left and top right corner pixels. In Union-Find based connected components algorithms, the unify step in the first pass is the most expensive step. WOS showed how to optimize away a large fraction of these calls using a decision tree that takes advantage of local topology. For example, since the top-center neighbor of the current pixel is also adjacent to the other mask elements, all of which have already been processed by virtue of the raster scan direction, if it is present it is sufficient to copy its value and move on. If it is absent, pick one of the remaining foreground pixels, copy their value, and use unify for the mask element on the right as it is now known to be non-neighboring with the left hand side. WOS's algorithm continues in this fashion until a match is found or all mask elements are processed at which point a new label is created.

For several years, this algorithm was the world's fastest, though it has been superceded by a newer work that exchanges the static decision tree for a dynamic one or precalculated generated one amongst other improvements. However, WOS's work is significant for both its simplicity and speed and thus serves as the inspiration for this library. For 2D 8-connected images, we provide a specialization using Wu et al's original decision tree for a slight performance boost.

We're interested in exploring the block based approaches of Grana, Borghesani, and Cucchiara ([5],[7]), however their approach appears to critically rely on binary images. We'll continue to think about ways to incorporate it. We also considered the approach of He et al [8] which is also supposed to modestly faster than than WOS. However, it substitutes the Union-Find data structure (one array) with three arrays, which imposes a memory requirement that is at odds with our goal of processing large images.

Extending to 3D

The approach presented below is very similar to that of Sutheebanjard [6]. To move to a 3D 26-connected neighborhood, the mask must be extended into three dimensions in order to connect neighboring planes. Observe that the 8-connected mask covers the trailing half of the neighborhood (the part that will have been already processed) such that the current pixel can rely on those labels. Thus the mask for the 26-connected neighborhood covers only two out of three potential planes: the entire lower plane (nine voxels), and a mask identical to WOS's (four voxels) on the current plane. While some further optimizations are possible, to begin, the problem can be conceptually decomposed into two parts: establishing a 9-connected link to the bottom plane and then an 8-connected link to the current plane. This works because the current pixel functions as a hub that transmits the connection information from the 9-connected step to the 8-connected step.

Fig. 1: Mask for an 8-connected plane. If J,K,L, and M are all eliminated, only N remains and a new label is assigned.

j k l
m n .
. . .

The very first Z plane (Z=0) the algorithm runs against is special: the edge effect omits the bottom plane of the mask. Therefore, as the remaining mask is only comprosed of the 8-connected 2D mask, after this pass, the bottom of the image is 8-connected. At Z=1, the 9-connected part of the mask kicks in, forming connections to Z=0, making the current plane now (8 + 9) 17-connected. At Z=2, the 9-connected bottom mask now forms connections from Z=1 to Z=2 on the top, making Z=1 (17 + 9) 26-connected. By induction, when this process proceeds to completion it results in a 26-connected labeling of the volume.

Following inspiration from WOS, we construct a decision tree on the densely labeled bottom plane that minimizes the number of unifications we need to perform.

Fig 2. The mask for the lower plane in 3D.

a b c
d e f
g h i

As e is connected to all other voxels, if present, it can simply be copied. If e is absent, b and h fully cover the mask. If b is absent, h, a, c comprise a covering. If h is absent, b, g, i are one. Below is a list of coverings such that each proceeding entry in the list assumes the first letters in the entries above are background.

  1. e
  2. k, (h | g, i)
  3. b, (h | g, i)
  4. h, a, c
  5. m, (f | c, i)
  6. d, (f | c, i)
  7. f, g, a
  8. a, c, g, i
  9. c, g, i
  10. g, i
  11. i

The decision tree is then constructed such that each of these coverings will be evaluated using the fewest unifications possible. It's possible to further optimize this by noting that e and b are both fully connected to the upper 2D mask. Therefore, if either of them are present, we can skip the 8-connected unification step. It's also possible to try the DF covering first if B is background, which would save one unification versus HAC given even statistics, but it seems to be slightly slower on the dataset I attempted. To move from binary data to multilabel data, I simply replaced tests for foreground and background with tests for matching labels.

In order to make a reasonably fast implementation, I implemented union-find with path compression. I conservatively used an IDs array qual to the size of the image for the union-find data structure instead of a sparse map. The union-find data structure plus the output labels means the memory consumption will be input + output + rank + equivalences. If your input labels are 32-bit, the memory usage will be 4x the input size. This becomes more problematic when 64-bit labels are used, but if you know something about your data, you can decrease the size of the union-find data structure. I previously used union-by-size but for some reason it merely reduced performance and increased memory usage so it was removed.

For more information on the history of connected components algorithms, and an even faster approach for 2D 8-connected components, consult Grana et al's paper on Block Based Decision Trees. [5,7]

Phantom Labels

In the course of thinking of improvements to several algorithms, we developed a technique we term "Phantom Labeling" for improving the SAUF method directly.

Definition: Phantom Labels are elements of a CCL mask that 
transmit connectivity information between other elements of the 
mask but cannot directly pass their value to the current pixel 
during the first pass of a SAUF derived algorithm.

Reproducing Fig. 1 again, but with new letters for the more limited problem, the standard SAUF mask appears like so:

Fig. 3: Mask for an 8-connected plane.

a b c
d x .
. . .

This results in a decision tree like so assuming x is a foreground pixel.

if b:
    x := b
elif a:
    x := a 
    if c:
        unify(a,c)
elif d:
    x := d
    if c: 
        unify(c,d)
elif c:
    x := c
else:
    x := new label

There is an opportunity here for eliminating up to half of the unify calls, one of the more expensive operations in modern CCL by slightly modifying the mask:

Fig. 4: 8-connected mask modified to include phantom label P.

. P .
a b c
d x .
. . .

This results in a modified decision tree.

if b:
    x := b
elif a:
    x := a 
    if c and not P: <--- change here
        unify(a,c)
elif d:
    x := d
    if c: 
        unify(c,d)
elif c:
    x := c
else:
    x := new label

The novelty of this technique is unclear, but it is very simple to apply and results in substantial speed ups for the 4 and 6 connected problems, a minor improvement for 8-connected, and is readily compatible with the multi-label approach unlike block based approaches.

4 and 6-Connected CCL Algorithm

Here is where the phantom label technique shines. It's a bit harder to find 4 and 6 connected algorithms in the literature, I assume because many of the techniques invented for the 8-way problem, such as the Union-Find data structure for the equivalency table and run-based approaches, are applicable to the simpler problem. However, the SAUF decision tree approach was lacking as every pixel required a unify call in the 4-way problem and two in the 6-way problem.

Fig. 5: 4-connected mask modified to include phantom label P.

P b .
a x .
if a:
    x := a
    if b and not P:
        unify(a,b)
elif b:
    x := b
else:
    x := new label

This gives a decent improvement on the order of 10-20%. If you're lucky, you might not incur even a single label merge operation. In the 6-way problem, there are three phantom labels that can be exploited and the improvement is closer to 50% on our data, a fairly substantial amount. Again, with luck you might avoid any unify operations at all.

Fig. 6: Mask for the 6-way problem with phantom labels P, Q, and R added.

P b
a x
. Q
R c

You can even use multiple routes to propagate information if a label is missing. For example, if path (a,P,b) is unavailable due to a missing P, you could potentially transmit information using path (a,R,c,Q,b).

Four Pass Algorithm

We introduce two additional passes over the image label prior to running the two-pass SAUF algorithm. These additional passes are used to collect statistcs for optimizing the SAUF passes.

Estimating Provisional Labels

The first additional pass is used to over-estimate the number of provisional labels generated by the first SAUF pass. A better estimation allows a smaller allocation for the Union-Find datastructure. For some operating systems, the reduced size of the allocation and improved caching recovers more time than is spent collecting statistics.

This can be computed by counting the number of transitions between labels along each row of the image. This scan is easily written such that the instructions can be vectorized to minimize the cost of the scan. The number of transitions is guaranteed to be larger than or equal to the number of provisional labels as all provisional labels are generated in this fashion and then reduced by stealing a label from a neighboring voxel.

A hierarchy of estimators can be written as:

0 <= provisional labels <= X transitions <= static estimate <= voxels

Binary images can also be estimated statically as voxels / 2 for 4 and 6-way, voxels / 4 for 8 and 18 way, and voxels / 8 for 26 connected. For multi-label images, the best static estimate is voxels as no assumptions can be made about how labels connect to each other (in the worst case all eight voxels in a cube have different labels).

It is also possible to check XY and XYZ transitions to get a tighter bound, but in experiments, the amount of time spent checking those directions exceeded the benefit obtained by checking the X pass. Often the X pass alone results in factors as high as voxels / 100.

Estimation of the number of labels also allows aborting processing before the first SAUF pass in the case of an all background cube.

Estimating Foreground Location

The second additional pass is estimating the location of the foreground. In the literature, this strategy is sometimes referred to as a "one-and-a-half pass" where the foreground location is computed during the first SAUF pass and then used to skip processing of background voxels during the relabeling pass.

Here we perform this check up front so that it can be performed minimally. Instead of integrating the calculation into the first pass which could force some computation on every voxel, we scan each row from the left to find the first foreground voxel and then scan from the right to the find the foreground voxel at the end. The results are tabulated in a uint32 table of starts and ends to each row of size 2 * sy * sz. This ensures that the volume is scanned at most once, and most likely much less if the shapes fill the space reasonably well. Then, both passes of the SAUF method scan only the part of each row indicated by this table.

Certain shapes and distributions defeat the efficiency of scanning only the starts and ends of the row (such as random images or an image with foreground on the start and end of each row and nowhere else). However, for a great many shapes, this provides substantial efficiencies and minimal downside for a dense multi-label image as only two YZ slices of the images are scanned before the table is completed.

Early Abortion Points

There are three locations in the algorithm at which further processing can be aborted early without changing the result.

  1. After estimating provisional labels if zero transitions are detected (an all zeros volume). A black image is returned.
  2. After the first SAUF pass if the number of provisional labels is zero or one. In this case, the provisional labels are guaranteed to be identical to final labels.
  3. After assigning final labels to each provisional label in a translation array. If the number of final labels equals the number of provisional labels, the provisional labels were accurately assigned and the relabeling scan can be skipped.

Papers Using cc3d

A number of papers are using cc3d now. Many of them seem to be deep learning applications as instance segmentation is liable to generate touching non-binary labels. Some are in geoscience, neuroscience, and medical fields. If cc3d is helpful to you, please feel free to email us and let us know. We might be able to offer some tips if its performance critical (though we can't guarantee timeliness of response). There are so many variations of the CCL problem, you might be surprised at what you can do.

https://scholar.google.com/scholar?as_ylo=2019&q=connected-components-3d&hl=en&as_sdt=0,31

References

  1. A. Rosenfeld and J. Pfaltz. "Sequential Operations in Digital Picture Processing". Journal of the ACM. Vol. 13, Issue 4, Oct. 1966, Pg. 471-494. doi: 10.1145/321356.321357 (link)
  2. R. E. Tarjan. "Efficiency of a good but not linear set union algorithm". Journal of the ACM, 22:215-225, 1975. (link)
  3. K. Wu, E. Otoo, K. Suzuki. "Two Strategies to Speed up Connected Component Labeling Algorithms". Lawrence Berkeley National Laboratory. LBNL-29102, 2005. (link)
  4. S. Selkow. "The Tree-to-Tree Editing Problem". Information Processing Letters. Vol. 6, No. 6. June 1977. doi: 10.1016/0020-0190(77)90064-3 (link)
  5. C. Grana, D. Borghesani, R. Cucchiara. "Optimized Block-based Connected Components Labeling with Decision Trees". IEEE Transactions on Image Processing. Vol. 19, Iss. 6. June 2010. doi: 10.1109/TIP.2010.2044963 (link)
  6. P. Sutheebanjard. "Decision Tree for 3-D Connected Components Labeling". Proc. 2012 International Symposium on Information Technology in Medicine and Education. doi: 10.1109/ITiME.2012.6291402 (link)
  7. C. Grana, D. Borghesani, R. Cucchiara. "Fast Block Based Connected Components Labeling". Proc. 16th IEEE Intl. Conf. on Image Processing. 2009. doi: 10.1109/ICIP.2009.5413731 (link)
  8. L. He, Y. Chao and K. Suzuki, "A Linear-Time Two-Scan Labeling Algorithm", IEEE International Conference on Image Processing, vol. 5, pp. 241-244, 2007.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

connected_components_3d-3.24.0.tar.gz (77.8 kB view details)

Uploaded Source

Built Distributions

connected_components_3d-3.24.0-cp313-cp313-win_amd64.whl (505.1 kB view details)

Uploaded CPython 3.13Windows x86-64

connected_components_3d-3.24.0-cp313-cp313-win32.whl (558.4 kB view details)

Uploaded CPython 3.13Windows x86

connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

connected_components_3d-3.24.0-cp313-cp313-macosx_11_0_arm64.whl (684.1 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

connected_components_3d-3.24.0-cp313-cp313-macosx_10_13_x86_64.whl (766.2 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

connected_components_3d-3.24.0-cp312-cp312-win_amd64.whl (505.8 kB view details)

Uploaded CPython 3.12Windows x86-64

connected_components_3d-3.24.0-cp312-cp312-win32.whl (556.5 kB view details)

Uploaded CPython 3.12Windows x86

connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

connected_components_3d-3.24.0-cp312-cp312-macosx_11_0_arm64.whl (685.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

connected_components_3d-3.24.0-cp312-cp312-macosx_10_13_x86_64.whl (768.0 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

connected_components_3d-3.24.0-cp311-cp311-win_amd64.whl (520.0 kB view details)

Uploaded CPython 3.11Windows x86-64

connected_components_3d-3.24.0-cp311-cp311-win32.whl (569.7 kB view details)

Uploaded CPython 3.11Windows x86

connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

connected_components_3d-3.24.0-cp311-cp311-macosx_11_0_arm64.whl (692.7 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

connected_components_3d-3.24.0-cp311-cp311-macosx_10_9_x86_64.whl (776.8 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

connected_components_3d-3.24.0-cp310-cp310-win_amd64.whl (519.3 kB view details)

Uploaded CPython 3.10Windows x86-64

connected_components_3d-3.24.0-cp310-cp310-win32.whl (570.6 kB view details)

Uploaded CPython 3.10Windows x86

connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

connected_components_3d-3.24.0-cp310-cp310-macosx_11_0_arm64.whl (691.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

connected_components_3d-3.24.0-cp310-cp310-macosx_10_9_x86_64.whl (780.8 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

connected_components_3d-3.24.0-cp39-cp39-win_amd64.whl (519.4 kB view details)

Uploaded CPython 3.9Windows x86-64

connected_components_3d-3.24.0-cp39-cp39-win32.whl (571.2 kB view details)

Uploaded CPython 3.9Windows x86

connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.0 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

connected_components_3d-3.24.0-cp39-cp39-macosx_11_0_arm64.whl (691.9 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

connected_components_3d-3.24.0-cp39-cp39-macosx_10_9_x86_64.whl (781.4 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

Details for the file connected_components_3d-3.24.0.tar.gz.

File metadata

  • Download URL: connected_components_3d-3.24.0.tar.gz
  • Upload date:
  • Size: 77.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for connected_components_3d-3.24.0.tar.gz
Algorithm Hash digest
SHA256 a77efece9e042d030b984b67560ff9ebe1fa46f3d0a9a2b093a275bf0722eaa0
MD5 6fc75647d51e2ed0c2a4f8616ac280fb
BLAKE2b-256 f40a3ac254653885abbcd0d8966be56da83cd49917a9b24f0d12fa541f025e03

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e5b5dfed48449490691267611540a7ec1f528c1ca853542a5348728e06e5f691
MD5 535f8298516cb4abe0867797c1d45ceb
BLAKE2b-256 232d9a452c82e46a9471d5c7b45512ef17fb5269b6a7279c87fe8d26301937e0

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-win32.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-win32.whl
Algorithm Hash digest
SHA256 accefec81c645ae73d5e596f560a8d1ebd7eae52db242cc5cece64c382f70402
MD5 81552f6f5d37cea82f6731096124c654
BLAKE2b-256 150263a5a4e684a8bdd6834011c0751b0dabac0664cedf2aeb789cf1f90dd043

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6f11295ac7b9f0c4cbbd79009786b75590ee45f1673edf97f1f54c188c6b1833
MD5 721abb2f3f10f1d8612742a959c10424
BLAKE2b-256 2876e0cb6a0af347b422d968c8d22bd458821a1710df08fb6ecf5d04dc73f81a

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f55c429038530290e7479602fb80b03cadd5a31b18c5d9d66c005eb7adba7249
MD5 78702a0cad5ca98d351793ca9891913a
BLAKE2b-256 ae9f76e4575c90f48a7cca6011cf819ac00c0c0553c8394618804383ad99c27e

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c4b5db80c07292ce19f0b227468e306401936da584e9ac82420a6459a50f4707
MD5 cf30abf539ee70e0374e64e358a4c7ca
BLAKE2b-256 39c0afb675852295d82cb4e75d20fd302ef1be535b7504f0d7ef6993ea336d93

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 19d5b311072e4932c53515e82e0478648772b5d4ba9fe2d9f1bb04a1f12466d7
MD5 12651b898d993be6a9759bf2d507e2f0
BLAKE2b-256 18632895ae5fe9f9e95e728a559b76c3f43bf4b255c55868deb5e0efe7369af6

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 96cc26066262776bbba0befb4ceee0ab38d085d0b6bcc4070325c1260694cdb9
MD5 80fd4e893e37299cfd12dd6f59b6916f
BLAKE2b-256 30dd8107f40cce27c100ab10d1509b9588289ad9372b8dc0de8ed68cf436cd88

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-win32.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 10073997c8c37bd9b5c27776a43f047b261d6bf9df7475c403a4ca6e13cad03f
MD5 3334a12d9930ad999189c60a596d90e0
BLAKE2b-256 2d37c1ab642d034eb34328bc5ed8e3a5409bf839d4ae413c6b3bc6235729dfc2

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a1d51c8492a883e93664ee476a9173ec65de16c7cd4684f44b57c817ace95a46
MD5 009d110eb6d56a487ce63b32cc22dfeb
BLAKE2b-256 cd1f160640c198905dc72c25a816e87dc073f20a2a9ba155935a9bcf41462162

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4797e904ec623b6fec2c6a7dec46a4689e3ffe88bbe503803e288305610983e3
MD5 e950dc328b7af40a4fbf4f088bba8b79
BLAKE2b-256 758944a8af873715a397efcbbbc3f5bc6c71fb6cc290db67baeba6a9760b8906

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 94fce3d81b11aa050d93a52f10ec6da1d6fc70330d5046a064633c8314755108
MD5 62a60e4bc4f8f2f3b9c90d3d617d4d86
BLAKE2b-256 af6aa7cda054e33f5fdb7d930a81b31015a922210bf7f315abd8c3142ae5b14e

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 cc9e882944bdb37be44f4cd4e030b17eaf5c8b3de4b76c68fed2c57e753b9479
MD5 14f605ba48a166bbaf6e1cba0415a8ec
BLAKE2b-256 d68297c6c5570364ca20d1ca7c5e5f91186d327f3e46f8c889e67aa9237f277b

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a83cf2be95562bdedca509a362d0cce983ca35493381e5bf47926ec4f4bd06a2
MD5 2f4cf249b7154bca601d4dad05db35d0
BLAKE2b-256 6c52425fe0b0fa048de33789101b726add2ea95b04d32327c4878ef3188b63c8

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-win32.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 517d0eeaa3151668ff0c26d1cb0aa5939ecf6ad541a368c4742f4e8730f601f2
MD5 c691e9e3d47b1f2ef0fbca69566e141f
BLAKE2b-256 6f4c3c8db41908ea386d18af14ba5b33623f7682ee9192be4d4b9e9204c2050d

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0e650e1dfb1c1a4f1c1e489708086e6a03a01adfe14d541ade1a1043ec28bf36
MD5 8f986d3cdf5ac3f2e431faf364ecaa4d
BLAKE2b-256 1165069c8679c630b6ea42af9d534a4a3aaadccc5e8f136bfd11ef89d57e8edd

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 05d541d10ffd5d09a8b6db84b770f4d23c534516860bd162eaa3291a359d2431
MD5 8f5f65d0f6436333d9c410880f5246d4
BLAKE2b-256 0fd6001ce20aaa9455c48370b064ddfbc857b5c39645ac1809a3a930ce7a4024

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9b79517b8ad49e5433ccf9242bf9784813b132d46ea655d335037ce1e6dc940e
MD5 872eb346a554443a5c68282d54397642
BLAKE2b-256 41985c8643b0e69e434961976685fb91d6de9f8dc2625a7ba8d632fa921befc6

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4f3e68df68533439957a32f953b3f0f5586f28087320a5305c97d5121f1de82f
MD5 e6b0f45c56b78abe573a687de602d4fb
BLAKE2b-256 7dd863dfd42ad05acba3a4683e423da76630d36de87bd7409a897578805c1c41

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 6478ff6b09b031b42fb59863872d9fb58ebce6bddb984e78a2145e5cdcb04414
MD5 f83262efe4110087edc82f41877593dc
BLAKE2b-256 9f83c8d912f98af833e95b405a9bd7d33ee81c411d7db207dfaceb1cdbde8242

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-win32.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 9c044d28d3509807f81f888581d16f814a514ece2e4ed0168f26afa4a1bc9bce
MD5 4eeccb1306be96023dfd58a1892ccd3a
BLAKE2b-256 299b475c335000e635e9263bd3840939db9f328322f741a6f35617301a280d08

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9fd5afa0ff4d7c452ffa46095d8cd689727c35fc372581bc8ca0906e2f09b289
MD5 fb3e41ba68c1a349741f74ea6873b125
BLAKE2b-256 c159567a5b86ae5159176681919a4e0a973cf5a2a820b09b000d46da34a94cc0

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4def2957701881a6663815c4d75c6678cb7dceee473162cc40f0282617270ac5
MD5 6b835bede6eef2d832d7e087051d3735
BLAKE2b-256 fcbb769dd72b52144997993e356d12114f0b246608d5ddc97fd889790b26a990

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9d90d03156adc272dbb13cbdab61bb1d5005ec1c2accaa5ece3d5eb996fd9619
MD5 ed90c3f32c07f7f05d4663fab13e9e89
BLAKE2b-256 2a5f2810fba57b7b07199c2d72ce85e3b37784597ca553b581b359e7fca14b03

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 bf2c00d0e27f1b6b95f9b72b2fc98732301d5160dc9ee2ea648060ff7f67ceca
MD5 cf74080a9844843f7eb88281046eb7e1
BLAKE2b-256 0249b3c42a927029ab63fac2ccb200398cf6f97a4b134d148c4d37e267428baf

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 c392284424d124ec053bf83b76232961836e629a51bffeaa6dc453845e2eb855
MD5 b80b79d9955ac775a13b07d4c6b1ec2c
BLAKE2b-256 639e269a845bd6bc17f6e9f7cc9f8644d92f3315910cf3088370be26f9baf429

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-win32.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 814fe4ddf3cb09d1c8f01b99d10f5c35990d6df904f516892914746fb2424f84
MD5 f741f2b734aec4df2e2e93b424ff1a39
BLAKE2b-256 27cfc446bb51e770d4eb00c3af9770eb2b4b8057d6c12a4e38f34f9c9bc7b618

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 01187b4649d189d2b0cd75cce414e78f7f88566603c60f92922912d62db108f4
MD5 a38abb0f0271ff1b7a32498c97545124
BLAKE2b-256 94f178b87e6b633d2b0e3b31e7f54333823893a204e861c19f077314570439f6

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fa4e0a3b92bdc733f3306f7b225f223ce791f920e94eda02a1e0c58a80670a5b
MD5 22d468cba47d4979e56ac82c674d7b32
BLAKE2b-256 a2d4bf8bf0e1679f339f4be80d6bdae56f5cd49d8a0acfc1ab5c6b3da1699ac3

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 289530bbcf4c9b099fe26acfdb7b25c8da180f2c1d2254f1346b853bfea18fa8
MD5 0704bb45e0caef48797d8a9a6dcb7e21
BLAKE2b-256 cb60c59c384b35eaa5a6d3b5aba75ce52ea1a124bac89e490310141c25540364

See more details on using hashes here.

File details

Details for the file connected_components_3d-3.24.0-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-3.24.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 887a6648a5698c695de29a302e5dc586709a10f53ace0c9bd9237544713aa810
MD5 0ce2a21703ac4b4f6f1aa57e3c9c534c
BLAKE2b-256 69e8930e1ccb44c8f0f0af62c2d969b1897d340664ad365aef811f5df7ca9431

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page