Colortracking With OpenCV

Track a color is a pretty interesting and useful feature that OpenCV allow to do via multiples operations. The central function is InRangeS, it takes to values and all the pixels whose value is within the two values is set to white and all the others to black. At this point we have a picture where all pixels that match the wanted color are white.

Another important point is that we do not use the BGR or RGB colorspace because the pixel value is highly dependant of the luminosity and few others factors so to get the better result, the image is firstly converted to the HSV colorspace (hue, saturation, and intensity).

Then to compare a frame and the next we have to use the moments functionnalities that allow to calculate the Spatial moment and get the central point. Finally a line can be easily drawn between the current central point and the one of the previous frame.

Result :

Thresholded image (with InRangeS):

The Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import cv2.cv as cv

def getThresholdImage(im):
    newim = cv.CloneImage(im)
    cv.Smooth(newim, newim, cv.CV_BLUR,12) #Remove noise

    hsv=cv.CreateImage(cv.GetSize(im), 8, 3)
    cv.CvtColor(newim, hsv, cv.CV_BGR2HSV) # Convert image to HSV
    imThreshed = cv.CreateImage(cv.GetSize(im), 8, 1)
    #Do the threshold on the hsv image, with the right range for the yellow color
    cv.InRangeS(hsv, cv.Scalar(20, 100, 100), cv.Scalar(30, 255, 255), imThreshed)
    del hsv
    return imThreshed


capture = cv.CaptureFromCAM(0)

cv.NamedWindow("video")
cv.NamedWindow("thresh")

tmp = cv.QueryFrame(capture)
imgScribble = cv.CreateImage(cv.GetSize(tmp), 8, 3) #Image that will contain lines

posx = 0
posy = 0

while True:
    frame = cv.QueryFrame(capture)

    imgYellowTresh = getThresholdImage(frame) #Apply the threshold function

    moments = cv.Moments(cv.GetMat(imgYellowTresh),1)
    moment10 = cv.GetSpatialMoment(moments, 1, 0)
    moment01 = cv.GetSpatialMoment(moments, 0, 1)
    area = cv.GetCentralMoment(moments, 0, 0) #Get the center

    lastx = posx
    lasty = posy
    if area == 0:
        posx = 0
        posy = 0
    else:
        posx = moment10/area
        posy = moment01/area

    if lastx > 0 and lasty > 0 and posx > 0 and posy > 0: #Mean we have received coordinates to print
        #Draw the line
        cv.Line(imgScribble, (int(posx),int(posy)), (int(lastx),int(lasty)), cv.Scalar(0, 255,255),3,1)

    #Add the frame and the line image to see lines on the webcam frame
    cv.Add(frame, imgScribble, frame)

    cv.ShowImage("video", frame)
    cv.ShowImage("thresh", imgYellowTresh)
    c=cv.WaitKey(1)
    if c==27 or c==1048603: #Break if user enters 'Esc'.
        break
    elif c== 1048690: # 'r' for reset
        cv.Zero(imgScribble)

This source file is also hosted on github.

<<Officials OpenCV Python Samples | Home | Motion detection>>