Created
April 4, 2017 13:40
-
-
Save nikgens/13f5efd9985ff8c4fbddb27fde7bc6e8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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