@c Copyright (C) 1996-2022 The Octave Project Developers
@c
@c This file is part of Octave.
@c
@c Octave is free software: you can redistribute it and/or modify it
@c under the terms of the GNU General Public License as published by
@c the Free Software Foundation, either version 3 of the License, or
@c (at your option) any later version.
@c
@c Octave is distributed in the hope that it will be useful, but
@c WITHOUT ANY WARRANTY; without even the implied warranty of
@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@c GNU General Public License for more details.
@c
@c You should have received a copy of the GNU General Public License
@c along with Octave; see the file COPYING.  If not, see
@c <https://www.gnu.org/licenses/>.

@node Image Processing
@chapter Image Processing

Since an image is basically a matrix, Octave is a very powerful
environment for processing and analyzing images.  To illustrate
how easy it is to do image processing in Octave, the following
example will load an image, smooth it by a 5-by-5 averaging filter,
and compute the gradient of the smoothed image.

@example
@group
I = imread ("myimage.jpg");
S = conv2 (I, ones (5, 5) / 25, "same");
[Dx, Dy] = gradient (S);
@end group
@end example

@noindent
In this example @code{S} contains the smoothed image, and @code{Dx}
and @code{Dy} contains the partial spatial derivatives of the image.

@menu
* Loading and Saving Images::
* Displaying Images::
* Representing Images::
* Plotting on top of Images::
* Color Conversion::
@end menu

@node Loading and Saving Images
@section Loading and Saving Images

The first step in most image processing tasks is to load an image
into Octave which is done with the @code{imread} function.
The @code{imwrite} function is the corresponding function
for writing images to the disk.

In summary, most image processing code will follow the structure of this code

@example
@group
I = imread ("my_input_image.img");
J = process_my_image (I);
imwrite (J, "my_output_image.img");
@end group
@end example

@DOCSTRING(imread)

@DOCSTRING(imwrite)

@DOCSTRING(IMAGE_PATH)

It is possible to get information about an image file on disk, without actually
reading it into Octave.  This is done using the @code{imfinfo} function which
provides read access to many of the parameters stored in the header of the
image file.

@DOCSTRING(imfinfo)

By default, Octave's image IO functions (@code{imread}, @code{imwrite},
and @code{imfinfo}) use the @code{GraphicsMagick} library for their
operations.  This means a vast number of image formats is supported
but considering the large amount of image formats in science and
its commonly closed nature, it is impossible to have a library
capable of reading them all.  Because of this, the function
@code{imformats} keeps a configurable list of available formats,
their extensions, and what functions should the image IO functions
use.  This allows one to expand Octave's image IO capabilities by
creating functions aimed at acting on specific file formats.

While it would be possible to call the extra functions directly,
properly configuring Octave with @code{imformats} allows one to keep a
consistent code that is abstracted from file formats.

It is important to note that a file format is not actually defined by its
file extension and that @code{GraphicsMagick} is capable to read and write
more file formats than the ones listed by @code{imformats}.  What this
means is that even with an incorrect or missing extension the image may
still be read correctly, and that even unlisted formats are not necessarily
unsupported.

@DOCSTRING(imformats)

@node Displaying Images
@section Displaying Images

A natural part of image processing is visualization of an image.
The most basic function for this is the @code{imshow} function that
shows the image given in the first input argument.

@DOCSTRING(imshow)

@DOCSTRING(image)

@DOCSTRING(imagesc)

@node Representing Images
@section Representing Images

In general Octave supports four different kinds of images, grayscale
images, RGB images, binary images, and indexed images.  A grayscale
image is represented with an M-by-N matrix in which each
element corresponds to the intensity of a pixel.  An RGB image is
represented with an M-by-N-by-3 array where each
3-vector corresponds to the red, green, and blue intensities of each
pixel.

The actual meaning of the value of a pixel in a grayscale or RGB
image depends on the class of the matrix.  If the matrix is of class
@code{double} pixel intensities are between 0 and 1, if it is of class
@code{uint8} intensities are between 0 and 255, and if it is of class
@code{uint16} intensities are between 0 and 65535.

A binary image is an M-by-N matrix of class @code{logical}.
A pixel in a binary image is black if it is @code{false} and white
if it is @code{true}.

An indexed image consists of an M-by-N matrix of integers
and a C-by-3 color map.  Each integer corresponds to an
index in the color map, and each row in the color map corresponds to
an RGB color.  The color map must be of class @code{double} with values
between 0 and 1.

The following convenience functions are available for conversion between image
formats.

@DOCSTRING(im2double)

@DOCSTRING(gray2ind)

@DOCSTRING(ind2gray)

@DOCSTRING(rgb2ind)

@DOCSTRING(ind2rgb)

Octave also provides tools to produce and work with movie frame structures.
Those structures encapsulate the image data (@qcode{"cdata"} field) together
with the corresponding colormap (@qcode{"colormap"} field).

@DOCSTRING(getframe)

@DOCSTRING(movie)

@DOCSTRING(frame2im)

@DOCSTRING(im2frame)

The @code{colormap} function is used to change the colormap of the current
axes or figure.

@DOCSTRING(colormap)

@DOCSTRING(iscolormap)

The following functions return predefined colormaps, the same that can be
requested by name using the @code{colormap} function.

@DOCSTRING(rgbplot)

@DOCSTRING(autumn)

@DOCSTRING(bone)

@DOCSTRING(colorcube)

@DOCSTRING(cool)

@DOCSTRING(copper)

@DOCSTRING(cubehelix)

@DOCSTRING(flag)

@DOCSTRING(gray)

@DOCSTRING(hot)

@DOCSTRING(hsv)

@DOCSTRING(jet)

@DOCSTRING(lines)

@DOCSTRING(ocean)

@DOCSTRING(pink)

@DOCSTRING(prism)

@DOCSTRING(rainbow)

@DOCSTRING(spring)

@DOCSTRING(summer)

@DOCSTRING(turbo)

@DOCSTRING(viridis)

@DOCSTRING(white)

@DOCSTRING(winter)

@DOCSTRING(contrast)

The following three functions modify the existing colormap rather than
replace it.

@DOCSTRING(brighten)

@DOCSTRING(spinmap)

@DOCSTRING(whitebg)

The following functions can be used to manipulate colormaps.

@DOCSTRING(cmunique)

@DOCSTRING(cmpermute)

@node Plotting on top of Images
@section Plotting on top of Images

If gnuplot is being used to display images it is possible to plot on
top of images.  Since an image is a matrix it is indexed by row and
column values.  The plotting system is, however, based on the
traditional @math{(x, y)} system.  To minimize the difference between
the two systems Octave places the origin of the coordinate system in
the point corresponding to the pixel at @math{(1, 1)}.  So, to plot
points given by row and column values on top of an image, one should
simply call @code{plot} with the column values as the first argument
and the row values as the second.  As an example the following code
generates an image with random intensities between 0 and 1, and shows
the image with red circles over pixels with an intensity above
@math{0.99}.

@example
@group
I = rand (100, 100);
[row, col] = find (I > 0.99);
hold ("on");
imshow (I);
plot (col, row, "ro");
hold ("off");
@end group
@end example

@node Color Conversion
@section Color Conversion

Octave supports conversion from the RGB color system to the HSV color system
and vice versa.  It is also possible to convert from a color RGB image to a
grayscale image.

@DOCSTRING(rgb2hsv)

@DOCSTRING(hsv2rgb)

@DOCSTRING(rgb2gray)
