How do you convert RGB to HSV?
Scale the three channels to 0–1. Value is the largest one. Saturation is how far the smallest falls below the largest, as a share of the largest. Hue is an angle that depends on which channel is largest and how the other two compare. rgb(255, 165, 0) (orange) becomes hsv(38.8, 100%, 100%). The converter shows hue in degrees and the other two as percentages, each to one decimal place.
HSV is popular outside CSS because it separates "which color" from "how vivid" and "how bright". That makes it handy for image processing (isolating every pixel within a hue band), sorting a palette by hue, or analysing whether a set of colors is too dark.
The formulas
With R, G, B as fractions, max and min their extremes, and d = max − min:
| Component | Calculation |
|---|---|
| V | max |
| S | d / max (0 if max is 0) |
| H when red is max | 60 × ((G − B) / d mod 6) |
| H when green is max | 60 × ((B − R) / d + 2) |
| H when blue is max | 60 × ((R − G) / d + 4) |
| H when d is 0 | 0 |
A negative hue has 360 added. The tool then multiplies S and V by 100 and rounds all three to one decimal.
Example: a red that wraps around
Try rgb(200, 50, 60), a raspberry red with a hint of blue:
- Fractions: R = 0.784, G = 0.196, B = 0.235.
- max = 0.784 (red), min = 0.196, d = 0.588.
- V = 78.4%. S = 0.588 / 0.784 = 75%.
- Red is largest, so H = 60 × ((0.196 − 0.235) / 0.588) = 60 × (−0.067) = −4°.
- Negative, so add 360: H = 356°.
Output: hsv(356, 75%, 78.4%). Hue runs in a circle, and red sits at both ends. A red with a little blue lands just under 360, while a red with a little green lands just over 0. rgb(255, 0, 1) gives 359.8°, and rgb(255, 1, 0) would be near 0.2°.
This matters if you're thresholding. A filter for "red" pixels needs two ranges (say 0–10 and 350–360), or you'll miss half of them.
Rescaling for code libraries
Every library picks its own ranges, so values from this tool usually need converting before you paste them into code:
| Where | Hue | Saturation | Value |
|---|---|---|---|
| This tool | 0–360 | 0–100 | 0–100 |
| OpenCV, 8-bit images | 0–180 (H ÷ 2) | 0–255 | 0–255 |
Python colorsys |
0–1 | 0–1 | 0–1 |
Steps to turn a picked color into an OpenCV threshold, for instance:
- Convert a sample of the target color here, e.g.
rgb(255, 165, 0)giveshsv(38.8, 100%, 100%). - Halve the hue: about 19.
- Multiply S and V by 2.55: 255 and 255.
- Widen into a range, such as hue 14–24 with saturation and value above some floor, and test on real images.
OpenCV halves the hue so it fits in a single byte. Forgetting that is a classic bug: a hue of 38 in OpenCV is actually 76°, a yellow-green.
Edge cases
| RGB | HSV | Why |
|---|---|---|
0, 0, 0 |
hsv(0, 0%, 0%) | Black: no hue, no saturation |
128, 128, 128 |
hsv(0, 0%, 50.2%) | Grays have hue 0 by convention |
34, 139, 34 |
hsv(120, 75.5%, 54.5%) | Forest green: pure green hue, darkened |
0, 255, 254 |
hsv(179.8, 100%, 100%) | Just short of pure cyan at 180° |
Hue is rounded to one decimal, and anything that would round up to 360° is shown as 0 instead, since the two are the same angle. rgb(255, 0, 0.1), a red with a trace of blue at 359.98°, comes out as hsv(0, 100%, 100%). The tool's HSV inputs accept both 0 and 360.
Input rules
Enter three numbers from 0 to 255: rgb(30, 144, 255), 30, 144, 255, 30 144 255 and 30-144-255 all work, decimals are allowed, and a fourth number (alpha in rgba() or after /) is ignored. CSS-style percentages such as rgb(100%, 50%, 0%) are scaled so that 100% is 255. A minus sign at the start of a number, as in -30, 144, 255, makes it negative and shows an error. Everything runs in the browser.
The inverse is the HSV to RGB converter. If your starting point is a HEX code, HEX to HSV skips a step. For print, RGB to CMYK gives ink percentages instead. And if you're writing that image-processing script in Python, the Python lessons cover the basics.
Last updated