python opencv color tracking
Below is my python code for tracking white color objects.
It works - but only for a few seconds and then the whole screen turns black and in some times it not work.
I experimented with blue color and it works - but white and green are giving me problems:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
_, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of white color in HSV
# change it according to your need !
sensitivity = 15
lower_white = np.array([0,0,255-sensitivity])
upper_white = np.array([255,sensitivity,255])
# Threshold the HSV image to get only white colors
mask = cv2.inRange(hsv, lower_white, upper_white)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
Well, first thing you should know what color space you are using.
Just a small tutorial of color spaces in OpenCV for Mat
of type CV_8UC3
. (Images from Wikipedia)
HSV
In the HSV (Hue, Saturation, Value) color space, H gives the color dominant color, S the saturation of the color, V the lightness. In OpenCV, the ranges are different. S,V are in [0,255], while H is in [0, 180]. Typically H is in range [0,360] (the full circle), but to fit in a byte (256 different values) it's value is halved.
In HSV space is easier to separate a single color, since you can simply set the proper range for H, and just take care that S is not too small (it will be almost white), and V is not too small (it will be dark).
So for example, if you need almost blue colors, you need H to be around the value 120 (say in [110,130]), and S,V not too small (say in [100,255]).
White is not a hue (the rainbow doesn't have white color in it), but is a combination of color.
In HSV, you need to take all range of H (H in [0, 180]), very small S values (say S in [0, 25]), and very high V values (say V in [230, 255]). This basically corresponds to the upper part of the central axis of the cone.
So to make it track white objects in HSV space, you need:
lower_white = np.array([0, 0, 230])
upper_white = np.array([180, 25, 255])
Or, since you defined a sensitivity value, like:
sensitivity = 15
lower_white = np.array([0, 0, 255-sensitivity])
upper_white = np.array([180, sensitivity, 255])
For other colors:
green = 60;
blue = 120;
yellow = 30;
...
sensitivity = 15
// Change color with your actual color
lower_color = np.array([color - sensitivity, 100, 100])
upper_color = np.array([color + sensitivity, 255, 255])
Red H value is 0, so you need to take two ranges and "OR" them together:
sensitivity = 15
lower_red_0 = np.array([0, 100, 100])
upper_red_0 = np.array([sensitivity, 255, 255])
lower_red_1 = np.array([180 - sensitivity, 100, 100])
upper_red_1 = np.array([180, 255, 255])
mask_0 = cv2.inRange(hsv, lower_red_0 , upper_red_0);
mask_1 = cv2.inRange(hsv, lower_red_1 , upper_red_1 );
mask = cv2.bitwise_or(mask1, mask2)
Now you should be able to track any color!