OpenCV  4.5.2
Open Source Computer Vision
Hit-or-Miss

Prev Tutorial: More Morphology Transformations
Next Tutorial: Extract horizontal and vertical lines by using morphological operations

Original author Lorena GarcĂ­a
Compatibility OpenCV >= 3.0

Goal

In this tutorial you will learn how to find a given configuration or pattern in a binary image by using the Hit-or-Miss transform (also known as Hit-and-Miss transform). This transform is also the basis of more advanced morphological operations such as thinning or pruning.

We will use the OpenCV function morphologyEx() .

Hit-or-Miss theory

Morphological operators process images based on their shape. These operators apply one or more structuring elements to an input image to obtain the output image. The two basic morphological operations are the erosion and the dilation. The combination of these two operations generate advanced morphological transformations such as opening, closing, or top-hat transform. To know more about these and other basic morphological operations refer to previous tutorials (Eroding and Dilating) and (More Morphology Transformations).

The Hit-or-Miss transformation is useful to find patterns in binary images. In particular, it finds those pixels whose neighbourhood matches the shape of a first structuring element \(B_1\) while not matching the shape of a second structuring element \(B_2\) at the same time. Mathematically, the operation applied to an image \(A\) can be expressed as follows:

\[ A\circledast B = (A\ominus B_1) \cap (A^c\ominus B_2) \]

Therefore, the hit-or-miss operation comprises three steps:

  1. Erode image \(A\) with structuring element \(B_1\).
  2. Erode the complement of image \(A\) ( \(A^c\)) with structuring element \(B_2\).
  3. AND results from step 1 and step 2.

The structuring elements \(B_1\) and \(B_2\) can be combined into a single element \(B\). Let's see an example:

Structuring elements (kernels). Left: kernel to 'hit'. Middle: kernel to 'miss'. Right: final combined kernel

In this case, we are looking for a pattern in which the central pixel belongs to the background while the north, south, east, and west pixels belong to the foreground. The rest of pixels in the neighbourhood can be of any kind, we don't care about them. Now, let's apply this kernel to an input image:

Input binary image
Output binary image

You can see that the pattern is found in just one location within the image.

Code

The code corresponding to the previous example is shown below.

As you can see, it is as simple as using the function morphologyEx() with the operation type MORPH_HITMISS and the chosen kernel.

Other examples

Here you can find the output results of applying different kernels to the same input image used before:

Kernel and output result for finding top-right corners
Kernel and output result for finding left end points

Now try your own patterns!

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::morphologyEx
void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Performs advanced morphological transformations.
cv::MORPH_HITMISS
@ MORPH_HITMISS
Definition: imgproc.hpp:226
cv::waitKey
int waitKey(int delay=0)
Waits for a pressed key.
CV_8U
#define CV_8U
Definition: interface.h:73
highgui.hpp
core.hpp
cv::Mat::convertTo
void convertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const
Converts an array to another data type with optional scaling.
cv::Size
Size2i Size
Definition: types.hpp:347
cv::imshow
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
cv::Scalar
Scalar_< double > Scalar
Definition: types.hpp:669
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::resize
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR)
Resizes an image.
cv::INTER_NEAREST
@ INTER_NEAREST
Definition: imgproc.hpp:247
cv
"black box" representation of the file storage associated with a file on disk.
Definition: affine.hpp:51
imgproc.hpp
cv::destroyAllWindows
void destroyAllWindows()
Destroys all of the HighGUI windows.
cv::Mat_< uchar >