Skip to content

Image Processing

48 built-in function(s) in this category.

  • AlphaChannel — AlphaChannel[image] gives the image's opacity as a one-channel image. An image with no alpha channel answers with an all-opaque one rather than declining: "how transparent is this?" has an answer for every image, and it is "not at all". Two channels are read as grey+alpha and four as RGB+alpha. (Stable)
  • Binarize — Binarize[image] thresholds image by Otsu's method (see FindThreshold), giving a "Bit" image. Binarize[image, t] thresholds at t. A pixel STRICTLY ABOVE the threshold becomes 1, so a pixel exactly at it becomes 0 -- which matters, because "above" and "at or above" differ on exactly the pixels a threshold was chosen to sit between. A colour image is reduced to luminance first. (Stable)
  • BoxMatrix — BoxMatrix[r] gives a (2r+1) x (2r+1) matrix of 1s. It is NOT normalised, matching Mathematica, so ImageConvolve[image, BoxMatrix[1]] is nine times too bright; the normalised version is a mean filter. Kept faithful rather than helpfully rescaled, since a caller using BoxMatrix in arithmetic needs the ones. (Stable)
  • Closing — Closing[image, r] dilates then erodes with the same element, filling dark features smaller than it. Idempotent, like Opening, and the two bracket the image: Erosion <= Opening <= image <= Closing <= Dilation pointwise everywhere. (Stable)
  • ColorConvert — ColorConvert[image, "Grayscale"] (or "Gray") reduces an image or an Image3D to a single channel using the Rec. 601 luminance weights 0.299 R + 0.587 G + 0.114 B, the same weights every filter here uses when it needs brightness. An image that is ALREADY GREY is returned unchanged, bit for bit, since no weighting happens. An image whose three channels are merely EQUAL is returned only to within an ulp, and whether it is exact depends on the value: those weights sum to 0.9999999999999999 when added in the order they are applied, though to exactly 1.0 in any order beginning with 0.114, so the final rounding lands on the input for some values and one ulp below it for others. The weights are the standard's and are not adjusted to compensate; a triple hand-tuned to sum to exactly 1.0 in double would no longer be Rec. 601. (Stable)
  • ColorQuantize — ColorQuantize[image, n] reduces the image to at most n colours by MEDIAN CUT: the box with the widest single-channel spread is split at its median until n boxes remain, and each collapses to its mean colour. Widest spread rather than most pixels, since a large box of nearly identical colours does not need splitting and a small one spanning half the spectrum does. Median cut rather than k-means because it is DETERMINISTIC -- a palette that depended on the random stream could not be tested or documented. The channel count is preserved and alpha passes through. (Stable)
  • ColorReplace — ColorReplace[image, old -> new] replaces every pixel within a tolerance of old by new; ColorReplace[image, {r1, r2, ...}] applies several rules and ColorReplace[image, rules, tol] sets the tolerance (default 0.02 -- at 0 only bit-identical colours match, which after any filtering is nothing at all). Distance is Euclidean in RGB, and where rules overlap the NEAREST wins rather than the first, so the answer does not depend on the order they were written. Colours may be RGBColor[r, g, b], GrayLevel[v], a number or {r, g, b}. Replacing a grey image's colour with a non-grey one produces a three-channel image, since flattening the new colour to its luminance would give grey when the caller asked for red. An alpha channel passes through: transparency is not a colour. (Stable)
  • CornerFilter — CornerFilter[image] gives the corner strength at every pixel, from the eigenvalues of the Gaussian-weighted second-moment matrix of the gradient (the structure tensor). Both eigenvalues small is flat, one large is an edge, both large is a corner. CornerFilter[image, r] sets the window radius (default 2); CornerFilter[image, r, method] selects "MinimumEigenvalue" (the default -- Shi-Tomasi's lambda_min, which is directly "how much does the weaker direction vary" and is comparable across images) or "Harris" (det - 0.04 trace^2, cheaper since it needs no square root, and negative on edges). A STRAIGHT EDGE SCORES ZERO under both: every gradient in the window is parallel, so the matrix has rank 1 and its determinant and smaller eigenvalue vanish. Colour is reduced to luminance first, since a corner is a property of brightness. (Stable)
  • DerivativeFilter — DerivativeFilter[image, {n, m}] gives the n-th derivative down the rows and the m-th across the columns, each order from 0 to 2. The kernel is a separable outer product of 1-D stencils: order 0 is the smoothing {1,2,1}/4, order 1 the central difference {-1,0,1}/2, order 2 the second difference {1,-2,1}. So {0,1} is Sobel-x and {1,0} is Sobel-y. The stencils are NORMALISED, unlike the raw integer Sobel kernels, which report a gradient eight times the true slope -- harmless when only the ranking of edges matters, and wrong for anything that reads the number. On f(x) = c x the first derivative gives exactly c. The result is a "Real" image. (Stable)
  • Dilation — Dilation[image, r] gives the maximum over a (2r+1) x (2r+1) square neighbourhood; Dilation[image, elem] uses the SUPPORT of the matrix elem -- its nonzero positions -- as the neighbourhood. This is flat morphology: the element's values do not enter the maximum, which is what keeps Dilation[img, BoxMatrix[1]] and Dilation[img, 1] the same operation. Padding replicates the border, the same rule the convolutions use, which is what makes Dilation >= image hold at the edges too. A full rectangle is separable for the maximum exactly as for a sum, so it costs kw + kh comparisons rather than kw * kh. (Stable)
  • DistanceTransform — DistanceTransform[image] replaces each pixel by its EXACT Euclidean distance to the nearest background pixel; background pixels are 0, so the value rises toward the interior of a blob. DistanceTransform[image, t] takes pixels above t as foreground (default 0). Exact rather than the classic two-pass chamfer approximation, which cannot represent sqrt(2) with integer steps and so gets diagonal distances a few percent wrong -- invisible on a picture and fatal to a test. Uses Felzenszwalb and Huttenlocher's lower-envelope-of-parabolas method, O(n) per row with no sorting. Separability is EXACT here because squared Euclidean distance is a sum over the axes, so minimising it decomposes per axis; the square root is taken once at the end rather than per pass. (Stable)
  • EdgeDetect — EdgeDetect[image] finds edges by the Canny algorithm, giving a "Bit" image. EdgeDetect[image, r] sets the Gaussian smoothing radius (default 2; 0 means no smoothing). EdgeDetect[image, r, t] sets the high threshold explicitly. Four stages: smooth, because a derivative amplifies noise; gradient by the normalised Sobel pair; non-maximum suppression along the gradient direction, which is what makes an edge ONE pixel wide rather than a thick band; and hysteresis, keeping any pixel above the high threshold plus any above 0.4 of it that is 8-connected to one, so a real edge survives its faint stretches while isolated weak responses do not. The high threshold defaults to Otsu's method applied to the SUPPRESSED magnitude, where the two classes really are edge against non-edge; on the raw magnitude it would be dominated by the ridge flanks. (Stable)
  • Erosion — Erosion[image, r] gives the minimum over a (2r+1) x (2r+1) square neighbourhood; Erosion[image, elem] uses the support of elem. Dual to Dilation: for a symmetric element, Erosion[f, k] equals 1 - Dilation[1 - f, k] exactly, which holds at the border only because the replicate padding is itself self-dual. (Stable)
  • FindThreshold — FindThreshold[image] gives a threshold separating the image into two classes, by Otsu's method: the level maximising the BETWEEN-class variance w0 w1 (mu0 - mu1)^2, which is algebraically the same as minimising the weighted within-class variance but needs only one incremental pass over a 256-bin histogram. A colour image is reduced to Rec. 601 luminance first. Returns unevaluated for an image whose pixels are all identical, since no threshold splits one cluster into two. (Stable)
  • GaussianFilter — GaussianFilter[image, r] blurs image with a Gaussian of radius r. It is exactly ImageConvolve[image, GaussianMatrix[r]] -- the same matrix through the same convolution, not a second implementation -- and a test asserts the identity. (Stable)
  • GaussianMatrix — GaussianMatrix[r] gives a (2r+1) x (2r+1) Gaussian matrix normalised to sum 1. GaussianMatrix[{r, sigma}] states the standard deviation; it defaults to r/2, which puts the kernel's edge at two standard deviations. Normalisation divides by the realised sum rather than the analytic 2 pi sigma^2, because the analytic constant is correct only for an infinite kernel and using it on a truncated one leaves the sum under 1 -- which darkens an image slightly on every pass. (Stable)
  • GradientFilter — GradientFilter[image] gives the gradient magnitude Sqrt[dx^2 + dy^2], using the normalised Sobel derivatives of DerivativeFilter. The magnitude rather than |dx| + |dy| because it is ROTATION INVARIANT: an edge at 45 degrees reports the same strength as one at 0, where the absolute sum would report it sqrt(2) times stronger and so bias every downstream threshold by orientation. A colour image is reduced to luminance first and differentiated once, rather than differentiated per channel and combined by some arbitrary rule. (Stable)
  • HistogramTransform — HistogramTransform[image] equalises the histogram, spreading the brightness distribution toward uniform over 256 bins by mapping each value through the cumulative distribution. The mapping is computed from the LUMINANCE and applied to every channel as a ratio, so hue survives; equalising each channel independently would shift colour, since it removes exactly the imbalance that makes an image warm or cool. A black pixel has no ratio to scale and takes the new luminance in every channel. Alpha passes through. (Stable)
  • Image — Image[data] is a raster image, normalising to the canonical Image[data, type]. The data is a rectangular height x width array of pixel values, or height x width x channels for a colour image, so it is indexed data[[y, x]] with rows running down the image -- note that ImageDimensions reports {width, height}, transposed relative to this. The type is inferred from the values: all-integer data in {0, 1} is "Bit", all-integer in 0..255 is "Byte", anything else is "Real". Image[data, type] states the type instead, and declines if the data does not fit it. Ragged data declines rather than being padded. (Stable)
  • Image3D — Image3D[data] is a volumetric image, normalising to Image3D[data, type]. The data is a depth x height x width array of voxels, or depth x height x width x channels for colour, so it is indexed data[[z, y, x]] with slices outermost. ImageDimensions reports {width, height, depth} -- FULLY REVERSED from that order, which is Mathematica's convention. Type inference and the accessors match Image: ImageQ is False for a volume (use Image3DQ), while ImageDimensions, ImageChannels, ImageType and ImageData all accept either rank. (Stable)
  • Image3DQ — Image3DQ[expr] gives True if expr is a valid volumetric image in canonical form. Malformed input to Image3D stays unevaluated, so this is how validity is tested. (Stable)
  • ImageAdjust — ImageAdjust[image] stretches to the full range: the darkest pixel becomes exactly 0 and the brightest exactly 1. It is IDEMPOTENT, a second stretch being the identity. A constant image has no range to stretch and comes back unchanged, since dividing by zero is not the answer and mapping the single value to either end would be arbitrary. ImageAdjust[image, {c, b}] and [image, {c, b, g}] apply contrast c, brightness b and gamma g by a curve stated here rather than inferred: v' = (v - 1/2)(1 + c) + 1/2 + b, clipped to [0, 1], then raised to the power 1/g. Contrast pivots about mid-grey so it does not also shift brightness; clipping precedes gamma because a negative base has no real power. This curve is Mathilda's documented choice, not a claim of bit-compatibility with Mathematica. Accepts volumes as well as planes. (Stable)
  • ImageAssemble — ImageAssemble[{{a, b}, {c, d}}] tiles a grid of images into one; ImageAssemble[{a, b}] makes a single row. Each tile keeps its natural size -- a row is as tall as its tallest tile and a column as wide as its widest, and any gap is left blank rather than stretched, since stretching would resample an image the caller did not ask to resize. Alpha survives if any tile had it. (Stable)
  • ImageChannels — ImageChannels[image] gives the number of colour channels: 1 for a grey image, otherwise the length of each pixel's value list (3 for RGB, 4 with an alpha channel). (Stable)
  • ImageCompose — ImageCompose[base, over] alpha-composites over onto base, centred, keeping base's size and clipping whatever falls outside. ImageCompose[base, over, {x, y}] centres the overlay at {x, y} in image coordinates -- x from the left, y from the BOTTOM. ImageCompose[base, {over, a}] scales the overlay's opacity by a. A grey image composed with a colour one produces colour: grey means the same value in every channel, so it is replicated rather than zero-padded. (Stable)
  • ImageConvolve — ImageConvolve[image, kernel] convolves image with the rank-2 numeric kernel. This is true convolution: the kernel is REFLECTED before summing, so it differs from correlation on an asymmetric kernel (the two agree exactly on a symmetric one such as a Gaussian or a box). Out-of-range reads clamp to the nearest edge pixel, replicating the border, so a constant image convolved with a kernel summing to 1 comes back unchanged everywhere including the edges -- zero padding would darken them. The result is always a "Real" image of the same dimensions, since a filtered byte is not generally a byte. Each colour channel is convolved independently. (Stable)
  • ImageCorners — ImageCorners[image] gives the positions of corners. ImageCorners[image, r, t, d, n] sets the window radius (default 2), the threshold as a fraction of the largest response (0.05), the MINIMUM SEPARATION in pixels (0), and the maximum number of features (all). Three filters apply in that order because each removes what the others cannot: a threshold alone returns a blob of adjacent pixels per corner since the response is smooth; 3x3 non-maximum suppression alone returns a maximum in every flat region since a plateau of zeros has maxima; and separation is what makes the list usable, since the first two leave clusters a pixel apart -- 4104 of them on a noise-like 512x512 image. Separation is greedy in DESCENDING RESPONSE order, so the survivor of a cluster is its strongest member rather than whichever came first in raster order, and the feature limit is applied last: before separation it would return n positions from a single cluster. The result is sorted strongest first, ties broken by position so the same image always gives the same list. Positions are {row, column}, 1-based, so each indexes ImageData directly; that is NOT Mathematica's {x, y} from the bottom left, and Mathematica spells the feature limit as a MaxFeatures option where this takes it positionally -- both differences are stated rather than guessed. (Stable)
  • ImageCorrelate — ImageCorrelate[image, kernel] correlates image with kernel: the kernel is NOT reflected, which is the only difference from ImageConvolve. The two are related exactly -- correlation equals convolution with the kernel reversed on both axes -- and they agree on any symmetric kernel, so the distinction only shows on an asymmetric one, where a delta with {{1,2,3}} gives {3,2,1} here and {1,2,3} convolved. ImageCorrelate[image, template, "NormalizedCrossCorrelation"] is template matching: it subtracts the local mean and divides by the local standard deviation, so it measures SHAPE and is invariant to brightness offset and contrast scale. Plain correlation is maximised by brightness rather than similarity -- a white patch beats a correct but darker match -- which is why raw correlation is a poor matcher. Where the template is a crop of the image the score is exactly 1 and is the global maximum. A flat window has no shape to compare and scores 0 rather than dividing by zero; scoring 1 would make every flat region match everything. Colour is reduced to luminance first for the NCC form. (Stable)
  • ImageCrop — ImageCrop[image, {w, h}] crops to w x h about the centre, any odd remainder going to the right and bottom -- the same floor-division convention the kernel centres use, which is what makes ImageCrop[ImagePad[image, m], ImageDimensions[image]] exactly the original image. A crop may not enlarge. ImageCrop[image] instead TRIMS A UNIFORM BORDER, asking how much of the frame carries no information; the border colour is read from a corner rather than assumed black, since a scanned page's margin is white. An entirely uniform image comes back unchanged, there being no content to keep and a zero-sized image not being one. (Stable)
  • ImageData — ImageData[image] gives the pixel array as reals in [0, 1], scaling out the image's type -- a "Byte" 255 comes back as exactly 1.0. The array is height x width, or height x width x channels for a colour image, interleaved. ImageData[image, type] gives the stored values unscaled instead, where type must be the image's own type; converting between types is a separate operation with its own rounding, not something this does silently. (Stable)
  • ImageDimensions — ImageDimensions[image] gives {width, height}. This is TRANSPOSED relative to ImageData, which returns a height x width array -- the same convention Mathematica uses. (Stable)
  • ImageLevels — ImageLevels[image] gives {{level, count}, ...}: the histogram as DATA, not a plot -- use Histogram over the result for a picture. ImageLevels[image, n] uses n bins. Levels are on the same unit scale as ImageData, so a level can be compared against a pixel value without rescaling. A "Bit" image uses its 2 natural levels and "Byte" its 256, because those ARE the distinct values; a "Real" image has no natural set and is binned into 256 over [0, 1]. The counts sum to the pixel count exactly, every pixel landing in one bin. Accepts volumes as well as planes. (Stable)
  • ImagePad — ImagePad[image, m] pads m pixels on every side; ImagePad[image, {{left, right}, {bottom, top}}] pads each side separately, in Mathematica's VISUAL order -- so top adds rows at the start of the data, since row 1 is the top of the image. Negative amounts crop, but may not erase the image. ImagePad[image, m, v] fills with the value v (default 0); ImagePad[image, m, "Fixed"] replicates the edge pixel, the same boundary rule the filters use, so padding then filtering composes with it; ImagePad[image, m, "Reflected"] mirrors WITHOUT repeating the edge -- {1,2,3} padded by 1 gives {2,1,2,3,2}, not {1,1,2,3,3}, because doubling the edge sample biases any later average toward the border. Reflection uses a period of 2n-2, so padding deeper than the image still works. (Stable)
  • ImageQ — ImageQ[expr] gives True if expr is a valid image in canonical form, and False otherwise. Malformed input to Image stays unevaluated, so ImageQ is how validity is tested. (Stable)
  • ImageReflect — ImageReflect[image] reflects top to bottom; ImageReflect[image, Left] or Right reflects left to right, and Top or Bottom is the vertical reflection again -- either name of a pair selects the same axis, since reflecting to the top and reflecting to the bottom are one operation. For an Image3D, Front or Back selects the DEPTH axis, the pair Mathematica uses for volumes; those two DECLINE on a plane, which has no depth axis, rather than being reinterpreted as some other axis and turning a mistake into a wrong picture. A reflection is a pure index permutation, so it interpolates nothing: reflecting twice about the same axis is the identity bit for bit, and reflections about different axes commute exactly. (Stable)
  • ImageResize — ImageResize[image, {w, h}] resizes to w x h pixels; ImageResize[image, w] gives width w with the height following to preserve the aspect ratio. Resampling -> "Nearest" | "Bilinear" | "Average" selects the method; the default Automatic uses AREA AVERAGING when either axis shrinks and bilinear otherwise. That default is about aliasing: point-sampling a shrinking image destroys every frequency above half the new sampling rate -- a fine checkerboard reduced by nearest-neighbour comes back a flat field -- and no interpolation afterwards can restore what point-sampling discarded. Area averaging is a box prefilter and a resample in one pass, exact for integer reduction factors, using true fractional coverage so a 3 -> 2 reduction is as correct as 4 -> 2. Enlarging has no frequencies to remove, so bilinear is used there; area averaging on an enlargement would degenerate to nearest. Coordinates are centre-aligned, avoiding the half-pixel shift that sx = i * scale introduces at any scale other than 1:1. The result is a "Real" image; sizes must be positive integers. (Stable)
  • ImageRotate — ImageRotate[image] rotates a quarter turn counterclockwise; ImageRotate[image, angle] rotates by angle in radians (use n Degree for degrees). A multiple of a right angle takes an EXACT index-permutation path -- every pixel lands on another pixel's position, nothing is interpolated, and four quarter turns are exactly the identity. An odd number of quarter turns swaps the dimensions. Any other angle interpolates bilinearly, sampling the source per destination pixel (inverse mapping, so every output is filled exactly once; forward mapping leaves holes wherever the rotation stretches). Area rotated in from outside reads as 0 rather than the replicated edge, because that area was never photographed and smearing the border across it would invent content. (Stable)
  • ImageType — ImageType[image] gives the pixel type as "Bit", "Byte" or "Real". The type fixes the range of a stored value, which is what makes ImageData's scaling to the unit interval well defined. (Stable)
  • LocalAdaptiveBinarize — LocalAdaptiveBinarize[image, r] binarizes by comparing each pixel to the MEAN of its own (2r+1)x(2r+1) neighbourhood, and LocalAdaptiveBinarize[image, r, {c1, c2, c3}] to c1mean + c2stddev + c3. A global threshold cannot binarize unevenly lit content, and that is not a tuning problem: if one half of a page is darker than the other, no single number separates ink from paper in both halves at once. Mean alone (the default {1, 0, 0}) is Bradley's method; a negative c2 is Sauvola's, tightening the threshold where the neighbourhood is busy. Summed-area tables make the window statistics O(1) per pixel regardless of r -- without them a radius-16 window would be 1089 taps per pixel. The result is typed "Bit", since it is binary by construction. Colour is reduced to luminance first. (Stable)
  • MeanFilter — MeanFilter[image, r] averages over a (2r+1) x (2r+1) neighbourhood. This IS a convolution with a normalised box, and it is implemented as one rather than as a separate averaging loop -- two implementations of one identity is how the identity quietly stops holding. Being a full rectangle the kernel is separable, so it costs kw + kh rather than kw * kh. (Stable)
  • MedianFilter — MedianFilter[image, r] replaces each pixel with the median over a (2r+1) x (2r+1) neighbourhood. Unlike a Gaussian it removes an isolated outlier EXACTLY rather than attenuating and smearing it, which is what makes it the filter for salt-and-pepper noise. It is also the one filter here that is NOT separable: a sum, a maximum and a minimum all decompose because they ignore grouping, but a median depends on a value's rank within the whole window, and grouping destroys rank -- the median of row medians of {{1,2,9},{3,4,5},{6,7,8}} is 4 where the true median is 5. For an even window the lower middle is taken rather than the average of the two, so the output is always one of the inputs. (Stable)
  • MorphologicalComponents — MorphologicalComponents[image] labels the connected components of the foreground, giving an INTEGER MATRIX with background 0 and components numbered 1..k in raster order of first appearance. MorphologicalComponents[image, t] takes pixels above t as foreground (default 0, so nonzero is foreground). CornerNeighbors -> False uses 4-connectivity instead of the default 8. Two pixels touching only at a corner are ONE component under 8 and TWO under 4, which is the property that distinguishes the two rules -- every other property holds under either. A matrix rather than an Image, deliberately: Image type inference would call a label array of 1..12 a "Byte" image and ImageData would then divide every label by 255. Labels are indices, not brightnesses. Contiguous labels in scan order mean Max of the result is the component count. (Stable)
  • Opening — Opening[image, r] erodes then dilates with the same element, removing bright features smaller than it while leaving larger ones close to their original size. IDEMPOTENT: Opening[Opening[f]] equals Opening[f], which is the defining property and the reason opening twice is not a sharpening loop. (Stable)
  • Pruning — Pruning[image] removes one pixel from every free end of the foreground; Pruning[image, n] repeats that n times, which shortens each branch by up to n and deletes any branch shorter than that. Used after Thinning to remove the short spurs a skeleton grows at boundary irregularities. An end point has exactly one foreground neighbour, so an ISOLATED pixel is not one and survives: pruning shortens branches rather than erasing specks. Pruning[image, 0] is the image unchanged. The result is a "Bit" image. (Stable)
  • RandomImage — RandomImage[] gives a 150x150 grey image of uniform noise on [0, 1]. RandomImage[max] scales the range to [0, max]; RandomImage[max, {w, h}] sets the size, and a single n means {n, n}. ColorSpace -> "RGB" gives three independent channels. Samples are drawn from the same stream as RandomReal, so SeedRandom makes the result reproducible. (Stable)
  • RemoveAlphaChannel — RemoveAlphaChannel[image] drops the alpha channel. RemoveAlphaChannel[image, b] instead COMPOSITES over a background of brightness b, which is the difference between forgetting the transparency and resolving it: a half-transparent white pixel over black is grey, where dropping alpha would leave it white. (Stable)
  • SetAlphaChannel — SetAlphaChannel[image] attaches a fully opaque alpha channel. SetAlphaChannel[image, a] sets one opacity everywhere when a is a number in [0, 1], or per pixel when a is an image of the same dimensions (read as grey, so a colour mask is not taken as its red channel alone). A mask of the wrong size is declined rather than resampled. (Stable)
  • Thinning — Thinning[image] reduces the foreground to a one-pixel-wide skeleton by Zhang-Suen thinning, iterating until a pass deletes nothing. Thinning[image, n] stops after n iterations. The two subiterations are what preserve connectivity: deleting every individually-removable pixel in one pass severs a diagonal line, since two diagonal neighbours can each be removable while removing both disconnects the shape. A non-binary image is thresholded at 0.5 -- apply Binarize first for any other rule. The result is a "Bit" image, and it is always a subset of the input. (Stable)