Detailed Analysis on Finding and Drawing Contours in an Image

Image source: wikipedia.org

Overview

Computer vision tasks like object detection, edge detection, image deskewing, fraud detection etc involve the detection and usage of contours. Contours are curves joining points on an object’s boundary which have the same color and/or intensity. Contours are detected as an array of (x,y) points on an image.

This array of points when joined, represents a contour curve. In this tutorial, we study the detection of contours in depth. Contour detection is frequently used in many topics and hence an in-depth study is required to gain a strong understanding of the basics of the concept.

Note: Object to be found must be white and the background should be black when using OpenCV contours.

Import Libraries

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

Numpy: Numpy is an open-source python library for handling n-dimensional arrays, written in the C programming language. Python is also written in the C programming language. Loading Numpy in the memory enables the Python interpreter to work with array computing in a fast and efficient manner.

Numpy offers the implementation of various mathematical functions, algebraic routines and Fourier transforms. Numpy supports different hardware and computing technologies and is well suited for GPU and distributed computing. The high-level language used provides ease of use with respect to the various Numpy functionalities.

CV2: OpenCV (Open source computer vision) library is a library written in C++ for optimized computer vision operations. The library has more than 2500 optimized algorithms. Improvements are being made to provide seamless integrations with CUDA.

The library is being used in various countries across the globe for face detection, surveillance, detecting drowning accidents, running interactive art, inspecting labels on products etc.

Matplotlib: Matplotlib is a Python library that enables plotting publication-quality graphs, static and interactive graphs using Python. Matplotlib plots can be exported to various file formats, can work with third-party packages and can be embedded in Jupyter notebooks.

Load Image

im=cv.imread('object.jpeg')
Image Source : https://www.codingem.com/inspect-a-python-object/

The function imread() loads an image from file and returns the image.

Various image file formats like windows bitmaps, JPEG files, PNG files, Sun Rasters, TIFF etc are supported by the imread() function. In OpenCV, colored images are stored in the BGR scheme.

For example in a 24-bit color image, the first 8 bits (1 byte) are Blue, next 1 byte is Green and the last byte is Red. Similar logic will be followed for the next pixel (B-G-R).

Greyscaling

imgray = cv.cvtColor(im,cv.COLOR_BGR2GRAY)

The cvtColor method converts the image from one colorspace to another as per the specified argument. E.g. in this code segment, we convert the image from BGR colorspace to greyscale.

Thresholding

ret, thresh = cv.threshold(imgray, 127, 255, 0)

The threshold() function converts each pixel of a greyscale image to one of the two (0 or maximum ) values.

  1. The first argument is the input image which must be in greyscale.
  2. The second argument is the user-defined threshold value.
  3. The third argument is the user-defined maximum pixel value.
  4. The fourth argument is the type of thresholding used.

OpenCV provides various types of thresholding and “0” corresponds to THRESH_BINARY. In the above line of code, if the pixel value is less than 127 then that pixel is assigned a value 0 and if the pixel value is greater than or equal to 127, the pixel is assigned a value of 255.

The function returns two values — the applied threshold value as “ret” and the thresholded image as “thresh”.

Finding Contours

contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)

We use the findContours method to find the contour curve-points in the image.

  1. The first argument to the findContours method is the thresholded image.
  2. The second argument to the findContours method is the contour retrieval mode.

The contours can be present in the image in various modes. An example is nested contours, where one contour is present inside another contour (e.g. a rectangle inside another rectangle) in a parent-child relationship.

cv.RETR_TREE mode returns all parent-child relationships among the contours with detailed hierarchical details in the format [Next contour at the same hierarchical level, Previous contour at the same hierarchical level, First_child index, index of Parent].

E.g. let us assume that we have 5 numbered contours with their hierarchical level mentioned in brackets — 0(0), 1(0), 2(1), 3(1), 4(2) — as shown in the figure below. This means that we have 5 contours (0 through 4) and three hierarchical levels (0 through 2).

We analyze the first contour “0”. Next contour at the same hierarchical level is “1”. Previous contour at the same hierarchical level is “-1” (no contour). First child is “-1” (no contour). Parent is “-1” (no contour).

Hence the hierarchy array for the “0” contour is [1,-1,-1,-1]. So the hierarchy numpy array for all the contours will be array([ [ [1,-1,-1,-1], [-1,0,2,-1], [3,-1,4,1], [-1,2,-1,1], [-1,-1,-1,2] ] ]) where the element indices represent the contour numbers (0 through 4).

Image Source : Author

The third argument to the findContours method is the mode of selection of contour points. E.g. cv.CHAIN_APPROX_NONE mode selects all the continuous contour points which uses more memory.

If we want to detect the contour points for contour number “1” we can find the four corner points using cv.CHAIN_APPROX_SIMPLE and label the contour as a rectangle. This results in efficient memory utilization.

The return values of the findContours method are the “contours” and “hierarchy” arrays. The “hierarchy” numpy array has been explained earlier. The “contours” array is a list of contours. Each contour is a numpy array of (x,y) boundary points.

E.g. assume that the contour “1” is array([ [[1,2 ]], [[3,4]] ]) and the contour “2” is array([ [[5,6]],[[7,8]] ]). The final “contour” array comprising of contour 1 and contour 2 now becomes [ array([ [[1,2 ]], [[3,4]] ]), array([ [[5,6]],[[7,8]] ]) ].

Drawing Contours

cv.drawContours(im, contours, -1, (0,255,0), 3)
  1. The drawContours method takes the source image as the first argument.
  2. The second argument is a Python list of contours.
  3. The third argument gives the index of the contour to be drawn from the contour array.
  4. “-1” means that all contours from the contour array are to be drawn.
  5. The fourth and fifth arguments specify the color and thickness of the drawn contour line.

Displaying Output

plt.imshow(im)
plt.show()

The imshow() function is used to display the image on a 2D screen. Note that the matplotlib.pyplot.imshow() method displays the image in the RGB color space instead of the OpenCV standard BGR color space.

The output image shows the contours plotted in Green. As can be seen, the method is effective for object detection, edge detection and has IDP applications. The show() method displays all open figures.

Conclusion

This brings us to the end of the article. In this article, we studied finding and drawing contours with OpenCV in details. We focused on gaining an in-depth understanding of the libraries and code used when defining a contour through the OpenCV library.

Please write comments and reviews as applicable. Feedback is always welcome.

Note: This article takes words from my earlier Analytics Vidhya article on “Heart disease prediction using logistic regression on UCI dataset”

My name is Narayanan (Yetirajan**) Arvind and I am working as an AI/ML R&D engineer at IN-D by Emulya Technologies PTE LTD. My interests lie in Computer vision, NLP , Deep learning and machine learning. My linkedin profile can be found at: https://www.linkedin.com/in/arvind-yetirajan-narayanan-iyengar-2b0632167/

  • * meaning king of the ascetics

References

--

--

Arvind (Yetirajan) Narayanan Iyengar

King of the ascetics | AI/ML R&D engineer with 10 years of research experience. My interests lie in CV, NLP, ML, Deep learning and Software Engineering.