HSV v RGB with inRange

asked 2019-08-14 14:55:11 -0500

I used a colour picker and worked out equivalent range values in HSV and RGB for my special yellow.

Scalar yellowHsvMin = new Scalar(50, 35, 40);
Scalar yellowHsvMax = new Scalar(55, 91, 71);

Scalar yellowRgbMin = new Scalar(139, 127, 66);
Scalar yellowRgbMax = new Scalar(249, 238, 114);

But when I apply a filter using the HSV values:

Mat raw = Imgcodecs.imread("file.jpg");
Matt colours = new Matt(raw.size(), raw.type());
Matt yel = new Matt(raw.size(), raw.type());
Imgproc.cvtColor(raw, colours, Imgproc.COLOR_BGR2HSV);
Core.inRange(colours, yellowHsvMin, yellowHsvMax, yel);

I get a hugely different answer to using RGB values:

Mat raw = Imgcodecs.imread("file.jpg");
Matt colours = new Matt(raw.size(), raw.type());
Matt yel = new Matt(raw.size(), raw.type());
Imgproc.cvtColor(raw, colours, Imgproc.COLOR_BGR2RGB);
Core.inRange(colours, yellowRgbMin, yellowRgbMax, yel);

I would expect it to be slightly different from rounding errors etc but it's completely different. Can anyone help me understand what I'm doing wrong?

edit retag flag offensive close merge delete

Comments

see Color conversions RGB ↔ HSV and notice

8-bit images: V←255V,S←255S,H←H/2(to fit to 0 to 255)

sturkmen gravatar imagesturkmen ( 2019-08-14 19:43:29 -0500 )edit

the upper limit of H would be 179 but your H in yellowRgbMax is 249, which may make more colors(especially red) show in your image.

gino0717 gravatar imagegino0717 ( 2019-08-14 21:32:39 -0500 )edit

@gino0717 The "H" in yellow-->Rgb<--Max is 249 because it's only used in the RGB channels. yellow-->Hsv<--Max is 55 (below 179) and is used with the COLOR_BGR2HSV channels.

davidnewcomb gravatar imagedavidnewcomb ( 2019-08-15 18:12:13 -0500 )edit

try swap your channel 0 and channel 2 like:

Scalar yellowRgbMin = new Scalar(66, 127, 139);
Scalar yellowRgbMax = new Scalar(114, 238, 249);

since the color in opencv channel is ( blue , green , red ) instead of ( red , green , blue )

gino0717 gravatar imagegino0717 ( 2019-08-15 20:49:16 -0500 )edit

There is no need to swap the channels in the scalar because the colour conversion (COLOR_BGR2--->RGB<---) has already converted it to RGB. In fact the RGB code (above) is pretty good. I don't understand why when I pick 2 shades of yellow (min/max) the RGB/BGR works fine but the HSV is useless. Even if I do min(45, 100, 100) and max(66, 255, 255) with BGR2HSV I expect to get everything that is yellowy but I get nearly all black. I am clearly not understanding something about HSV colour filtering but I don't know what it is.

davidnewcomb gravatar imagedavidnewcomb ( 2019-08-16 09:48:14 -0500 )edit

@sturkman not sure why you posted the link? Looks like you are just saying v,s [0,255] and h [0,179] which isn't relevant either because none of my hsv values are outside that range.

davidnewcomb gravatar imagedavidnewcomb ( 2019-08-16 09:58:33 -0500 )edit

i mean you need to half of H values

Scalar yellowHsvMin = new Scalar(25, 35, 40);
Scalar yellowHsvMax = new Scalar(28, 91, 71);
sturkmen gravatar imagesturkmen ( 2019-08-16 21:55:48 -0500 )edit