Edge Detection

September 05, 2022
Computer Vision

Canny Edge Detection

OpenCV also offers a very handy function called Canny (after the algorithm’s inventor, John F. Canny), which is very popular not only because of its effectiveness, but also the simplicity of its implementation in an OpenCV program, as it is a one-liner:

# Import Necessary library
import cv2
import numpy as np
# Read MyPic.jpg from system as grayscale
img = cv2.imread("MyPic.jpg", 0)
# Create Canny Edge Detection and saving image
cv2.imwrite("canny.jpg", cv2.Canny(img, 200, 300))

Our input Image:

Output Image for Canny Edge Detection will be:

The Canny edge detection algorithm is quite complex but also interesting: it’s a five-step process that denoises the image with a Gaussian filter, calculates gradients, applies non maximum suppression (NMS) on edges, a double threshold on all the detected edges to eliminate false positives, and, lastly, analyzes all the edges and their connection to each other to keep the real edges and discard the weak ones.

Contour Detection

Another vital task in computer vision is contour detection, not only because of the obvious aspect of detecting contours of subjects contained in an image or video frame, but because of the derivative operations connected with identifying contours.

These operations are, namely, computing bounding polygons, approximating shapes, and generally calculating regions of interest, which considerably simplify interaction with image data because a rectangular region with NumPy is easily defined with an array slice. We will be using this technique a lot when exploring the concept of object detection (including faces) and object tracking.

Let’s go in order and familiarize ourselves with the API first with an example:

# Import Necessary library
import cv2
import numpy as np

# Create a black box of 200x200 pixels
img = np.zeros((200, 200), dtype=np.uint8)
# Add a white box of 100x100 pixels in the black box
img[50:150, 50:150] = 255
# Store new image as box.jpg
cv2.imwrite("box.jpg",img)
# Obtain thresholding between 127 and 255 intensity
ret, thresh = cv2.threshold(img, 127, 255, 0)
# Obtain contours in image with defined thresholding
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Convert image to gray scale
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# Draw green contours of width 4px in the image.
img = cv2.drawContours(color, contours, -1, (0,255,0), 4)
# Store contoured image as contours.jpg
cv2.imwrite("contours.jpg",color)

Our input Image:

Output Image for Canny Edge Detection will be:

Firstly, we create an empty black image that is 200x200 pixels in size. Then, we place a white square in the center of it utilizing ndarray’s ability to assign values on a slice.

We then threshold the image, and call the findContours() function. This function has three parameters: the input image, hierarchy type, and the contour approximation method. There are a number of aspects that are of particular interest in this function:

  • The function modifies the input image, so it would be advisable to use a copy of the original image (for example, by passing img.copy()).
  • Secondly, the hierarchy tree returned by the function is quite important:
  • cv2.RETR_TREE will retrieve the entire hierarchy of contours in the image, enabling you to establish “relationships” between contours. If you only want to retrieve the most external contours, use cv2.RETR_EXTERNAL. This is particularly useful when you want to eliminate contours that are entirely contained in other contours (for example, in a vast majority of cases, you won’t need to detect an object within another object of the same type).

The findContours function returns three elements: the modified image, contours, and their hierarchy. We use the contours to draw on the color version of the image (so that we can draw contours in green) and eventually display it.

Finding Area Using Contour

Finding the contours of a square is a simple task; irregular, skewed, and rotated shapes bring the best out of the cv2.findContours utility function of OpenCV. Let’s take a look at the following image:

In a real-life application, we would be most interested in determining the bounding box of the subject, its minimum enclosing rectangle, and its circle. The cv2.findContours function in conjunction with a few other OpenCV utilities makes this very easy to accomplish:

# Import Necessary library
import cv2
import numpy as np

# Read Image
img = cv2.imread("Hammer.png")
# Obtain thresholding between 127 and 255 intensity
ret, thresh = cv2.threshold( cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) , 127, 255, cv2.THRESH_BINARY)
# Obtain contours in image with defined thresholding
image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
   # Find bounding box coordinates
   x,y,w,h = cv2.boundingRect(c)
   cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)
   # Find minimum area
   rect = cv2.minAreaRect(c)
   # Calculate coordinates of the minimum area rectangle
   box = cv2.boxPoints(rect)
   # Normalize coordinates to integers
   box = np.int0(box)
   # Draw contours for box
   cv2.drawContours(img, [box], 0, (0,0, 255), 3)
   # Calculate center and radius of minimum enclosing circle
   (x,y),radius = cv2.minEnclosingCircle(c)
   # Cast to integers
   center = (int(x),int(y))
   radius = int(radius)
   # Draw the circle
   img = cv2.circle(img,center,radius,(0,255,0),2)


# Draw all the contours in image
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
# Save image as contour1.jpg
cv2.imwrite("contour1.jpg", img)

Output Image will be:

VIkas Donta

My name is VIkas Donta and I first discovered Web Designingin 2018. Since then, It has impact on my web design projects development career, and  improve my understanding of HTML/CSS tremendously!

Related Posts

Stay in Touch

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form

Stay in Touch

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form