Contours are curves joining point along a boundary having same colour or intensity. To accurately use the contour features, use a binary image. Since the findContours function modifies the original image always backup the original image in a separate variable. Also the object to be detected should white on a black background.

Once the image binarization is done, Contour detection can be carried out.
The findContours() function uses 3 arguments: First is the image, second the contour retrieval mode, third is contour approximation method. The outputs are the image,contours and hierarchy. Contours is a list of all the contours in the image. Each contour is an array of the coordinates making the contour.

To draw the contours we use the drawContours function. It takes as argument: the image name, the Python list containing all the contours generated by findContours, the index of the contour to draw and the colour and thickness of the boundary.

The contour approximation method is the third parameter in the findContours function. It can be set to cv2.CHAIN_APPROX_NONE which detects and saves all the boundary points in the contour or cv2.CHAIN_APPROX_SIMPLE which only saves the end points of the contour. The latter removes redundancy and also saves memory.

Canny Edge Detection

Edges are one of the most important features in an image. Edges are basically areas with high intensity contrast. Canny edge detection algorithm developed by John F. Canny in 1986 is a multi-stage optimal edge detector. It is carried out as follows:

Noise Reduction
Since every image is susceptible to noise a Gaussian filter is applied and the image is smoothed.

Intensity Gradient
A Sobel filter is applied to smoothed image in both x and the y axis. This gives the edge gradients and direction of the edge pixels.

Non-maximum Suppression
Every pixel extracted out by the Sobel filter is tested for whether it constitutes an edge or not.
This is done by testing if the pixel is at a local maximum in its neighbourhood in the direction of gradient.
This step basically thins out the edges.

Hysteresis Thresholding
This final tests if all the detected edges are real or dummy. Two threshold values minVal and maxVal are set. Any edge with intensity gradient above maxVal is an edge an those below minVal are discarded. The pixels which lie in between if are discarded if they are not connected to a sure edge.

A simple example to show how Canny edge detection is carried out using python:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('circle.png',0)
edges = cv2.Canny(img,100,200)

plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

The result:

An application for Canny Edge detection with trackbars to adjust the Hysteresis threshold values: