cutan.carve.refine¶
Clean a raw matte into a cut-out’s alpha: keep the subject, close it, edge it, de-spill it.
Each step is a function of arrays, so a caller can run any of them alone;
cutan.carve.carve() runs them in this order:
keep_components()— keep the part under the hint point (else the largest), dropping specks and the stray objects a matte also caught;fill_holes()— a pale face or an eye a matte called background;detach_bridges()— cut what hangs on the subject by a thin neck (a caption’s letters touching a head);despill()— re-paint the rim’s colour from the subject’s interior, so no backdrop colour is left in the semi-transparent edge.
Module Attributes
The alpha above which a pixel counts as the subject's. |
Functions
|
Pull the matte's edge in by |
|
Re-paint the edge's colours from the subject's interior; |
|
Cut away what hangs on the main body by a neck narrower than |
|
Soften the edge with a Gaussian of |
|
|
|
The components of the boolean |
- cutan.carve.refine.choke(alpha, px)[source]¶
Pull the matte’s edge in by
pxpixels (a smooth, distance-based erosion).>>> a = np.zeros((9, 9), np.float32); a[1:8, 1:8] = 1 >>> float(choke(a, 2)[1, 4]), float(choke(a, 2)[4, 4]) (0.0, 1.0)- Return type:
ndarray
- cutan.carve.refine.despill(rgb, alpha, rim, *, solid=None)[source]¶
Re-paint the edge’s colours from the subject’s interior;
(rgb, repainted share).The subject is
solid(the alpha BEFORE any feathering; defaultalpha) aboveSUBJECT. Trusted pixels are those at leastrimpx inside its edge (a distance, not an alpha: a soft interior is still interior). Repainted: every other pixel with some alpha — the anti-aliased band, a neural matte’s fuzzy fringe, what feathering spread over the backdrop — which is never more thanrimpx plus the fringe from the edge. Colours flow outward from the trusted pixels one pixel per pass, each the mean of its known neighbours, never from the backdrop. An outline stays an outline: it is solid, so its inner part is trusted. The share is of the subject’s pixels, the quality signal for a de-spill that repainted real content.>>> rgb = np.zeros((7, 7, 3), np.uint8); rgb[:] = (0, 0, 255) # a blue backdrop >>> rgb[1:6, 1:6] = (200, 0, 0); rgb[1, 1:6] = (100, 0, 160) # a red subject, a spilt top row >>> a = np.zeros((7, 7), np.float32); a[1:6, 1:6] = 1 >>> out, share = despill(rgb, a, 1) >>> tuple(int(c) for c in out[1, 3]), round(share, 2) ((200, 0, 0), 0.64)
- cutan.carve.refine.detach_bridges(mask, radius, *, point=None)[source]¶
Cut away what hangs on the main body by a neck narrower than
2 * radiuspx.Erodes by
radius, keeps the eroded component underpoint(else the largest), grows it back byradius + 1inside the original mask. Returns(mask, pieces): the cleaned mask and how many pieces it lost (connected parts of what was removed, at leastradius²px: a caption glyph, and also a thin part thinner than2 * radiuspx, which erosion cannot tell apart).>>> m = np.zeros((20, 40), bool); m[2:18, 2:18] = True # a body >>> m[9:11, 18:24] = True; m[6:14, 24:32] = True # a glyph on a 2-px neck >>> out, pieces = detach_bridges(m, 2) >>> pieces, bool(out[10, 28]), bool(out[10, 10]) (1, False, True)
- cutan.carve.refine.feather(alpha, sigma)[source]¶
Soften the edge with a Gaussian of
sigmapx (0 leaves it as it is).- Return type:
ndarray
- cutan.carve.refine.fill_holes(mask)[source]¶
maskwith every enclosed hole filled.>>> m = np.ones((5, 5), bool); m[2, 2] = False >>> bool(fill_holes(m)[2, 2]) True- Return type:
ndarray
- cutan.carve.refine.keep_components(mask, *, point=None, keep='point', min_share=0.02, gap=6)[source]¶
The components of the boolean
maskto keep.keep:"point"keeps the component underpoint(the largest when the point is off the subject or not given) and the pieces lying withingappx of it that are at leastmin_shareof its area (a hand or a hat a matte separated by a sliver);"largest"keeps the largest only;"all"keeps everything.>>> m = np.zeros((10, 30), bool); m[1:9, 1:9] = True; m[4:6, 25:27] = True >>> int(keep_components(m, keep="largest").sum()), int(keep_components(m, keep="all").sum()) (64, 68) >>> int(keep_components(m, point=(25, 4)).sum()) # the small piece, alone 4 >>> m[4:6, 11:13] = True # a piece 2 px from the body >>> int(keep_components(m, point=(4, 4), min_share=0.05).sum()) 68- Return type:
ndarray