OpenCV  4.5.2
Open Source Computer Vision
Eroding and Dilating

Prev Tutorial: Smoothing Images
Next Tutorial: More Morphology Transformations

Original author Ana Huamán
Compatibility OpenCV >= 3.0

Goal

In this tutorial you will learn how to:

  • Apply two very common morphological operators: Erosion and Dilation. For this purpose, you will use the following OpenCV functions:
Note
The explanation below belongs to the book Learning OpenCV by Bradski and Kaehler.

Morphological Operations

  • In short: A set of operations that process images based on shapes. Morphological operations apply a structuring element to an input image and generate an output image.
  • The most basic morphological operations are: Erosion and Dilation. They have a wide array of uses, i.e. :
    • Removing noise
    • Isolation of individual elements and joining disparate elements in an image.
    • Finding of intensity bumps or holes in an image
  • We will explain dilation and erosion briefly, using the following image as an example:

Dilation

  • This operations consists of convolving an image \(A\) with some kernel ( \(B\)), which can have any shape or size, usually a square or circle.
  • The kernel \(B\) has a defined anchor point, usually being the center of the kernel.
  • As the kernel \(B\) is scanned over the image, we compute the maximal pixel value overlapped by \(B\) and replace the image pixel in the anchor point position with that maximal value. As you can deduce, this maximizing operation causes bright regions within an image to "grow" (therefore the name dilation).
  • The dilatation operation is: \(\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\)
  • Take the above image as an example. Applying dilation we can get:

  • The bright area of the letter dilates around the black regions of the background.

Erosion

  • This operation is the sister of dilation. It computes a local minimum over the area of given kernel.
  • As the kernel \(B\) is scanned over the image, we compute the minimal pixel value overlapped by \(B\) and replace the image pixel under the anchor point with that minimal value.
  • The erosion operation is: \(\texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\)
  • Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image get thinner, whereas the dark zones gets bigger.

Code

Explanation

Note
Additionally, there are further parameters that allow you to perform multiple erosions/dilations (iterations) at once and also set the border type and value. However, We haven't used those in this simple tutorial. You can check out the reference for more details.

Results

Compile the code above and execute it (or run the script if using python) with an image as argument. If you do not provide an image as argument the default sample image (LinuxLogo.jpg) will be used.

For instance, using this image:

We get the results below. Varying the indices in the Trackbars give different output images, naturally. Try them out! You can even try to add a third Trackbar to control the number of iterations.

(depending on the programming language the output might vary a little or be only 1 window)

cv::String
std::string String
Definition: cvstd.hpp:150
cv::moveWindow
void moveWindow(const String &winname, int x, int y)
Moves the window to the specified position.
cv::erode
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Erodes an image by using a specific structuring element.
cv::samples::findFile
cv::String findFile(const cv::String &relative_path, bool required=true, bool silentMode=false)
Try to find requested data file.
cv::MORPH_RECT
@ MORPH_RECT
a rectangular structuring element:
Definition: imgproc.hpp:232
cv::waitKey
int waitKey(int delay=0)
Waits for a pressed key.
highgui.hpp
cv::namedWindow
void namedWindow(const String &winname, int flags=WINDOW_AUTOSIZE)
Creates a window.
cv::MORPH_ELLIPSE
@ MORPH_ELLIPSE
Definition: imgproc.hpp:235
cv::Size
Size2i Size
Definition: types.hpp:347
cv::getTrackbarPos
int getTrackbarPos(const String &trackbarname, const String &winname)
Returns the trackbar position.
cv::dilate
void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Dilates an image by using a specific structuring element.
cv::imread
Mat imread(const String &filename, int flags=IMREAD_COLOR)
Loads an image from a file.
cv::Mat::empty
bool empty() const
Returns true if the array has no elements.
cv::Mat::cols
int cols
Definition: mat.hpp:2096
cv::dnn::print
static void print(const MatShape &shape, const String &name="")
Definition: shape_utils.hpp:198
cv::imshow
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
cv::MORPH_CROSS
@ MORPH_CROSS
Definition: imgproc.hpp:233
cv::Point
Point2i Point
Definition: types.hpp:194
cv::Mat
n-dimensional dense array class
Definition: mat.hpp:801
cv::imshow
void imshow(const String &winname, const ogl::Texture2D &tex)
Displays OpenGL 2D texture in the specified window.
cv::CommandLineParser
Designed for command line parsing.
Definition: utility.hpp:799
cv::WINDOW_AUTOSIZE
@ WINDOW_AUTOSIZE
the user cannot resize the window, the size is constrainted by the image displayed.
Definition: highgui.hpp:188
cv::IMREAD_COLOR
@ IMREAD_COLOR
If set, always convert image to the 3 channel BGR color image.
Definition: imgcodecs.hpp:72
cv::createTrackbar
int createTrackbar(const String &trackbarname, const String &winname, int *value, int count, TrackbarCallback onChange=0, void *userdata=0)
Creates a trackbar and attaches it to the specified window.
cv
"black box" representation of the file storage associated with a file on disk.
Definition: affine.hpp:51
cv::getStructuringElement
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
Returns a structuring element of the specified size and shape for morphological operations.
imgproc.hpp
cv::add
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)
Calculates the per-element sum of two arrays or an array and a scalar.