how can i detect traffic light colors in opencv?

Here is one way to tell in Python/OpenCV using the G vs R 2D histogram. So if the 2D histogram has lots of white in the upper right, it is red, if along the lower left, it is green and if only along the diagonal, it is yellow.

So, make masks for the regions, mask the results and count the number of non-zero pixels using np.count_nonzero().

Input 1 (red)

enter image description here

Input 2 (green)

enter image description here

Input 3 (yellow)

enter image description here

import cv2
import numpy as np
import skimage.exposure as exposure
import os

filenames = ['traffic_light_red.jpg', 'traffic_light_green.jpg', 'traffic_light_yellow.jpg']

for filename in filenames:

    print(filename)

    # get name without suffix
    name = os.path.splitext(filename)[0]

    # read image
    img = cv2.imread(filename)

    # calculate 2D histograms for pairs of channels: GR
    histGR = cv2.calcHist([img], [1, 2], None, [256, 256], [0, 256, 0, 256])

    # histogram is float and counts need to be scale to range 0 to 255
    histScaled = exposure.rescale_intensity(histGR, in_range=(0,1), out_range=(0,255)).clip(0,255).astype(np.uint8)

    # make masks
    ww = 256
    hh = 256
    ww13 = ww // 3
    ww23 = 2 * ww13
    hh13 = hh // 3
    hh23 = 2 * hh13
    black = np.zeros_like(histScaled, dtype=np.uint8)
    # specify points in OpenCV x,y format
    ptsUR = np.array( [[[ww13,0],[ww-1,hh23],[ww-1,0]]], dtype=np.int32 )
    redMask = black.copy()
    cv2.fillPoly(redMask, ptsUR, (255,255,255))
    ptsBL = np.array( [[[0,hh13],[ww23,hh-1],[0,hh-1]]], dtype=np.int32 )
    greenMask = black.copy()
    cv2.fillPoly(greenMask, ptsBL, (255,255,255))

    #Test histogram against masks
    region = cv2.bitwise_and(histScaled,histScaled,mask=redMask)
    redCount = np.count_nonzero(region)
    region = cv2.bitwise_and(histScaled,histScaled,mask=greenMask)
    greenCount = np.count_nonzero(region)
    print('redCount:',redCount)
    print('greenCount:',greenCount)

    # Find color
    threshCount = 100
    if redCount > greenCount and redCount > threshCount:
        color = "red"
    elif greenCount > redCount and greenCount > threshCount:
        color = "green"
    elif redCount < threshCount and greenCount < threshCount:
        color = "yellow"
    else:
        color = "other"
    print("color: ",color)  

    # save result
    cv2.imwrite(name + '_histogram.jpg', histScaled)
    cv2.imwrite('redMask.jpg', redMask)
    cv2.imwrite('greenMask.jpg', greenMask)

    # view results
    cv2.imshow("hist", histScaled)
    cv2.imshow("redMask", redMask)
    cv2.imshow("greenMask", greenMask)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    print('')

Red Mask:

enter image description here

Green Mask:

enter image description here

Red Histogram:

enter image description here

Green Histogram:

enter image description here

Yellow Histogram:

enter image description here

Results:

traffic_light_red.jpg
redCount: 2627
greenCount: 0
color:  red

traffic_light_green.jpg
redCount: 0
greenCount: 1138
color:  green

traffic_light_yellow.jpg
redCount: 0
greenCount: 0
color:  yellow

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top