Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Method to extract specific color range from an image not working in Python

I'm trying to extract a specific color from an image within a defined BGR range using the cv2 module using Python 3. In the example below I am trying to isolate the fire from the exhaust of the space shuttle between yellow and white BGR values and then print out the percentage of RGB values within that range compared to the rest of the image.

Here is my minimal working example:

import cv2
import numpy as np
from matplotlib import pyplot as plt
import imageio

img = imageio.imread(r"shuttle.jpg")
cv2.imshow('original',img)
cv2.waitKey(1)

This is the output image. Its from wikipedia.

image description

#CONVERT TO HSV COLORS
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
color1 = np.uint8([[[0, 255, 255 ]]]) #yellow in BGR
color2 = np.uint8([[[255, 255, 255]]]) #white in BGR
hsv_color1 = cv2.cvtColor(color1,cv2.COLOR_BGR2HSV)
hsv_color2 = cv2.cvtColor(color2,cv2.COLOR_BGR2HSV)

print(hsv_color1)
print(hsv_color2)

#Define threshold color range to filter
mask = cv2.inRange(hsv_img, hsv_color1, hsv_color2)

# Bitwise-AND mask and original image
res = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)
ratio = cv2.countNonZero(mask)/(hsv_img.size/3)
print('pixel percentage:', np.round(ratio*100, 2))
#plt.imshow(mask)

cv2.imshow('mask',res)
cv2.waitKey(1)

However this does not seem to work because I get 0% of pixels between the yellow and white values. I'm not really sure where I'm going wrong:

Output

[[[ 30 255 255]]]
[[[  0   0 255]]]
pixel percentage: 0.0

And the output "res or mask" graph appears to be blank with a black image:

image description

Also when I just try to output the original image, it appears in a strange inverted color format:

cv2.imshow('hsv_img',hsv_img)

image description

Anyway, I have tried following the OpenCV tutorial on this but can't seem to get it to work: https://docs.opencv.org/3.2.0/df/d9d/tutorial_py_colorspaces.html

I guess what I'm tried to achieve here is something like the image below where only the colors between yellow and white are displayed, and then print out the percentage of pixels consisting of these colors. For the image below I just filtered out all colors below RGB (255, 255, 0) for yellow using a basic image processing software.

Is there a way to achieve this using the code I have already written or similar?

image description