(x,y) Δ” x Δ” x 2 + Δ” y 2 {%DELTA x} over sqrt {{%DELTA x^2} + {%DELTA y^2}} Δ” y Δ” x 2 + Δ” y 2 {%DELTA y} over sqrt {{%DELTA x^2} + {%DELTA y^2}}

Figure 1. Left panel: A small image with a blurry streak. Middle, the field of normalized x components taken from the gradient of the image on the left. Sharp black-to-white and white-to-black transitions pin-point where signs change at local maximum or minimum points. Right panel: the y components; the signal is here as well, but not as strong.

The gradient_orientation command computes normalized rates of intensity change across image width, height or depth axes, as chosen by the 'dimension' argument.

The command returns one image for each selected axis. Each depicts a field of normalized components of intensity change along one of the axial directions. These normalized components, taken in aggregate, form unit length vectors that show the direction, or orientation, of the gradient at each pixel of the given selected image. It is common to follow this command with -append c, producing an orientation field, to wit: a vector field depicting the normalized gradient of the selected image.

The format of the command is:

gradient_orientation dimension={1,2,3}

  1. dimension: Picks a combination of axes along which the command operates:
    1. "1" width only,
    2. "2" width and height,
    3. "3" width, height and depth.

Upon completion, this command places on the stack up to three images, each a field of normalized vector components reflecting, at the pixel locality, the relative instensity of the gradient along one of the cardinal axes.

The particular formulation of each vector component depends on the dimension argument. That argument chooses the components that make up the unit vector and establishes if the user is interested in one dimensional gradients along a line, two dimensional gradients on a surface or three dimensional gradients in a space. Once a dimension has been specified, then at each pixel the command determines the intensity change in each principal direction, the length of the vector formed by these components and the relative length of these components with respect to that vector. The command returns vector component fields, one for each axis. The following table summarizes these calculations:

dimension → 1 2 3
image 1 Δ” x | Δ” x | {%DELTA x} over lline %DELTA x rline Δ” x Δ” x 2 + Δ” y 2 {%DELTA x} over sqrt {{%DELTA x^2} + {%DELTA y^2}} Δ x Δ x 2 + Δ y 2 + Δ z 2 {%DELTA x} over sqrt {{%DELTA x^2} + {%DELTA y^2} + {%DELTA z^2}}
image 2 Δ” y Δ” x 2 + Δ” y 2 {%DELTA y} over sqrt {{%DELTA x^2} + {%DELTA y^2}} Δ y Δ x 2 + Δ y 2 + Δ z 2 {%DELTA y} over sqrt {{%DELTA x^2} + {%DELTA y^2} + {%DELTA z^2}}
image 3 Δ z Δ x 2 + Δ y 2 + Δ z 2 {%DELTA z} over sqrt {{%DELTA x^2} + {%DELTA y^2} + {%DELTA z^2}}

The command works with multispectral images and performs its computations independently on each channel, returning to the stack a set of images with a like number of channels.


-gradient_orientation is closely related to -gradient in that it finds datasets which reflect rates of intensity change in each cardinal direction over a field of pixels. It differs in that it scales these component by the length of the vector they form, a normalizaton. Thus, the data always range over the interval [ -1,…, 1 ] and vectors formed from these scaled components are of unit length.

Such vectors express how a gradient is oriented. Magnitude is not material as these vectors have lengths of one. In contrast, -gradient does not perform any normalization. Vectors formed from its components reflect both the intensity and direction of the gradient at a particular pixel.

Because -gradient's unnormalized vectors truly reflect the scale and direction of gradients, they are not particularly apt for certain kinds of feature analysis or extraction. The normalization of vectors by their length, as done by -gradient_orientation, distort the shape of the gradient in such a way as to make changes in trends around local maxima or minima very clear to see. Near local maxima or minima, at least one unnormalized vector component gradually vanishes, shrinking the gradient vector and obscuring the transition. With gradient_orientation, the reciprocal of gradient vector length scales the same vector component. The denominator is trending to zero as well as nominator, which sustains the unit length of the normalized vector. Consequently the normalized vector will abruptly "pop" to a new orientation at the crests or nadirs of local maxima or minima, where at least one component changes sign. These transitions form sharp boundaries in the images that gradient_orientation produces.

This walkthrough illustrates the effect:

A murky Goudy 1911 Bookletter Ampersand slowly sinking into darkness. The green line marks scan line 160, which we graph at the end of the walkthrough.
The gradient x component field, produced by executing -gradient x on the image in the previous panel.

These data reflect the intensity changes along the width of the image. In keeping with -gradient's remit, we know how much the intensity of the previous image is changing horizontally by the grayscale level: not at all in the gray areas, trending positive in the white areas, trending negative in the dark areas.

The red line demarks scanline 160 of this image.
The normalized gradient x component produced by -gradient_orientation 2.

The normalization which this command does essentially throws information away. Gradient vectors normalized to unit length no longer tell us "how much". For some purposes, however, that is not a terrible loss. In this case, the omission of "how much" makes the orientation of the vector that much clearer. This image only shows the horizontal component of the unit vector. Here, gray means "not much either way in the horizontal orientation." Lighter means "trending to the right!" Darker means "trending to the left!"

Because "how much" has been thrown out by the process of normalizing the gradient vector to unit length, changing trends along the horizontal orientation become manifestly clear. The sharp transitions in the image on the left coincide with those regions in the original image where the intensity is no longer growing lighter, but is now becoming darker. Finding that precise region in the original image is hard, as the original data are barely changing at all. It is somewhat clearer in the image that -gradient produces. Where the x component has been normalized, however, the trend change is manifestly obvious.

The blue line demarks scan line 160, which we chart in the next panel.
The graph of intensities along scanline 160 from the original image (green), the x component of the gradient (red) and the normalized x component produced by gradient_orientation (blue), normalized for comparison. Note the response of the gradient_orientation x component around image maxima and minima. It tends to remain at the limits of its range until a change of the sign of the tangent at peaks and troughs occurs, when it transits to the other limit of its range. The behavior of the gradient is similar, but less pronounced, and can be quite obscure.

Gradients in Data Series

When the command is given an argument of one, it simply computes normalized gradient changes along the x axis:

Δ” x | Δ” x | {%DELTA x} over lline %DELTA x rline

This is suitable for a one dimensional data sequence, typically placed in an image with depth = height = 1, In this setting, -gradient_orientation returns a sequence of +1, -1, 0 signals, with negative one indicating that the local gradient in the vicinity of the corresponding input pixel is trending negative; positive one indicates the gradient is trending positive; zero indicates the gradient is not changing at all. The analog quality that may have been present in the original image has been replaced by a tri-value digital signal.

Garry Osgood