Qu

imdilate

Builtin index · Images

result = imdilate(img, radius) <br> imdilate(img, se=)

Input: img, radius · Output: result

What it is

img is a binary (0/255 mask-style) Image; radius is a positive integer, the half-width of a square structuring element of side 2*radius+1 (a documented choice over a disk element). Performs binary morphological dilation, growing foreground regions.

Overloads

2 forms. Each carries its own inputs, outputs and worked example — pick the tab for the one you are calling.

CodeInputOutputDescription
result = imdilate(img, radius) <br> imdilate(img, se=)
img Imageimg a binary (0/255) Image.
radius —Dilation/erosion/opening/closing/top-hat/bottom-hat all reduce to their textbook binary definitions on a genuine mask: the foreground blob grows outward by radius, and every output pixel stays exactly 0 or 255 — no new grey levels ever appear.
Image —from disk()/line(), or hand-built
—

Examples

Written for this form and run by the build -- the output below is what the engine actually produced.

mb = [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 255, 0, 0; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]
binary_img = image_from_matrix(mb)
grown = imdilate(binary_img, 1)
print(imhist(grown, n_bins=4))   # [16, 0, 0, 9] -- only the two extreme bins are ever used

output
[16, 0, 0, 9]
CodeInputOutputDescription
result = imdilate(img, radius) <br> imdilate(img, se=)
img Imageimg a genuine grayscale (or color) Image with more than two intensity levels.
radius Imageradius is a positive integer, the half-width of a square structuring element of side 2*radius+1 (a documented choice over a disk element).
Image —from disk()/line(), or hand-built
imdilate/imerode/imopen/imclose/imtophat/imbothat are all implemented as a per-channel MAX (dilate) or MIN (erode) over the structuring window — true grayscale morphology, not "threshold then grow." Fed a smooth image, the intermediate grey levels shift around instead of snapping everything to black/white.

Examples

Written for this form and run by the build -- the output below is what the engine actually produced.

mg = [10, 60, 110, 160, 210; 20, 70, 120, 170, 220; 30, 80, 130, 180, 230; 40, 90, 140, 190, 240; 50, 100, 150, 200, 250]
gray_img = image_from_matrix(mg)
grown = imdilate(gray_img, 1)
print(imhist(grown, n_bins=4))   # [0, 6, 7, 12] -- three separate bins in use, no black survives at all

output
[0, 6, 7, 12]

How it works

and foreground/background separation (§ blob-manipulation pass, 2026-08-24). See image::Image's own "Binary morphology..." doc-comment section for the full binary-mask convention this whole group shares: a Value::Image is treated as "binary" when every pixel is grayscale (R=G=B) with two intended levels, 0 = background / 255 = foreground (is_foreground actually reads >=128, so a slightly antialiased mask still behaves sanely). No threshold/ otsu_threshold builtin existed in this shared working tree when this landed (a sibling agent's own lane) — this is a documented, independent design choice, not a guess at matching code that hadn't landed yet; reconcile if the sibling's own producer ends up using a different convention. imerode(img, radius) / imdilate(img, radius) — a square structuring element of side 2*radius+1 (documented choice over a disk — see image::Image::erode's doc comment). Additive se= kwarg (§ SE/hit-miss/watershed pass, 2026-09-25): an explicit structuring-element mask Image (disk()/line(), or hand-built) in place of the radius-implied square — radius is simply not read at all when se= is given, so the old two-positional-argument form keeps working unchanged.

From the note above this builtin in the interpreter, where the reasoning was written down as it was built.