Nick Pfeiffer
Nick Pfeiffer

Reputation: 211

Good technique for color masks with opencv

I've been struggling to create my own color masks that work using the following image enter image description here

I am trying to isolate the red stop sign in this example. My initial strategy was to use a color picker to get a range of red values (HSV format):

Lower bound:

enter image description here

Upper bound:

enter image description here

Code:

import numpy as np
import cv2

img = cv2.imread("image.jpg")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

lower = np.array([0, 59, 49])
upper = np.array([0, 100, 100])

mask = cv2.inRange(hsv, lower, upper)

result = cv2.bitwise_and(hsv, hsv, mask=mask)

cv2.imshow("image", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

The resulting image (result variable) is completely black, which I assume means that none of the red was detected. I assume this has something to do with the HSV values I chose, but I'm not sure what's wrong with them.

When I use 2 masks and modified HSV values (that I found online), it works very well; the stop sign and only the stop sign is highlighted in result:

import numpy as np
import cv2

img = cv2.imread("image.jpg")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

lower = np.array([0, 50, 50])
upper = np.array([10, 255, 255])
lower2 = np.array([170, 50, 50])
upper2 = np.array([180, 255, 255])

mask = cv2.inRange(hsv, lower, upper)
mask2 = cv2.inRange(hsv, lower2, upper2)
mask = mask + mask2

result = cv2.bitwise_and(hsv, hsv, mask=mask)

cv2.imshow("image", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

So my question is why does the second example work so much better than the first? Should I always use 2 masks and add them? What should the first mask do versus what the second mask does? How can I choose better HSV values?

Upvotes: 0

Views: 2418

Answers (1)

Christoph Rackwitz
Christoph Rackwitz

Reputation: 15365

Your first piece of code selects for exactly 0 degrees of hue. That stop sign will probably not have exactly that hue. Hence, not selected.

Your second piece of code gives some range of hues. That's why it can catch the stop sign.

The second piece of code has to split the hue range up into two segments because the desired hue goes from negative to positive (0 +- 20 degrees). cv.inRange has no logic that would allow you to express that in a single range. Hence two pieces, or-ed together (addition).

Upvotes: 3

Related Questions