Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding red color in image using Python & OpenCV

I am trying to extract red color from an image. I have code that applies threshold to leave only values from specified range:

img=cv2.imread('img.bmp') img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV) lower_red = np.array([0,50,50]) #example value upper_red = np.array([10,255,255]) #example value mask = cv2.inRange(img_hsv, lower_red, upper_red) img_result = cv2.bitwise_and(img, img, mask=mask) 

But, as i checked, red can have Hue value in range, let's say from 0 to 10, as well as in range from 170 to 180. Therefore, i would like to leave values from any of those two ranges. I tried setting threshold from 10 to 170 and using cv2.bitwise_not() function, but then i get all the white color as well. I think the best option would be to create a mask for each range and use them both, so I somehow have to join them together before proceeding.

Is there a way I could join two masks using OpenCV? Or is there some other way I could achieve my goal?

Edit. I came with not much elegant, but working solution:

image_result = np.zeros((image_height,image_width,3),np.uint8)  for i in range(image_height):  #those are set elsewhere     for j in range(image_width): #those are set elsewhere         if img_hsv[i][j][1]>=50 \             and img_hsv[i][j][2]>=50 \             and (img_hsv[i][j][0] <= 10 or img_hsv[i][j][0]>=170):             image_result[i][j]=img_hsv[i][j] 

It pretty much satisfies my needs, and OpenCV's functions probably do pretty much the same, but if there's a better way to do that(using some dedicated function and writing less code) please share it with me. :)

like image 749
yolo77 Avatar asked May 19 '15 17:05

yolo77


People also ask

Can OpenCV detect colors?

We can use the inRange() function of OpenCV to create a mask of color, or in other words, we can detect a color using the range of that color. The colors are stored in an RGB triplet value format inside a color image. To create its mask, we have to use the RGB triplet value of that color's light and dark version.

What is cv2 inRange?

inRange function. The cv2. inRange function expects three arguments: the first is the image were we are going to perform color detection, the second is the lower limit of the color you want to detect, and the third argument is the upper limit of the color you want to detect.

What is RGB in Python?

In more technical terms, RGB describes a color as a tuple of three components. Each component can take a value between 0 and 255, where the tuple (0, 0, 0) represents black and (255, 255, 255) represents white.


1 Answers

I would just add the masks together, and use np.where to mask the original image.

img=cv2.imread("img.bmp") img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  # lower mask (0-10) lower_red = np.array([0,50,50]) upper_red = np.array([10,255,255]) mask0 = cv2.inRange(img_hsv, lower_red, upper_red)  # upper mask (170-180) lower_red = np.array([170,50,50]) upper_red = np.array([180,255,255]) mask1 = cv2.inRange(img_hsv, lower_red, upper_red)  # join my masks mask = mask0+mask1  # set my output img to zero everywhere except my mask output_img = img.copy() output_img[np.where(mask==0)] = 0  # or your HSV image, which I *believe* is what you want output_hsv = img_hsv.copy() output_hsv[np.where(mask==0)] = 0 

This should be much faster and much more readable than looping through each pixel of your image.

like image 55
derricw Avatar answered Sep 30 '22 07:09

derricw