# OpenCV colour detection misses the colour: HSV ranges and the red wrap-around

> Fix colour masks: convert to HSV, find the range with a trackbar, handle red with two ranges and set the lighting steady.

Canonical: https://roboticsengineering.in/fix/opencv-colour-detection-hsv-range-wrong-red/ | Published: 2026-11-03 | Updated: 2026-11-04

**Convert to HSV and find your range with a trackbar.** Red needs two ranges because its hue wraps around.

## What the message means

In OpenCV hue runs from 0 to 179. Red sits at both ends, so one range cannot cover it. Lighting shifts saturation and value too.

## Fix it in this order

1. Convert the frame from BGR to HSV with cv2.cvtColor.
2. Make trackbars for the low and high of H, S and V and tune them live.
3. For red, join a mask for hue near 0 with a mask for hue near 170.
4. Use steady lighting, and avoid shiny surfaces.
5. Clean the mask with erode and dilate.
6. Find the largest contour for the object.

## Why it happens

OpenCV stores hue as 0 to 179 and saturation and value as 0 to 255. Red sits at both ends of the hue scale, so a single low-to-high range misses half of it. Two masks joined together cover it: for example hue 0 to 10 and hue 170 to 179 as starting points, then tune them with your own lighting.

Saturation and value change with brightness more than hue does, so keep their lower limits wide enough for shadows but high enough to ignore grey and white surfaces.

## If you see this, do this

| You see | Do this |
| --- | --- |
| Red is not found | Add the second hue range. |
| Works indoors, fails outdoors | Lighting. Widen S and V. |

## Related

[cannot open camera](https://roboticsengineering.in/fix/opencv-cannot-open-camera-wrong-index/), [camera calibration](https://roboticsengineering.in/camera-calibration-opencv-python/).

Last reviewed: November 2026. These are the usual causes and the order that finds them fastest. Test on your own board; clones and cables differ.

## Why this happens

HSV separates colour (hue) from how strong and how bright it is (saturation and value). OpenCV stores hue as half the usual angle so it fits in one byte: red is 0, yellow 30, green 60, cyan 90, blue 120 and magenta 150. Hue is a circle, so red sits at both ends, near 0 and near 179. A mask asking for hue 0 to 10 catches only half of the shades of red.

Saturation and value change a lot with light. In dim light value drops; under a coloured lamp hue shifts; on a shiny surface saturation falls. A range tuned in the afternoon can fail in the evening, so the limits should be set under the light the robot will use.

## How to confirm the cause

- Click or index one pixel on the object and print `hsv[y, x]`. Do this at several points to see the real spread of values.
- Show the mask itself with imshow. A mask that is mostly black with a few white dots means the range is too narrow; a mask full of white means it is too wide.
- Count mask pixels with `cv2.countNonZero(mask)` and watch the number while you move the object into shadow.
- Check the conversion flag. A frame from OpenCV is BGR, so COLOR_BGR2HSV is correct; using RGB2HSV swaps red and blue.
- Check the lower saturation and value limits, which keep white and grey surfaces out.

## Worked example

Pure red in BGR is (0, 0, 255), which converts to hue 0, saturation 255 and value 255. Two masks joined with OR cover both ends of the circle. Limits are starting points.

```
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
low  = cv2.inRange(hsv, (0, 120, 70),   (10, 255, 255))
high = cv2.inRange(hsv, (170, 120, 70), (179, 255, 255))
mask = cv2.bitwise_or(low, high)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
print(cv2.countNonZero(mask))
```

## Common mistakes

- Using hue values from an image editor on a 0 to 360 scale without halving them.
- Writing the range as (170, 10) and expecting it to wrap; inRange does not wrap.
- Setting saturation low enough that white walls appear in the mask.
- Tuning in one light and testing in another.
- Skipping the blur or morphology step and then tracking noise.

## If this did not fix it

- Automatic white balance or exposure changing the colours as the camera moves.
- Compression noise in a cheap camera at high resolution.
- Other red objects in the background; select the largest contour or restrict the region.
- A matte surface or a coating that looks different from what your eye expects.
