Greg
Greg

Reputation: 149

Correct colorspace for cv2.inRange() function

Regarding the following cv2.inRange(...) invocation:

mask = cv2.inRange(quantized_img, color, color)

Must the 'quantized_img' and 'color' arguments be strictly in HSV or it's OK to have RGB image and RGB 'color'? It seems that RGB works for me, but all examples I could find are HSV-based. So I'm concerned about the correct usage. Thanks!

Upvotes: 3

Views: 984

Answers (2)

Rahul Kedia
Rahul Kedia

Reputation: 1420

The explanation given by @Christoph Rackwitz is completely correct. I'll just like to add a few tips observed by me.

  • HSV and Lab color spaces are the best ones for color segmentation.
  • Keep BGR color space as probably the last option.
  • Do not just blindly start finding the range in HSV or Lab color segmentation for your color. Look for other methods too.
  • Other methods include:
    • Visualize each color channel of HSV and Lab separately as a grayscale image. You might see some pattern there only.
    • One thing that helped in my case was I did Otsu's thresholding on "Hue" and "Saturation" channels of my image and then performed a bitwise OR operation on their output. The final image had everything I need without any errors. Do a hit-and-try on your input images to observe such patterns. This helps a lot.

Upvotes: 2

Christoph Rackwitz
Christoph Rackwitz

Reputation: 15354

In general, use whatever color space you like. RGB/BGR is fine, HSV is fine, something completely made up (with cv.transform) is fine too.

inRange spans a "cube".

Think about it. Imagine a 3D plot with R,G,B axes, or with H,S,V axes. In RGB space, the faces of the cube are aligned with those RGB axes. in HSV space the faces of the cube are aligned with those axes instead.

Now, a cube spanned in RGB space, when transformed into HSV space, is not aligned with the axes in HSV space. In fact it's not even a cube anymore, but likely some kind of torus or section of a cone or something. Same goes the other way around.

If the area of values you're interested in, in whatever space you choose, is flat or even stick-shaped (instead of a mostly spherical cloud), the cube you have to span might align very badly with the area of values you are interested in, and would have to include a lot of values you aren't interested in.

So you move into another color space where your values of interest are somewhat better aligned with the axes in that space. Then the cube spanned by inRange fits your purpose better.

Imagine a "stick" in RGB space going from the black corner to the white corner. It represents "colors" with no saturation to them (because colors are in the other six corners of the cube). Try spanning a cube over that area. Doesn't fit well.

In HSV space however, it's trivial. Usually it's visualized as a cylinder/inverted cone though... span a thin cylinder in the center: any Hue (angle), any Value (height), with very low Saturation (close to the center axis). If you took HSV as a cube, you'd span a thin wall instead. And it all would fit very well.

RGB cube HSV cone

Upvotes: 5

Related Questions