Search code examples
pythonopencvcolor-detection

How to give user inputs to detect a specific color from video in opencv?


I have written a code in python to detect a red color in OpenCV. I am getting proper output,but I want to give user input in the code to detect a specific color. Eg: If I will give blue as a user input, it should show only blue on the output. I also want to add few attributes as a output, such as time of that object get detected and location of the live video. I am new to python and opencv, it would be great if I will get some guidance.

My existing code is as below:

import cv2
import numpy as np

# Capture the input frame from webcam
def get_frame(cap, scaling_factor):
    # Capture the frame from video capture object
    ret, frame = cap.read()

    # Resize the input frame
    frame = cv2.resize(frame, None, fx=scaling_factor,
            fy=scaling_factor, interpolation=cv2.INTER_AREA)

    return frame

if __name__=='__main__':
    cap = cv2.VideoCapture(0)
    scaling_factor = 0.5

    # Iterate until the user presses ESC key
    while True:
        frame = get_frame(cap, scaling_factor)

        # Convert the HSV colorspace
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        # Define 'blue' range in HSV colorspace
        lower = np.array([60,100,100])
        upper = np.array([180,255,255])

        # Threshold the HSV image to get only blue color
        mask = cv2.inRange(hsv, lower, upper)

        # Bitwise-AND mask and original image
        res = cv2.bitwise_and(frame, frame, mask=mask)
        res = cv2.medianBlur(res, 5)

        cv2.imshow('Original image', frame)
        cv2.imshow('Color Detector', res)

        # Check if the user pressed ESC key
        c = cv2.waitKey(5)
        if c == 27:
            break

    cv2.destroyAllWindows()   

Solution

  • Your code seems to work correctly. Looking at the equations about converting from RGB to HSV bearing in mind that boundaries in OpenCV are between 0-180 for H channel and 0-255 for S and V channels, we can generalize the code to work for all colors.

    import cv2
    import numpy as np
    
    # Capture the input frame from webcam
    def get_frame(cap, scaling_factor):
        # Capture the frame from video capture object
        ret, frame = cap.read()
    
        # Resize the input frame
        frame = cv2.resize(frame, None, fx=scaling_factor,
                fy=scaling_factor, interpolation=cv2.INTER_AREA)
    
        return frame
    
    # Define the color range in HSV colorspace
    lower1 = np.array([0,100,100])
    upper1 = np.array([60,255,255])
    lower2 = np.array([120,100,100])
    upper2 = np.array([180,255,255])
    def color_range(degree):
        # Degree is between 0-360
        # OpenCV uses 0-180 range for H channel
        degree = int(degree/2);
        global lower1, upper1, lower2, upper2
        if degree < 60:
            lower1 = np.array([int(0),100,100])
            upper1 = np.array([degree+60,255,255])
            lower2 = np.array([degree+120,100,100])
            upper2 = np.array([int(180),255,255])
        elif degree > 120:
            lower1 = np.array([degree-60,100,100])
            upper1 = np.array([int(180),255,255])
            lower2 = np.array([int(0),100,100])
            upper2 = np.array([degree-120,255,255])
        else:
            lower1 = np.array([degree-60,100,100])
            upper1 = np.array([degree+60,255,255])
            # ineffective variables
            lower2 = np.array([181,100,100])
            upper2 = np.array([181,255,255])
    
    if __name__=='__main__':
        cap = cv2.VideoCapture(0)
        scaling_factor = 0.5
    
        # create trackbar for color change
        winname = 'Color Detector'
        cv2.namedWindow(winname)
        cv2.createTrackbar('Color', winname, 0, 360, color_range)
    
        # Iterate until the user presses ESC key
        while True:
            frame = get_frame(cap, scaling_factor)
    
            # Convert the HSV colorspace
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
            # Threshold the HSV image to get only desired color
            mask1 = cv2.inRange(hsv, lower1, upper1)
            mask2 = cv2.inRange(hsv, lower2, upper2)
            mask = cv2.bitwise_or(mask1, mask2)
    
            # Bitwise-AND mask and original image
            res = cv2.bitwise_and(frame, frame, mask=mask)
    
            cv2.imshow('Original image', frame)
            cv2.imshow(winname, res)
    
            # Check if the user pressed ESC key
            c = cv2.waitKey(1) & 0xFF
            if c == 27:
                break
    
        cv2.destroyAllWindows()
        cap.release()