
Detect red circles in an image using OpenCV - AlexeyBrin
https://solarianprogrammer.com/2015/05/08/detect-red-circles-image-using-opencv/
======
lettergram
It would probably be better to use the Lab color space, and then you only have
to look at the a channel (which is the transformation of color between red and
green).

I used this to great effect in edge detection because the Lab color space is
based on eyes. Just changing images from RGB to the Lab color space increased
the accuracy of edge detection (particularly for red/green items) by about 7%:
[http://austingwalters.com/edge-detection-in-computer-
vision/](http://austingwalters.com/edge-detection-in-computer-vision/)

Further, I used this color space to design a super accurate fiducial marker
(and QR code)[1], that can be used to store a lot more information, easier to
track, etc.

I believe the grad student I was working with was going to publish a paper at
some point. For what ever reason I wasn't involved with the paper and the
paper doesn't appear to be published yet.

The HSV color space separates out hue and saturation, which helps remove the
background noise, but it would have trouble with overlapping circles or
circles where red and blue say mix to make purple. Converting to the Lab space
would actually help distinguish overlapping colors as well.

Here's a link to my work: [1]
[http://austingwalters.com/chromatags/](http://austingwalters.com/chromatags/)

~~~
Jack000
can you expand on why RGB wouldn't work? The most obvious way I can think of
to include chroma information in apriltags would be to use 3 colors matched to
the peak sensitivity of each channel. Does the RBG spectral sensitivity
overlap too much for this to work?

~~~
lettergram
The RGB color space works, it just has light encoded in each channel (making
it unnormalized). Separating out the light, i.e. normalizing on the color is
what gives LAB the advantage.

Further, because the way RGB is structured taking the difference between
channels is more difficult (requires more calculations) than it does for the a
& b channels. For instance, the a channel represents red to green, or positive
a represents red and negative a represents green. This aids in finding edges
between red and green with a simple addition/subtraction between pixels(a[i,i]
- a[j,j]). If we were to try the same thing in the RGB space it would look
something like (R[i,i] + G[i,i]) - (R[j,j] + G[j,j]), and you would still have
the impact of light to deal with...

------
elteto
I once wrote a similar OpenCV application [1], but in my case I needed to
detect a closed contour and evaluate how close that contour was to being a
circle. To provide a "score" I took advantage of the fact that in a circle the
ratio C^2/(4 _pi_ A) = 1 (where C is the circumference and A is the area).
This is a unique property of the circle (it is equivalent to saying that the
ratio of perimeter to area is maximized in a circle) and it's always lower for
any other closed shapes. And it also provides a nice 0..1 result which can be
interpreted as a percentage score!

I followed pretty much the same image segmentation/binary threshold as in the
article, but found that the gaussian blur step was unnecessary in my case, so
I skipped it. Also, the closed contours API in OpenCV provides the area and
perimeter results so it was _very easy_ to get it all working. Most of the
code was actually just writing a simple UI in Python.

[1]
[https://www.youtube.com/watch?v=iN6D5j2RfX0](https://www.youtube.com/watch?v=iN6D5j2RfX0)

------
userbinator
This expression should work to get all the reds without having to do
colourspace transform (standard unsigned 8-bit RGB expanded to signed ints of
greater width):

    
    
        r - g > 128 && r - b > 128
    

The constants can be adjusted to change the definition of what you consider
red. (Based on [https://en.wikipedia.org/wiki/File:HSV-RGB-
comparison.svg](https://en.wikipedia.org/wiki/File:HSV-RGB-comparison.svg) )

~~~
lettergram
It doesn't properly handle the light, i.e. if the r or g channel is super dim
it'll cause issues.

------
0x0
Getting an SSL privacy error (NET::ERR_CERT_AUTHORITY_INVALID) on this page.
(I've removed the StartCom root CA from my OS after reading
[https://groups.google.com/forum/#!topic/mozilla.dev.security...](https://groups.google.com/forum/#!topic/mozilla.dev.security.policy/k9PBmyLCi8I)
)

------
k_sze
Technically wrong. Those are red _discs_ , not red _circles_. </pedantic>

~~~
k_sze
You think I'm joking, right? I'm not.

Think of the keywords that apply to the title. "OpenCV" and "circle"
definitely are. I don't consider "detect" and "image" as keywords here because
if you are using OpenCV, there's a _very_ high probability that you want to
detect something in an image. So "detect" and "image" are pretty much implied
by "OpenCV". And I'm going to give you the benefit of doubt and include "red"
as a keyword.

So we end up with "OpenCV", "circle", and "red". Three keywords. "circle"
being technically wrong means that you got 1/3 of the keywords wrong. That's
actually no small mistake.

Let's say you are working on a project and you are in urgent need to find out
how to use OpenCV to effectively detect actual _circles_ (not red _discs_ ).
You type these keywords into your favourite search engine: ["opencv",
"circle"]. And you get this article as the top result because it has the right
keywords and it ranks high in popularity. Then congratulations, you just
wasted your precious time. Of course, you can start from this article and get
to your correct solution. But remember I said that you're in urgent need,
you're in a hurry, you don't have time to waste.

The converse is also true: you want to detect actual red _discs_ but you can't
find this article because the article's keywords are wrong.

When I saw the title of the article, I really was expecting it to talk about
detecting _circles_ , not _discs_. I started at the beginning and I thought
"ok, maybe the author's approach is to start from discs and eventually get to
circles". I followed through to the end expecting to see actual circles, but
then... nothing. I was really disappointed.

I could be even more pedantic and point out that in mathematics, a circle has
no width, but if we take that extra pedantic definition, then we won't expect
to detect anything at all in an image. The difference here is that when we
talk about "circle", we know that we are really talking about an _approximate
representation_ of a circle. But a circle is not an approximate representation
of a disc, or vice versa, period.

------
1024core
Or you could use the Circle Hough Transform:
[https://en.wikipedia.org/wiki/Circle_Hough_Transform](https://en.wikipedia.org/wiki/Circle_Hough_Transform)

~~~
Animats
Which is what they did. It's inefficient, because it's a brute-force process,
but it works.

