Title: Detecting Circles in Images using OpenCV and Hough Circles - PyImageSearch

URL Source: https://pyimagesearch.com/2014/07/21/detecting-circles-images-using-opencv-hough-circles/

Published Time: 2014-07-21T14:00:01+00:00

Markdown Content:
[![Image 1: Figure 2: Detecting the top of a soda can using circle detection with OpenCV.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20317'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/07/detect_circles_soda.jpg)

A few days ago, I got an email from a PyImageSearch reader asking about circle detection. See below for the gist:

> Hey Adrian,
> 
> Love your blog. I saw your post on [detecting rectangles/squares](https://pyimagesearch.com/2014/04/21/building-pokedex-python-finding-game-boy-screen-step-4-6/) in images, but I was wondering, how do you detect circles in images using OpenCV?
> 
> Thanks.

Great question.

As you’ve probably already found out, detecting circles in images using OpenCV is substantially harder than detecting other shapes with sharp edges.

But don’t worry!

In this blog post I’ll show you how to utilize the `cv2.HoughCircles` function to detect circles in images using OpenCV.

**To learn how to detect circles with OpenCV, _just keep reading!_**

![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

The cv2.HoughCircles Function
-----------------------------

In order to detect circles in images, you’ll need to make use of the `cv2.HoughCircles` function. It’s definitely not the easiest function to use, but with a little explanation, I think you’ll get the hang of it.

Take a look at the function signature below:

cv2.HoughCircles(image, method, dp, minDist)

*   **`image`:** 8-bit, single channel image. If working with a color image, convert to grayscale first.
*   **`method`:** Defines the method to detect circles in images. Currently, the only implemented method is `cv2.HOUGH_GRADIENT`, which corresponds to the [Yuen et al.](http://www.bmva.org/bmvc/1989/avc-89-029.pdf) paper.
*   **`dp`:** This parameter is the inverse ratio of the accumulator resolution to the image resolution (see Yuen et al. for more details). Essentially, the larger the `dp` gets, the smaller the accumulator array gets.
*   **`minDist`:** Minimum distance between the center _(x, y)_ coordinates of detected circles. If the `minDist` is too small, multiple circles in the same neighborhood as the original may be (falsely) detected. If the `minDist` is too large, then some circles may not be detected at all.
*   **`param1`:** Gradient value used to handle edge detection in the Yuen et al. method.
*   **`param2`:** Accumulator threshold value for the `cv2.HOUGH_GRADIENT` method. The smaller the threshold is, the more circles will be detected (including false circles). The larger the threshold is, the more circles will potentially be returned.
*   **`minRadius`:** Minimum size of the radius (in pixels).
*   **`maxRadius`:** Maximum size of the radius (in pixels).

If this method seems complicated, don’t worry. It’s actually not too bad.

But I will say this — be ready to play around with the parameter values from image to image. The `minDist` parameter is especially important to get right. Without an optimal `minDist` value, you may end up missing out on some circles, or you may detecting many false circles.

Ready to apply the `cv2.HoughCircles` function to detect circles in images?

Great. Let’s jump into some code:

\# import the necessary packages
import numpy as np
import argparse
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add\_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse\_args())

**Lines 2-4** import the necessary packages we’ll need. We’ll utilize NumPy for numerical processing, `argparse` for parsing command line arguments, and `cv2` for our OpenCV bindings.

Then, on **Lines 7-9** we parse our command line arguments. We’ll need only a single switch, `--image`, which is the path to the image we want to detect circles in.

Let’s go ahead and load the image:

\# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args\["image"\])
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR\_BGR2GRAY)

We load our image off disk on **Line 12** and create a copy of it on **Line 13** so we can draw our detected circles without destroying the original image.

As we’ll see, the `cv2.HoughCircles` function requires an 8-bit, single channel image, so we’ll go ahead and convert from the RGB color space to grayscale on **Line 14**.

Okay, time to detect the circles:

\# detect circles in the image
circles = cv2.HoughCircles(gray, cv2.HOUGH\_GRADIENT, 1.2, 100)

# ensure at least some circles were found
if circles is not None:
	# convert the (x, y) coordinates and radius of the circles to integers
	circles = np.round(circles\[0, :\]).astype("int")

	# loop over the (x, y) coordinates and radius of the circles
	for (x, y, r) in circles:
		# draw the circle in the output image, then draw a rectangle
		# corresponding to the center of the circle
		cv2.circle(output, (x, y), r, (0, 255, 0), 4)
		cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

	# show the output image
	cv2.imshow("output", np.hstack(\[image, output\]))
	cv2.waitKey(0)

Detecting the circles is handled by the `cv2.HoughCircles` function on **Line 17**. We pass in the image we want to detect circles as the first argument, the circle detection method as the second argument (currently, the `cv2.cv.HOUGH_GRADIENT` method is the only circle detection method supported by OpenCV and will likely be the only method for some time), an accumulator value of 1.5 as the third argument, and finally a `minDist` of 100 pixels.

A check is made on **Line 20** to ensure at least one circle was found in the image.

**Line 22** then handles converting our circles from floating point _(x, y)_ coordinates to integers, allowing us to draw them on our output image.

From there, we start looping over the center _(x, y)_ coordinates and the radius of the circle on **Line 25**.

We draw the actual detected circle on **Line 28** using the `cv2.circle` function, followed by drawing a rectangle at the center of the circle on **Line 29**.

Finally, **Lines 32 and 33** display our output image.

So there you have it — detecting circles in images using OpenCV.

But let’s go ahead and take a look at some results.

Fire up a shell, and execute the following command:

$ python detect\_circles.py --image images/simple.png

We’ll start with something simple, detecting a red circle on a black background:

[![Image 3: Figure 1: Detecting a simple circle in an image using OpenCV.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20326'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/07/detect_circles_simple.jpg)

**Figure 1:** Detecting a simple circle in an image using OpenCV.

Not bad! Our Python script has detected the red circle, outlined it in green, and then placed an orange square at the center of it.

Let’s move on to something else:

$ python detect\_circles.py --image images/soda.png

[![Image 4: Figure 2: Detecting the top of a soda can using circle detection with OpenCV.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20317'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/07/detect_circles_soda.jpg)

**Figure 2:** Detecting the top of a soda can using circle detection with OpenCV.

Again, our Python script is able to detect the circular region of the can.

Now, let’s try the 8 circle problem.

In this problem we have _one_ large circle, followed by _seven_ circles placed inside the large one.

Since this is a much smaller image than the previous ones (and we are detecting multiple circles), I’m going to adjust the `minDist` to be 75 pixels rather than 100.

[![Image 5: Figure 3: Notice how cv2.HoughCircles failed to detect the inner-most circle.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20322'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/07/detect_circles_8circles.jpg)

**Figure 3:** Notice how `cv2.HoughCircles` failed to detect the inner-most circle.

Hm. Now it looks like we have ran into a problem.

The `cv2.HoughCircles` function was able to detect only _seven_ of the circles instead of all _eight_, leaving out the one in the center.

Why did this happen?

It’s due to the `minDist` parameter. The center _(x, y)_ coordinates for the large outer circle are identical to the center inner circle, thus the center inner circle is discarded.

Unfortunately, there is not a way around this problem unless we make `minDist` unreasonably small, and thus generating many “false” circle detections.

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

**I strongly believe that if you had the right teacher you could _master_ computer vision and deep learning.**

Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?

That’s _not_ the case.

All you need to master computer vision and deep learning is for someone to explain things to you in _simple, intuitive_ terms. _And that’s exactly what I do_. My mission is to change education and how complex Artificial Intelligence topics are taught.

If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to _successfully_ and _confidently_ apply computer vision to your work, research, and projects. Join me in computer vision mastery.

**Inside PyImageSearch University you'll find:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, ensuring you can keep up with state-of-the-art techniques
*   ✓ **Pre-configured Jupyter Notebooks in Google Colab**
*   ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
*   ✓ Access to **centralized code repos for _all_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

Summary
-------

In this blog post I showed you how to use the `cv2.HoughCircles` function in OpenCV to detect circles in images.

Unlike detecting squares or rectangles in images, detecting circles is substantially harder since we cannot reply on approximating the number of points in a contour.

To help us detect circles in images, OpenCV has supplied the `cv2.HoughCircles` function.

While the `cv2.HoughCircles` method may seem complicated at first, I would argue that the most important parameter to play with is the `minDist`, or the minimum distance between the center _(x, y)_ coordinates of detected circles.

If you set `minDist` too small, you may end up with many falsely detected circles. On the other hand, if `minDist` is too large, then you may end up missing some circles. Setting this parameter definitely takes some fine tuning.

Have a Question?
----------------

Do you have a question about OpenCV and Python? Just send me a message. And I’ll do my best to answer it on this blog.

![Image 6](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### Download the Source Code and FREE 17-page Resource Guide

Enter your email address below to get a .zip of the code and a **FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.** Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!