Python opencv - blob detection or circle detection

I'm having trouble detecting areas of a circle. I tried it using the HoughCircles function from opencv. However, although the images are pretty similar, the parameters for funtion must be different in order to detect loops.

Another approach I tried was to iterate over each pixel and check if the current pixel is white. If so, check to see if there is a blob in this area (the distance to the center of the blob is less than a threshold). If there is, add a pixel to the blob, if not, then create a new blob. It also does not work properly.

Does anyone have an idea how I can make this work (90% detection)? I have attached an example image and another image where I have designated loops. Thanks!

example

arrow example

UPDATE: Thanks so far for the help! This is the code in which I get the outlines 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 neatly. I drew them in the image: contours_filtered_area

This is the part that I filtered by roundness, it goes right 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 "roundness" in the loop, and the values ​​are from 10,000 to 100,000.

UPDATE # 2: After fixing missing brackets, it now works!

 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

+8
python opencv circle
source share
2 answers

As a starting point, you can start with:

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

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

EDIT: As @Miki suggested, there is a better and cleaner way to detect if the geometric shape is round with rounding = 4pi (area / perimeter ^ 2) and determines a threshold such as 0.9 to check if the shape is circular , For a perfect circle circularity == 1 . You can fine tune this threshold to suit your needs.

You can turn to arcLength to find the perimeter of the contour and contourArea to get the area of ​​the contour that is required to calculate roundness.

+4
source share

We could try the Hough Transformation also detect circles in the image and play with the thresholds to get the desired result (detected circles in green border lines with red dots in the form of 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

+1
source share

All Articles