Skip to content

Instantly share code, notes, and snippets.

@nikgens
Created April 4, 2017 13:40
Show Gist options
  • Save nikgens/13f5efd9985ff8c4fbddb27fde7bc6e8 to your computer and use it in GitHub Desktop.
Save nikgens/13f5efd9985ff8c4fbddb27fde7bc6e8 to your computer and use it in GitHub Desktop.
import cv2
import numpy as np
import imutils
img = cv2.imread('circle1.jpg')
if img.shape[1] > 600:
img = imutils.resize(img, width=600)
clone = img.copy()
gray = cv2.cvtColor(clone, cv2.COLOR_BGR2GRAY)
ret,gray_threshed = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
'''
What is this filter? Bilateral filtering forms a very good way to preserve edges.
It is a non-linear filter and helps reduce noise. The concept of this filter is that,
at each pixel, its value is substituted by the average of the neighbourhood pixels.
That gives the smooth effect when this filter is applied. In our image, we see that
the background is not very even. This filter will help to even out the surface,
preserving the edges. OpenCV provides a function to implement bilateral filter.
The parameters used are: the image, window size for averaging the neighbour,
sigmaColor(Sigma value in the color space. This says that the farther colors
in the pixel neighbour will be mixed together. The larger the value, usually greater
that 150, the greater is the effect), sigmaSpace(Sigma value in coordinate space.
Larger value says that farther pixels will influence the current pixel).
Code below demonstrates a bilateral filter.
'''
bilateral_filtered_image = cv2.bilateralFilter(gray_threshed, 5, 175, 175)
'''
We applied a bilateral filter to preserve the edges. Now, it s time to detect the edges.
We will use Canny edge detector to detect edges in the image. By tracing the edges,
we are extracting features of the image. This detector uses two threshold values.
The Canny algorithm uses the first threshold to find the fine links and the second
threshold to find strong edges. The algorithm uses Gaussian filter, intensity
gradient and non-maxima suppression in the process of finding the edges.
OpenCV provides a function to implement edge detection using Canny algorithm.
It takes 3 parameters: image, lower threshold and upper threshold.
'''
edge_detected_image = cv2.Canny(bilateral_filtered_image, 75, 200)
# Find contours
_, contours, _= cv2.findContours(edge_detected_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
'''
This is the section where we are going to find circular objects.
The concept that we are going to use is, approxPolyDP. What does this do?
Well, this function helps to find what kind of polygon is the contour.
How? It gives the output as number of vertices for the polygon.
For eg., a square contour will give the output as 4 points, pentagon as 5 points and so on.
Circular objects will have higher number of points. Here, we see that depending on the type
of objects in the image, polygons with greater than 8 vertices form curvier shapes, here circle and ellipse.
If we carefully observe the function for approxPolyDP, we see that it calculates the percentage
of arcLength or perimeter of the contour. Approximates the contour with that information.
The higher the percentage, the lower the number of vertices. We are therefore using a very
low percentage to find details of the contour. After getting that information, we also
find the area of the contour. This is done in order to eliminate very small objects.
Below code explains the filtering process. Once that is done, we have the required circular shapes.
'''
contour_list = []
for contour in contours:
approx = cv2.approxPolyDP(contour,0.01*cv2.arcLength(contour,True),True)
area = cv2.contourArea(contour)
if ((len(approx) > 8) & (50000 > area > 10000) ): #10000 > area > 30
contour_list.append(contour)
#Displaying the results
cv2.drawContours(clone, contour_list, -1, (255,0,0), 2)
print(int(len(contour_list)/2))
# Show keypoints
cv2.imshow("Original", img)
cv2.imshow('Smooth', bilateral_filtered_image)
cv2.imshow('Edge', edge_detected_image)
cv2.imshow('Objects Detected',clone)
#cv2.imshow("output", np.hstack([img, clone]))
cv2.waitKey(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment