- image-processing
- Color spaces
- Images
- Creating images
- Basic image information
- Logical and morphological operations
- PNM movies
- Image operations
- Image pairs
- Thresholding
- Colour Threshold
- Histogram Equalization
- Adaptive Thresholding
- Histogram
- Rendering Line Segments
- Points and bounding boxes
- Quantization
- Ellipses
- Resizing
- Connected Components
- Chains
- Conjuring
- Distance Transform
- Buffers
- Misc
- Stacking
- Angles
- Display
- License

## image-processing

This page is maintained in the package's github repository.

This is a Chicken Scheme egg with various image processing utilities.

Note that a few of these functions call ImageMagick.

### Color spaces

*[constant]*

`*max-red*`

*[constant]*

`*max-green*`

*[constant]*

`*max-blue*`

*[constant]*

`*max-grey*`

*[constant]*

`*max-hue*`

*[constant]*

`*max-saturation*`

*[constant]*

`*max-value*`

These are exposed in case we want to switch to 16-bit grayscale or colors.

*[procedure]*

`(rgb->hsv rgb)`

*[procedure]*

`(hsv->rgb hsv)`

*[procedure]*

`(rgb->cd rgb)`

*[procedure]*

`(rgb->cmyk rgb)`

*[procedure]*

`(rgb->uv-hsv c)`

Various color space conversions. Colors are vectors of values.

*[procedure]*

`(rgb->xyz c)`

*[procedure]*

`(xyz->rgb c)`

*[procedure]*

`(xyz->l*ab c)`

*[procedure]*

`(l*ab->xyz c)`

*[procedure]*

`(rgb->l*ab c)`

*[procedure]*

`(l*ab->rgb c)`

Convert to l*ab. Colors are vectors of values. This is space in which Euclidean distance is similar to human perceputal distance. These implement a 2 degree observer and the D65 illuminant.

*[procedure]*

`(rgb->html c)`

Not really a color space conversion, covert an rgb color to an HTML color *#rrggbb*.

### Images

*[record]*

`(define-structure pbm raw? bitmap)`

*[record]*

`(define-structure pgm raw? maxval grey)`

*[record]*

`(define-structure ppm raw? maxval red green blue)`

*[procedure]*

`(pnm? m)`

Three image formats are supported. PBMs are binary images, PGMs are greyscale and PPMs are tri-plane (nominally RGB) images. All planes are stored as scheme matrices. Together all of these formats are called PNM. This is a standard format that many tools (such browser and ImageMagick) can read and write. PNMs can be serialized as either raw packed binaries or ascii text files. Note that we are unable to read or write raw PBMs.

*[procedure]*

`(image-ref i p)`

Index into an PNM image or into a matrix. This is like indexing into a matrix except that the arguments are reversed. A *matrix-ref* takes the row and then the column, image-ref takes a point which is an (x,y) coordinate.

*[procedure]*

`(pbm-ascii pbm)`

Ensure that the PBM image is in ascii. We are unable to read or write raw PBMs.

*[procedure]*

`(pnm-copy pnm)`

The resulting image will not share any data with the original.

### Creating images

*[procedure]*

`(read-pnm pathname)`

Read a PNM. We determine the kind of image (PBM, PGM, PPM see above) from the file header.

*[procedure]*

`(write-pnm pnm pathname)`

Write a PNM. If don't provide an extension an appropriate one will be appended to your pathname.

*[procedure]*

`(pbm-constant width height bit)`

*[procedure]*

`(pgm-constant width height grey)`

*[procedure]*

`(ppm-constant width height red green blue)`

Create constant images.

*[procedure]*

`(pbm-left-vertical-stripe width height left)`

Create a black vertical stripe on a white image.

*[procedure]*

`(crop-image pnm x y width height)`

Crop an image and return a new image of the given size.

*[procedure]*

`(pnm->ppm pnm)`

*[procedure]*

`(pnm->pgm pnm)`

Convert any image format to a color or greyscale image

*[procedure]*

`(pbm->pgm pbm)`

*[procedure]*

`(pgm->ppm pgm)`

*[procedure]*

`(pbm->ppm pbm)`

*[procedure]*

`(ppm->pgm ppm)`

Various image conversions.

*[procedure]*

`(pgm->pbm pgm threshold)`

*[procedure]*

`(ppm->pbm ppm threshold)`

Convert a color or greyscale image to a binary image with the provided threshold.

### Basic image information

*[procedure]*

`(pnm-width pnm)`

*[procedure]*

`(pnm-height pnm)`

Basic image information.

*[procedure]*

`(ppm-hue ppm)`

*[procedure]*

`(ppm-saturation ppm)`

*[procedure]*

`(ppm-value ppm)`

Creates a greyscale image representing one of the HSV channels from a color image.

*[procedure]*

`(ppm-mean image colour-transform)`

*[procedure]*

`(ppm-covariance image colour-transform)`

*[procedure]*

`(pgm-mean image)`

*[procedure]*

`(pgm-variance image)`

Compute the mean or covariance of an image. These take an optional colour transform.

### Logical and morphological operations

*[procedure]*

`(pbm-and pbm1 pbm2)`

*[procedure]*

`(pbm-or pbm1 pbm2)`

*[procedure]*

`(pbm-not pbm)`

*[procedure]*

`(pbm-xor pbm1 pbm2)`

Basic logical operations on binary images.

*[procedure]*

`(pgm-absolute-difference pgm1 pgm2)`

Compute the difference between two greyscale images.

*[procedure]*

`(empty-pnm? pnm)`

Is this image empty?

*[procedure]*

`(pbm-skeletonize pbm)`

*[procedure]*

`(pbm-bloat pbm n)`

Bloat or skeletonize a binary image.

*[procedure]*

`(pbm-flood pbm point)`

Floor fill a binary image.

### PNM movies

*[procedure]*

`(pnm-movie-frame-pathname pathname i)`

*[procedure]*

`(pnm-movie-length pathname)`

*[procedure]*

`(read-pnm-movie pathname)`

*[procedure]*

`(write-pnm-movie pnm-movie pathname)`

A PNM movie is a sequence of PNMs on disk.

### Image operations

*[procedure]*

`(overlay-pbm-on-pnm pbm pnm)`

The white pixels in the pbm become white in the resulting image.

*[procedure]*

`(pnm-black-window pnm upper-left lower-right)`

*[procedure]*

`(pnm-white-window pnm upper-left lower-right)`

Draw white or black windows on an image.

*[procedure]*

`(pbm-ppm-and pbm ppm)`

*[procedure]*

`(pgm-and-pbm pgm pbm)`

Black pixels in the PBM become black pixels in the result.

*[procedure]*

`(pnm-shift pnm delta)`

Shift an image down and rightward by the give number of pixels.

*[procedure]*

`(pgm-smooth pgm sigma)`

Smooth a greyscale image with the given variance.

*[procedure]*

`(pbm-proximity-clusterer pbm threshold)`

Cluster white pixels in the binary image with the given distance threshold.

*[procedure]*

`(pnm-rotate pnm)`

*[procedure]*

`(pnm-flip pnm)`

Rotate (transpose) an image or flip (mirror) an image.

*[procedure]*

`(ppm-burn base mask colour)`

Burn the ppm with the given mask and color.

### Image pairs

*[procedure]*

`(normal-flow-magnitude pgm1 pgm2 epsilon sigma sensitivity)`

*[procedure]*

`(threshold-normal-flow-magnitude pgm1 pgm2 epsilon sigma threshold)`

Compute normalized flow between two pairs of greyscale images.

### Thresholding

*[procedure]*

`(flatten-ppm ppm colour-transform)`

Returns a single matrix from a tri-plane PPM. This maps colour-transform over the image.

*[procedure]*

`(binary-threshold pgm threshold)`

Threshold a greyscale image.

*[procedure]*

`(find-threshold-otsu pgm)`

*[procedure]*

`(binary-threshold-optimal pgm)`

Otsu's Method to find an optional threshold and apply it.

*[procedure]*

`(find-threshold-means pgm)`

*[procedure]*

`(binary-threshold-means pgm)`

Method of Successive Means to find an optimal threshold and apply it.

### Colour Threshold

*[procedure]*

`(sample-image ppm colour-tx window-centre window-size)`

Map colour-tx over an region of a color image.

*[procedure]*

`(binary-threshold-colour ppm colour-tx point threshold)`

Binary threshold a colour image by sampling a region around the given point and thresholding all values that are within the given distance threshold of the mean color of that region.

*[procedure]*

`(colour-threshold ppm colour-tx mu isigma threshold)`

Binary threshold a colour image with the given mean and variance. The mahalanobis-distance between each pixel and the given mean and variance will be computed and compared to the threshold.

### Histogram Equalization

*[procedure]*

`(histogram-equalise pgm)`

Equalize a greyscale image.

### Adaptive Thresholding

*[procedure]*

`(make-integral-matrix matrix)`

Given a matrix compute an integral matrix which can provide the mean value of a rectangular region in O(1).

*[procedure]*

`(compute-integral-matrix-mu integral-matrix x y w)`

*[procedure]*

`(compute-integral-matrix-sigma squared-integral-matrix mu x y w)`

This computes the mean and variance of a square of size w in the given integral matrix.

*[procedure]*

`(compute-adaptive-threshold integral-matrix squared-integral-matrix x y w)`

Compute an adaptive threshold on the given integral matrix.

*[procedure]*

`(adaptive-threshold pgm winsize)`

Compute an adaptive threshold for a greyscale image with a given window size.

*[procedure]*

`(slide-window m f size)`

Map f over a matrix passing it square submatrices of the given size. At the edges f is passed *#f*.

*[procedure]*

`(count-pixels a)`

Count number of true values in a matrix.

*[procedure]*

`(ppm->label-closest ppm mu1 sigma1 mu2 sigma2 #!optional colour-transform)`

Create a binary image from a color image where points are either white or black depending on which is closer to the given means and variances.

### Histogram

*[procedure]*

`(find-histogram pixmap maxval)`

*[procedure]*

`(histogram-mean histogram i)`

*[procedure]*

`(histogram-variance histogram mu i)`

*[procedure]*

`(normalised-histogram histogram val)`

*[procedure]*

`(weighted-histogram histogram)`

*[procedure]*

`(cumulative-histogram histogram)`

*[procedure]*

`(find-between-class-variances omegas mus mu-total)`

Compute histograms from a matrix.

### Rendering Line Segments

*[procedure]*

`(midpoint l)`

Compute the midpoint of a line segment.

*[procedure]*

`(orientation v)`

Compute the orientation of a vector.

*[procedure]*

`(line-segment-orientation l)`

Compute the orientation of a line segment.

*[procedure]*

`(line-segment->points l)`

*[procedure]*

`(line-segments->points ls)`

*[procedure]*

`(points->line-segments ps)`

Convert between points and line semgents.

### Points and bounding boxes

*[procedure]*

`(points->pbm-of-size points height width)`

Take the list of points and create a binay image of the given size where those points are white.

*[procedure]*

`(points-bounding-box points)`

Computing a bounding box for a set of points.

*[procedure]*

`(bounding-box-size bb)`

Compute the size of a bounding box

*[procedure]*

`(points->points-bounding-box points bb)`

Recompute the coordinates of the given points relative to the top-left corner of the bounding box.

*[procedure]*

`(points->bounding-box-points points)`

Convert points to a list of points on the bounding box of those points.

*[procedure]*

`(normalize-to-bounding-box ps)`

*[procedure]*

`(normalize-to-other-bounding-box points ps)`

*[procedure]*

`(points->target-bounding-box points target-bb)`

*[procedure]*

`(points->other-target-bounding-box points ps target-bb)`

Normalize the cooredinates of these points to their bounding box. Or to the bounding box of the given points.

*[procedure]*

`(bounding-box-bloat bb p)`

Bloat a bounding box.

*[procedure]*

`(bounding-box-crop bb image)`

Crop a bounding box out of an image.

*[procedure]*

`(pbm->points pbm)`

*[procedure]*

`(points->pbm points height width)`

Convert a binary image to a set of points or vice versa.

### Quantization

*[procedure]*

`(quantize-coordinate x)`

*[procedure]*

`(quantize-point p)`

*[procedure]*

`(quantize-points ps)`

*[procedure]*

`(quantize-line-segment l)`

*[procedure]*

`(quantize-line-segments ls)`

Quantize coordinates, points or line segments.

### Ellipses

*[procedure]*

`(define-structure ellipse x0 y0 t0 a b)`

*[procedure]*

`(ellipse-center ellipse)`

*[procedure]*

`(ellipse-area ellipse)`

*[procedure]*

`(ellipse-eccentricity ellipse)`

Define and compute basic properties of ellipses.

*[procedure]*

`(radial-distance theta phi)`

The radial distance between two angles.

*[procedure]*

`(point-on-ellipse? p ellipse tolerance)`

Compute if a point is on an ellipse.

*[procedure]*

`(line-segment->ellipse l)`

Place an ellipse around a line segment

*[procedure]*

`(ellipse->points e #!optional (n 360))`

Sample *n* points on an ellipse.

### Resizing

*[procedure]*

`(resize-image w h i)`

Resize an image. This is quite slow as it writes the image out and calls imagemagick to resize it.

*[procedure]*

`(subsample-pbm pbm)`

Subsample a pbm by a factor of 2.

*[procedure]*

`(scale-ppm ppm scale)`

Scale a pbm by a factor of 2 or 4.

### Connected Components

*[procedure]*

`(connected-component-filter pbm delta threshold)`

Compute connected components of a binary image with distance thershold *delta* and size threshold *threshold*.x

*[record]*

`(define-private-structure vertex pixels vertex edges)`

*[record]*

`(define-private-structure edge u v)`

*[record]*

`(define-private-structure graph vertices edges)`

These are defined private for now as they need to be renamed.

*[procedure]*

`(pbm->graph pbm delta)`

*[procedure]*

`(labeling->graph labeling delta)`

Convert a binary image to a graph where pixels within *delta* of each other are connected.

*[procedure]*

`(dereference-vertex u)`

*[procedure]*

`(connected-components g)`

Compute the connect components of a graph.

*[procedure]*

`(vertices->pbm vertices height width)`

*[procedure]*

`(graph->pbm g height width)`

Convert a graph or list of vertices to a pbm.

### Chains

*[procedure]*

`(pbm->chains pbm)`

Convert a binary image to a list of chains, pixels that are connected to each other.

*[procedure]*

`(chains->pbm chains height width)`

Convert a list of chains to a pbm.

*[procedure]*

`(chain-filter pbm threshold)`

Filters chains below a certain length.

*[procedure]*

`(break-chain chain l)`

*[procedure]*

`(break-chains chains l)`

Break chains below a certain length.

### Conjuring

*[procedure]*

`(conjure pbms delta span threshold1 threshold2)`

Fill in missing values in pairs of frames.

### Distance Transform

*[procedure]*

`(distance-transform pbm)`

*[procedure]*

`(closest-transform-ref closest-transform p)`

Compute the Manhattan distance transform for a binary image and reference into that distance transform.

*[procedure]*

`(euclidean-1d-dt v)`

*[procedure]*

`(euclidean-2d-dt m)`

*[procedure]*

`(euclidean-1d-dt-vals v)`

*[procedure]*

`(euclidean-2d-dt-vals m)`

Compute a generalized squared-euclidean distance transform on the given vector or matrix. The *-vals* version also returns a map of the closest points.

### Buffers

*[record]*

`(define-structure pnm-buffer buffer width height pixfmt storage type)`

A mechanism to store raw image pointers.

*[procedure]*

`(pnm->pixfmt p p4?)`

*[procedure]*

`(pixfmt->stride pixfmt)`

*[procedure]*

`(image-type->pixfmt t p4?)`

*[procedure]*

`(image-type->storage-size t p4?)`

*[procedure]*

`(pnm->image-type p)`

*[procedure]*

`(pnm->storage p)`

*[procedure]*

`(pixfmt->red pixfmt)`

*[procedure]*

`(pixfmt->green pixfmt)`

*[procedure]*

`(pixfmt->blue pixfmt)`

*[procedure]*

`(pnm-buffer-size p p4?)`

*[procedure]*

`(pnm->pnm-buffer! p . p4?)`

*[procedure]*

`(pnm-fill-buffer! p b pixfmt)`

*[procedure]*

`(free-pnm-buffer! p)`

Misc raw image buffer operations.

*[procedure]*

`(imlib-image->pnm-buffer! image)`

*[procedure]*

`(imlib-image->ppm image)`

*[procedure]*

`(ppm->imlib-image ppm)`

Convert between PPMs and Imlib images. PGMs and PBMs must first be converted to PPMs because Imlib only handles RGB images.

*[procedure]*

`(pnm-buffer->pnm b)`

*[procedure]*

`(pnm-buffer->pbm p)`

*[procedure]*

`(pnm-buffer->pgm p)`

*[procedure]*

`(pnm-buffer->ppm p)`

Convert a raw image buffer to a scheme image.

*[procedure]*

`(image->pnm-buffer! image)`

Convert any image to a raw image buffer.

### Misc

*[procedure]*

`(ppm-absolute-difference ppm1 ppm2)`

Compute the absolute difference between two color images.

*[procedure]*

`(set-ppm-pixel! ppm x y value)`

Set a pixel in a color image to a given value (a 3-vector).

*[procedure]*

`(pnm-pixel? i x y)`

Is this a valid position in the given image?

*[procedure]*

`(map-ppm-values ppm f)`

Map *f* on each component of each pixel in the image.

### Stacking

*[procedure]*

`(pbm-stack-vertical pbm1 pbm2)`

*[procedure]*

`(pbm-stack-horizontal pbm1 pbm2)`

*[procedure]*

`(ppm-stack-vertical ppm1 ppm2)`

Stack pbms.

*[procedure]*

`(ppm-stack-horizontal ppm1 ppm2)`

Stack ppms.

### Angles

*[procedure]*

`(degrees->radians angle)`

*[procedure]*

`(radians->degrees angle)`

*[procedure]*

`(normalize-rotation rotation)`

*[procedure]*

`(rotation+ x y)`

*[procedure]*

`(rotation- x y)`

*[procedure]*

`(angle-separation x y)`

*[procedure]*

`(mean-angle angles)`

Misc operation on angles.

*[procedure]*

`(rotation-matrix-2d theta)`

Produce the 2D rotation matrix for the given angle.

### Display

*[procedure]*

`(show i)`

Display an image. This invokes feh.

### License

Written by the [[Center for the Computational Study of Cognition, Control, and Perception|http://upplysingaoflun.ecn.purdue.edu/~qobi/cccp/]].

Maintainer: Andrei Barbu, andrei@0xab.com

Copyright 1993-1995 University of Toronto. All rights reserved. Copyright 1996 Technion. All rights reserved. Copyright 1996 and 1997 University of Vermont. All rights reserved. Copyright 1997-2001 NEC Research Institute, Inc. All rights reserved. Copyright 2002-2013 Purdue University. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses.