22

How can I define "lower" and "upper" range of two different color, such as red and blue (because red and blue are not next to each other in the HSV color)

This one belongs to red:

lower_red = np.array([160,20,70])
upper_red = np.array([190,255,255])

and this one belongs to blue:

lower_blue = np.array([101,50,38])
upper_blue = np.array([110,255,255])

I tried to combine them using if condition or make their own function but not work, can you guys show me the solution?

P/s: OpenCV in Python

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Nhiên Ngô Đình
  • 544
  • 2
  • 6
  • 16

4 Answers4

55

As you get two masks of colors, then use cv2.bitwise_or to get the final mask.

import cv2

## Read
img = cv2.imread("sunflower.jpg")

## convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

## mask of green (36,0,0) ~ (70, 255,255)
mask1 = cv2.inRange(hsv, (36, 0, 0), (70, 255,255))

## mask o yellow (15,0,0) ~ (36, 255, 255)
mask2 = cv2.inRange(hsv, (15,0,0), (36, 255, 255))

## final mask and masked
mask = cv2.bitwise_or(mask1, mask2)
target = cv2.bitwise_and(img,img, mask=mask)

cv2.imwrite("target.png", target)

Source:

enter image description here

Find green and yellow(the range is not that accurate):

enter image description here


BTW, to get more accurate range, here is a refer map in my related answer:

How to define a threshold value to detect only green colour objects in an image :Opencv

enter image description here

Kinght 金
  • 17,681
  • 4
  • 60
  • 74
  • How could I dynamically input the upper and lower ranges with RGB input? For instance, I have an application where the user submits an image and chooses two RGB values, upper and lower, to remove the background from. How would I convert those two RGB values into cv2-friendly HSV values for the cv2.inrange function? – Logan Price Jun 24 '23 at 20:31
4

The below image shows the HSV Colour space, which works using Hue, Saturation & Value (or lightness).

HSV Colour Space

When working in the HSV colour space it is important to remember this and that concepts such as Red & Green are a sort-of conversion back to a different data type.

Your upper and lower boundaries can therefore only be one point in this space but can include parts of the red and blue spectrum's, i.e. purple. You would need to select threshold values that meet the criteria of whatever processing output you need.

Either that or run two separate loops, the first to threshold out the Red, and the second to threshold out your blue and then blend the two images together using OpenCV Blend functions. See here for blending two colour spaces.

shiva
  • 5,083
  • 5
  • 23
  • 42
GPPK
  • 6,546
  • 4
  • 32
  • 57
  • I am working with traffic sign, one of them is red and the other is blue, I cannot blend them together. Is there any way to setting 2 different range or just run two separate loops? – Nhiên Ngô Đình Jan 05 '18 at 09:10
2
# Make a copy of the image

image_copy = np.copy(image)
## TODO: Define the color selection boundaries in RGB values
# play around with these values until you isolate the blue background

lower_blue = np.array([200,0,0]) 
upper_blue = np.array([250,250,255])

# Define the masked area

mask = cv2.inRange(image_copy, lower_blue, upper_blue)
# Vizualize the mask

plt.imshow(mask,cmap='gray')
0

Alternatively, You can create your two masks and combine them into one mask like this;

finalmask = mask_red | mask_blue

It is the same as using bitwise_or. And you can pipe many masks like this;

maskf = maskA | maskB | maskC
Anil Myne
  • 79
  • 3