I am trying to make a program which opens an image, scans it for circles/round shapes and returns the coordinates so that I can use the cv.Circle
function to draw circles over the circle detected.
My question is: How do I get the coordinates/radii of the circles detected in an image using cv.HoughCircles()
?
Using this page, I found out how to detect the circles (which took me a lot of time to find out since I don't understand terms like threshold and the OpenCV documentation for Python is really poor, almost none). Unfortunately, on that page it didn't show how to extract the information of each circle detected from the CvMat
created. How do I extract that information/is there some other way(eg. with MemoryStorage()
) ?
This is my code so far:
import cv, opencv
def main():
im = cv.LoadImageM("Proba.jpg")
gray = cv.CreateImage(cv.GetSize(im), 8, 1)
edges = cv.CreateImage(cv.GetSize(im), 8, 1)
cv.CvtColor(im, gray, cv.CV_BGR2GRAY)
cv.Canny(gray, edges, 50, 200, 3)
cv.Smooth(gray, gray, cv.CV_GAUSSIAN, 9, 9)
storage = cv.CreateMat(im.rows, 1, cv.CV_32FC3)
cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 2, gray.height/4, 200, 100)
# Now, supposing it found circles, how do I extract the information?
print storage.r
if __name__ == '__main__':
main()
Also, what value do the last two parameters of HoughCircles
need to have in order for me to detect really small circles (like 3mm on the screen) ?
Thank you all for your time and effort trying to help me!
The image I'm working with is this:
A similar solution in python. Originally I tried to run a contour detection described here, but it doesn't worked well. So first some thresholding was necessary. The code for threshold is here:
With this I get an image like this:
And after edge detection described in the link above I got this:
If you check the code, you will find that's really easy to count the objects. The only problem is, that some of the bubbles are counted twice. And I guess the thresholding function can be improved as well. But I suggest to use skimage it's easy to use and has good samples on their web page.
The last two parameters are what seem to be passed to
cv.Canny()
, which implies thatcv.Canny()
is called from withincv.HoughCircles()
. I'm not too sure about that.As for the sizes, it seems like the next two parameters (after
200, 100)
default to0
, which might mean that all sizes are detected.From the C++ example's source, I can also guess that you don't need to do a Canny edge detection:
You're trying to convert this C++ code into Python, I assume?
As far as I can tell,
CvMat
objects are iterable, just like a list:I don't have any test images, so don't take my word that this works. Your complete code would might be:
Have a look at my answer to this question for some working source code (it's C but I used a C++ compiler cause it's more lenient).
First, I cropped your image (to get something convenient to work with) and applied a threshold to your image to separate the foreground from the background:
Then I directly applied the source code to the thresholded image. Here is the text output:
And here is the output image:
The main problem is that circles that have merged together have not been detected at all. The code was originally written for detecting filled ellipses only, so you can probably deal with this issue by tweaking the code.