Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python opencv - blob detection or circle detection

Tags:

I am having problems detecting circle areas. I tried it with the HoughCircles function from opencv. However even though the images are pretty similar the parameters for the funtion have to be different in order to detect the cirles.

Another approach I tried was to iterate over every pixel and check if the current pixel is white. If this is the case then check if there is a blob object in the area (distance to blob center smaller than a threshold). If there is, append the pixel to the blob, if not then create a new blob. This also didn't work properly.

Has anyone a idea how I can make this work (90% detection) ? I attached a example image and another image where I marked the cirles. Thanks!

example

example with arrows

UPDATE: Thank you for the help so far! This is the code where I acquire the contours and filter them by area:

im = cv2.imread('extract_blue.jpg') imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) im_gauss = cv2.GaussianBlur(imgray, (5, 5), 0) ret, thresh = cv2.threshold(im_gauss, 127, 255, 0) # get contours contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  contours_area = [] # calculate area and filter into new array for con in contours:     area = cv2.contourArea(con)     if 1000 < area < 10000:         contours_area.append(con) 

This works pretty neat. I drew them on the image: contours_filtered_area

This is the part where I filtered by circularity, it goes straight below the code where I filter by area:

contours_cirles = []  # check if contour is of circular shape for con in contours_area:     perimeter = cv2.arcLength(con, True)     area = cv2.contourArea(con)     if perimeter == 0:         break     circularity = 4*math.pi*(area/perimeter*perimeter)     print circularity     if 0.8 < circularity < 1.2:         contours_cirles.append(con) 

However, the new list 'contours_cirles' is empty. I printed 'circularity' in the loop and the values are all between 10 000 and 100 000.

UPDATE #2: After correcting the missing brackets it is working now!

contours_cirles = []  # check if contour is of circular shape for con in contours_area:     perimeter = cv2.arcLength(con, True)     area = cv2.contourArea(con)     if perimeter == 0:         break     circularity = 4*math.pi*(area/(perimeter*perimeter))     print circularity     if 0.7 < circularity < 1.2:         contours_cirles.append(con) 

Thanks a lot guys! :)

example_done

like image 370
cmplx96 Avatar asked Feb 13 '17 12:02

cmplx96


People also ask

What is blob detection OpenCV?

Blob stands for Binary Large Object and refers to the connected pixel in the binary image. The term "Large" focuses on the object of a specific size, and that other "small" binary objects are usually noise.

What is blob detection used for?

In computer vision, blob detection methods are aimed at detecting regions in a digital image that differ in properties, such as brightness or color, compared to surrounding regions.

Is OpenCV good for object detection?

Basically, the Haar cascade technique is an approach based on machine learning where we use a lot of positive and negative images to train the classifier to classify between the images. Haar cascade classifiers are considered as the effective way to do object detection with the OpenCV library.

What algorithm is used to detect circles in OpenCV?

cv2. HoughCircles(image, method, dp, minDist) Where Image is the image file converted to grey scale Method is the algorithm used to detct the circles. Dp is the inverse ratio of the accumulator resolution to the image resolution. minDist is the Minimum distance between the center coordinates of detected circles.


2 Answers

As a starting point you may start with:

  • Find all the contours in the given image using cv2.findContours()
  • Iterate over each contour:
    • calculate the area, if the area of contour is in a given range say 70 < area < 150. This will filter out some extremely smaller and large contours.
    • After filtering the contours with the area threshold, you need to check the number of edges of contour, which can be done using: cv2.approxPolyDP(), for a circle len(approx) must be > 8 but < 23. Or you may apply some more sophisticated operations to detect circles here.

You should try to implement this approach and update the question with the code that you will write henceforth.

EDIT: As suggested by @Miki, there is a better and cleaner way of detecting if a geometrical shape is of circular shape using circularity = 4pi(area/perimeter^2), and decide a threshold such as 0.9, to check if the shape is circular. For perfect circle circularity == 1. You may fine tune this threshold as per your needs.

You may consult arcLength to find the perimeter of the contour and contourArea to get the area of the contour which are required to calculate the circularity.

like image 75
ZdaR Avatar answered Sep 28 '22 08:09

ZdaR


We could try Hough Transformation too to detect the circles in the image and play with the thresholds to get the desired result (detected circles in green boundary lines with red dots as centers):

import cv2 import numpy as np  img = cv2.imread('rbv2g.jpg',0) img = cv2.medianBlur(img,5) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)  circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,10,                             param1=50,param2=12,minRadius=0,maxRadius=20)  circles = np.uint16(np.around(circles)) for i in circles[0,:]:     # draw the outer circle     cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)     # draw the center of the circle     cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)  cv2.imshow('detected circles',cimg) cv2.waitKey(0) cv2.destroyAllWindows() 

enter image description here

like image 25
Sandipan Dey Avatar answered Sep 28 '22 08:09

Sandipan Dey