A picture is a grid of numbers, and its simplest pattern is a set of stripes, with a frequency and a direction. Watch the stripes below turn with the dot beside them, and close in as it moves away from the centre.
A frequency with a direction
x[n₁, n₂] = 0.5 + 0.5 cos(2π(u n₁ + v n₂)) on 128 × 128 pixels.
u = 1/16, v = 0: upright stripes 16.0 pixels apart; the dot lies on the across axis.
Describe this picture
The grating on 128 × 128 pixels, in two square panels. The first draws the grating in grey levels, each pixel as a small square of whole screen pixels. The second is the frequency plane, across and down, each from −0.5 to 0.5 cycles per pixel, with growing downward as the rows do. On it a filled dot marks , joined to the centre by a thin line, and an open ring marks the mirror, . The readouts are and in cycles per pixel, the spacing in pixels and the direction in degrees from the axis toward . The 13 s clip opens on : upright stripes 16.0 pixels apart, the dot on the across axis. From 3.5 s the dot turns 45° about the centre at the same distance: and read 0.0442, and the stripes turn with it and stay 16.0 pixels apart. From 8 s it moves to : level stripes 8.0 pixels apart, twice the frequency, half the spacing, at 90°. When the clip ends, drag the dot anywhere in the plane, or use the arrow keys: each press moves it by 1/128 of a cycle per pixel, Shift with an arrow by 1/16, and Home brings it back to . Its place is kept in the link, as grating.u and grating.v, and the caption gives the spacing and the direction.
A frequency with a direction
Look closely at a phone screen and you see tiny squares of light, in rows and columns. Each square is a pixel, and it shows one brightness. So a picture on a screen is a grid of numbers.
Where do the numbers come from? A camera’s sensor is a grid of small light meters, so a photograph is the scene sampled at a grid of points. That is the sampling of Sampling & aliasing (10.1), with dots in two directions instead of one.
I write the brightness of one pixel as , from 0 for black to 1 for white. The first index, , is the column, counted across from the image’s left edge. The second, , is the row, counted down from the top, the way we read text. An image is this signal of two indices.
Stripes
The simplest pictures are stripes. Take one row and make it a sinusoid that repeats every 16 pixels, as in Sinusoids (3.2), “Height and repeat time”: . The 0.5 in front and the height 0.5 keep the brightness between 0 and 1.
Give every row the same values, and you get upright stripes, 16 pixels apart. Along a row the wave goes through 1/16 of a cycle per pixel. Now let both indices take part:
Here is the number of cycles per pixel as you go across, and the number as you go down. They are plain numbers, set once for the whole picture. A picture like this is a grating, and the pair is its spatial frequency: cycles per pixel of distance, not per second.
In radians per pixel the two parts are and , the of 3.2 counted per pixel instead of per sample. On this page I quote them in cycles per pixel, as and .
Size and direction
Where are the stripes? The brightness depends only on the sum . Walk in a direction that keeps that sum the same, and the brightness stays the same: that path is a stripe. The sum stays the same when you walk at right angles to the arrow from to .
So the stripes run at right angles to . Now walk a distance along that arrow instead. The sum grows by , and one cycle has passed when it has grown by 1. The stripes are therefore
pixels apart. The size of the spatial frequency, , sets the spacing. Its direction is the angle of the arrow, measured from the across axis and turning toward down. Think of a ploughed field: how close the furrows are and which way they run are two separate facts.
To draw a spatial frequency, I use a map with across and down, each from −0.5 to 0.5. I call it the frequency plane, and one grating is a point on it. Why it stops at half a cycle per pixel comes in the next section.
A grating shows up on the plane as two dots, not one. In Complex exponentials & phasors (3.4) a cosine was two arrows spinning opposite ways. Here the two arrows are , one at and one at , mirror images through the centre.
The picture at the top of the page draws both: the grating, and its dot and mirror on the plane.
Notice the middle frame. After the turn, and have both fallen to 0.0442, yet the spacing is still 16.0 pixels. Along one row, the turned stripes now cross every pixels. The spacing is measured across the stripes, the shortest way: 1 over the size of the frequency, 0.0625.
When the clip ends, the dot is yours. Pull it toward the centre and watch the stripes spread apart; turn it and watch them turn.
Half a cycle per pixel, in each direction
Follow one row of a grating. There is fixed, so the row is a sinusoid with cycles per pixel. By 10.1’s “Where a tone lands”, and give the same samples:
The extra is a whole number of turns. A cosine is even as well, so and look the same along a row. That leaves from −0.5 to 0.5, and the same argument down a column leaves from −0.5 to 0.5.
So a picture holds spatial frequencies up to half a cycle per pixel in each part, and the frequency plane is that square. Each part has its own limit. The grating is fine, though its size, 0.566, is more than 0.5.
A finer pattern comes back as a coarser, false one somewhere else in the square. That is aliasing, and the next instrument shows it happening.
Skip pixels, and false rings appear
To see where aliasing happens in a picture, I want every spatial frequency at once, each at its own place. A zone plate does that. On 256 × 256 pixels, with and from 0 to 255, it is
where and are the pixel’s offsets from the centre, across and down. Its brightness makes rings around the centre, and they close in as you move out.
How many cycles per pixel do the rings have near a given pixel? Step one pixel across, from to . The angle inside the cosine grows by
which is of a cycle. So near offset the rings have about cycles per pixel across, and about down.
At the centre that is 0. At the edges it reaches about half a cycle per pixel: the step from to is 0.498 of a cycle. Every spatial frequency in the square appears once, the frequency at offset .
Keep every M-th pixel
Now shrink the zone plate the crudest way: keep every -th pixel in each direction, . This is “Keep every M-th sample: the spectrum stretches and folds” of Downsampling and decimation (22.1), done across and down.
There every frequency was multiplied by , and here too. A pattern with cycles per original pixel has cycles per kept pixel, and it folds when passes ½. Near offset , , so the rings fold where
The same holds down, with . So everything farther than pixels from the centre, across or down, aliases. The limit is cycle per original pixel, and it halves each time doubles.
The false coarse pattern that fine detail turns into is called moiré. You have seen it on television: a presenter’s finely striped shirt shimmers with broad patterns that the shirt does not have.
Skip pixels, and false rings appear
A 256 × 256 zone plate: rings whose frequency grows from 0 at the centre to half a cycle per pixel at the edges.
All 256 × 256 pixels: one centre, rings closing in toward the edges, contrast 0.354 everywhere.
Describe this picture
A 256 × 256 zone plate: rings whose frequency grows from 0 at the centre to half a cycle per pixel at the edges. One square panel with the image in grey levels, each pixel drawn as a square of whole screen pixels, so the screen adds no aliasing of its own. After skipping, each kept pixel is drawn as an square, so the panel keeps its size. A dashed square, labelled “alias limit”, sits pixels from the centre. The readouts are , the aliased area in percent of the kept pixels, and the ring contrast outside the limit, the RMS of the brightness about 0.5. The 13 s clip opens on all 256 × 256 pixels: one centre, rings closing in toward the edges, contrast 0.354 everywhere, nothing aliased. At 3.5 s it cross-fades to every 2nd pixel: inside the dashed square the rings are right; outside, false rings grow round the edges’ midpoints and the corners, over 74.21 % of the kept pixels, at 0.353. At 8 s it cross-fades to every 4th pixel: a grid of false centres, with 92.94 % of the kept pixels aliased at full contrast, 0.353. When the clip ends, two full-width buttons in a group named “Before skipping”, “skip only” and “blur first”, choose whether to average each block first; the choice is kept in the link, as moire.blur. With blur first at every 4th pixel, the false rings fade to 0.056 and the true rings keep 0.278.
Watch the corners and the middle of each edge as fewer pixels are kept: false rings grow there, outside the dashed square.
I measure the rings’ contrast as the RMS of the brightness about 0.5, the RMS of How big is a signal (1.3), “Four everyday sizes”. For a cosine of height 0.5 it is .
Notice the end frame: with every 4th pixel kept, 92.94 % of the kept pixels lie where the rings alias. The false rings there are as strong as the true ones, 0.353 against the 0.354 of the whole zone plate.
Why 92.94 % and not the 93.75 % of the area outside the square? The kept pixels on the dashed square itself count as inside: 17 of the 64 kept columns lie within 32 pixels of the centre. For it is 65 of 128, which gives 74.21 % against 75 %.
Where the false centres come from
Take the middle of the left edge, . There the rings have half a cycle per original pixel. Keep every 2nd pixel and that becomes 1 cycle per kept pixel, which gives the same samples as 0 cycles, by 10.1’s rule.
Zero frequency is what the true centre has. So a false centre appears at the middle of each edge, and at each corner, where both parts are half a cycle. The kept picture repeats every 64 kept pixels, so each false centre is a copy of the true one.
With every 4th pixel, the frequency per kept pixel is a whole number at every multiple of 64 pixels from the centre: . That puts false centres on a grid, 64 pixels apart, as in the end frame.
Blur first
When the clip ends, press “blur first” under the zone plate. It averages each block of pixels before keeping one value per block. I call this area averaging: each kept value is the mean brightness over the area its block covers.
The block average is the -point moving average of Frequency response of discrete-time systems (12.4), “A moving average, probed”, run across and then down. So area averaging is 22.1’s “Filter first, then keep every M-th”, with a simple filter. With in cycles per pixel, its gain in each direction is
The gain is 0 at , and so on, the frequencies that land on false centres. At the middle of the left edge, where the false centre sat, area averaging leaves plain grey: 0.500 at , 0.501 at .
Outside the dashed square the false rings fade from 0.353 to 0.117 at , and to 0.056 at . Each block’s average is placed at its block’s middle when I sort it inside or outside the square.
The price is that the true rings fade as well. Inside the square they keep 0.289 at and 0.278 at , down from 0.354. At the limit, , the gain in each direction is 0.707 for and 0.653 for .
So a block average is a rough low-pass filter: it fades what would alias, and some of what would not. The decimation filters of 22.1 were designed to cut more sharply, and Image filtering (28.2) builds blurs of other shapes.
Jaggies
A sharp edge in a picture is the square wave of 10.1’s “A square wave aliases at any note”. The brightness jumps from 0 to 1, and a jump holds frequencies that never end. However many pixels you have, some of those frequencies lie past half a cycle per pixel.
On a tilted edge, that aliasing shows as a staircase. The steps are called jaggies. Area averaging softens them: an edge pixel gets the fraction of its area that the shape covers, a grey between 0 and 1.
The maths behind it · matrix rank
An image is a matrix, with one row of the matrix per row of pixels. An upright grating has every row the same: it is a column of ones times one row, a matrix of rank 1. A tilted one splits as , a sum of two such products, so it has rank 2 unless or is ½.
Worked example
1. Spacing from frequency. Take . Its size is , so the stripes are pixels apart. The direction is the angle whose tangent is , which is 53.1°.
In radians per pixel, and , and gives the same 20 pixels. Along one row the stripes cross every pixels, farther apart than 20, as in the turned frame of the first instrument.
2. The alias limit. Keep every 2nd pixel of the zone plate. The limit is cycle per original pixel. The rings reach that where , which is pixels from the centre, where the dashed square sits.
3. A grating that turns. Take and keep every 4th pixel. The limit is , so is fine and is past it. On the kept pixels the frequencies are multiplied by 4, to , and gives the same samples as .
So the kept pixels show the grating . Its stripes are kept pixels apart, which is 8.94 original pixels, twice the true 4.47. Its direction is −26.6° instead of 63.4°. The false stripes are coarser, and they have turned through a right angle.
Where you’ll meet this
Every image resizer and thumbnail maker meets this problem. Keeping every -th pixel is fast but makes moiré. OpenCV’s area resampling, INTER_AREA, averages each block, and its documentation suggests it for shrinking images, as it gives results free of moiré.
Many cameras put a thin optical low-pass filter in front of the sensor. It blurs the light slightly before the pixels sample it, the job of the anti-alias filter of Anti-aliasing and practical converters (10.4). Some cameras leave it out for sharper pictures, and then fine fabrics can show moiré.
Fonts on screens are drawn with grey edge pixels, each as dark as the share of it that the letter covers, as in the figure; this is called anti-aliasing. Scanners meet moiré when they scan printed pictures, which are made of fine dots, and many offer a “descreen” setting that blurs first.
The page Image filtering (28.2) slides small grids of numbers over an image, which is how blurs are made. The 2-D DFT (28.3) computes the frequency plane of any image, not only of a grating. For more, see Gonzalez and Woods, Digital Image Processing (4th ed., 2018), chapters 2 and 4, and J. S. Lim, Two-Dimensional Signal and Image Processing (1990), chapter 1.
The maths behind it · power spectra of photographs
Photographs of natural scenes have most of their power at low spatial frequencies. Their power falls roughly as with the distance from the centre of the frequency plane, like the brown noise of Power spectral density (24.4). For such a spectrum on 256 × 256 pixels, about 13 % of the power lies beyond the limit of every 2nd pixel; for the zone plate it is three quarters. That is why shrinking a photograph aliases less than shrinking a zone plate.
Reference card
| Quantity | Formula | Notes |
|---|---|---|
| Image | column across, row down | |
| Grating | , | |
| Spacing | pixels | or ; stripes at right angles to |
| Spectrum | dots at and | the two arrows of a cosine |
| Limit | each part below ½ cycle ( rad) per pixel | a square, not a circle |
| Zone plate | near offset : cycles per pixel | every frequency once |
| Keep every M-th | limit cycle per original pixel | aliases beyond pixels here |
| Area average | gain each way | blur first; 0 at |