Tag Archives: cv2.morphologyEx

Understanding Structuring Element with Trackbars

As we already discussed that the most important thing in morphological image processing is the Structuring element. This is used to probe an image for finding the region of interest. Different shapes and sizes of SE will produce a different result. Thus it becomes vital to have a good grasp on this for better understanding of morphological image processing. In this blog, let’s create trackbars which makes it really easy to visualize the result for different values. So, let’s get started.

Steps:

  • Load the image and create a window to attach trackbars
  • Specify the morphological operations and Structuring elements
  • Create the trackbars and the callback function

This will produce the following output

Play with the trackbars to get a feel about the morphological operations. That’s all for this blog. Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time

Thinning and Thickening

In the previous blog, we discussed Hit-or-Miss transformation, that is used for finding desired patterns in an image. In this blog, we will discuss various applications of Hit-or-miss transform such as thinning, thickening, etc. So, let’s get started.

Thinning

This is somewhat similar to erosion or opening operation that we discussed earlier. As clear from the name, this is used to thin the foreground region such that its extent and connectivity is preserved. Preserving extent means preserving the endpoints of a structure whereas connectivity can refer to either 4-connected or 8-connected. Thinning is mostly used for producing skeletons which serve as image descriptors, and for reducing the output of the edge detectors to a one-pixel thickness, etc.

There are various algorithms to implement the thinning operation such as

  • Zhang Suen fast parallel thinning algorithm
  • Non-max Suppression in Canny Edge Detector
  • Guo and Hall’s two sub-iteration parallel Thinning algorithm
  • Iterative algorithms using morphological operations such as hit-or-miss, opening and erosion, etc

In this blog, we will only discuss the last algorithm, rest we will discuss in the following blogs. So, let’s get started.

In this, we can implement thinning either using erosion and opening operations or by using hit-or-miss operation. Let’s first discuss thinning using erosion and opening. This can be expressed as the union of skeleton subsets where each subset is given by the following expression (A-Binary image and B-structuring element)

Here, n indicates the number of iterations of erosion. N is the last iterative step before A erodes to the empty set (stopping condition). Now, let’s discuss how to implement this using OpenCV-Python.

Now, let’s discuss thinning using hit-or-miss transform. Thinning of set A by SE B can be expressed in terms of hit-or-miss transform as

This means we remove all those pixels whose neighborhood exactly matches the pixels in the SE. Instead of applying this with a single structuring element, it is a common practice to implement it using a sequence of SE so as to produce symmetric results. This operation is mostly applied iteratively until no further changes occur.

Thickening

Thickening is the dual of thinning and thus is equivalent to applying the thinning operation on the background or on the complement of the set A.

In the next blog, we will discuss the remaining thinning algorithms in detail. Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.

Hit-or-Miss Transform

In this blog, we will discuss Hit-or-Miss transformation. This is basically used for shape detection or finding particular patterns in the given image. The shape or pattern to match has to be provided via the structuring element. This transformation can be easily implemented using the erosion operation. So, let’s get started.

Here, we use two structuring elements (say B1 and B2). In this, we ask a simple question of does B1 fits the object while, simultaneously, B2 misses the object, i.e. fits the background? In other words, we are interested only in those pixels whose neighborhood exactly matches B1 while not matching B2 at the same time. As we already discussed that erosion answers the question of whether the SE fits or not. Thus, Hit-or-Miss operation can be expressed in terms of erosion as

Here, we assume that both SE B1 and B2 don’t intersect otherwise this operation cannot be performed. Because both B1 and B2 are disjoint sets, we can express both in terms of a single structuring element. Doing so makes the operation more interpretable. Let’s see how.

Suppose we want to find a T-shaped pattern in the image defined by the SE B1 such that it does not contain the pattern defined by B2 in its right neighborhood. 0 below represents that we don’t care about these positions. Below figure shows how to combine two SE into one.

Now, just compare the underlying pixels values with the combined SE. If it matches exactly then the pixel underneath the origin of SE is set to 1 else 0. Let’s take an example. Suppose we want to find the above combined SE in the image shown below. Clearly, the one on the lower right matches the pattern defined by the combined SE. The result is shown on the right side.

Below is the code for this. The hit-or-miss can be implemented using the OpenCV cv2.morphologyEx() function by passing the flag cv2.MORPH_HITMISS as shown below.

This way you can find any patterns in the input image. In the next blog, we will discuss other applications of hit-or-miss operation such as thinning, thickening, convex Hull, etc. Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.

Opening and Closing

In the previous blogs, we discuss two fundamental morphological operations – Erosion and Dilation. Both have their own advantages and disadvantages. For instance, erosion is useful in removing salt noise and structures of a certain shape but at the same time, if holes or gaps are present in the object, this tends to amplify them. So, what we want is something that removes the structures or fills holes/gaps without affecting the remaining foreground parts.

One plausible solution is to combine erosion and dilation operation. So, for instance, let’s take the case of noise removal. Like we discussed that the erosion will remove the salt noise but at the same time will shrink the foreground region also. To counter this, we apply dilation operation using the same structuring element. Because noise is removed, so dilation will only work on the shrunk foreground area and revert it back to the original. This process of applying erosion followed by dilation is known as Opening and in this blog, we will discuss this method in detail.

So, why is the name Opening? Because this opens up the gap between the objects connected by thin protrusions that are of size less than that of the structuring element. Below is the image where the bridge is 2 pixels wide while the SE is 3 pixels wide.

Now, let’s formulate the opening operation in terms of a set operation. The opening of binary image A by the structuring element B is defined as the erosion of A by B, followed by the dilation of the result by B. This can be stated using any of the two expressions as shown below

The second one states that the opening is the union of all the translations of SE B that fits into A. There is an interesting property associated with the opening known as idempotence. This simply states that if an image has been opened once, performing the subsequent opening operation with the same SE will have no effect on that image. This is because after opening the new boundaries created are such that the SE always fits inside them. Now, let’s discuss another operation – closing that is a dual of opening operation.

Closing

This is the just the reverse of Opening i.e Dilation followed by Erosion. Because this closes the holes/gaps present in the object while keeping the initial object size the same. That’s why the name Closing. Now, let’s formulate this in terms of a set operation.

Actual implementation involves rotating the SE by 180 degrees before performing dilation and erosion. But since our SE is mostly symmetric, we usually don’t care. Similar to the opening, this operator is also idempotent. Unlike opening, this fuses narrow breaks or bridges between the objects. Generally, good for removing pepper noise but not salt noise.

Now, let’s discuss how to implement these using OpenCV-Python. For Opening, one way is to first apply erosion and then dilation using the builtin functions we discussed earlier. Similarly, for closing also. Fortunately, OpenCV provides another function that directly implements these operations as shown below.

Here, src is the input image with any number of channels( all will be processed independently) and the kernel is the structuring element whose origin is defined by the anchor (default (-1,-1)). Don’t know why the iterations argument is given because the opening and closing are idempotent operators. You can create the SE using cv2.getStructuringElement() or simply using numpy. It is sometimes useful to pad the image to account for the boundary pixels or if the image is of non-regular shape and this can be done using the “borderType” and “borderValue” arguments. The “op” argument specifies which type of morphological operation to apply. Following are the types available.

  • MORPH_OPEN – an opening operation
  • MORPH_CLOSE – a closing operation
  • MORPH_GRADIENT – a morphological gradient
  • MORPH_TOPHAT – “top hat”
  • MORPH_BLACKHAT – “black hat”

Below is an example where we open and close the image with the rectangular SE.

In the next blog, we will discuss other morphological operators like morphological gradient, top hat, etc. Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.