pythonimageopencvimage-processingcolor-detection

Detect circles with specific colors using opencv


I have to detect yellow circles in an image using OpenCV and python, as shown in the first image:

Picture 1 image

Once I detect the yellow circle, I have to highlight it, like so:

Picture 2

I am new to OpenCV, so I was looking for some guidance or help. All help is appreciated


Solution

  • Here's a potential approach:

    We convert image to HSV and then determine lower and upper boundaries to create a mask using cv2.inRange(). This step isolates the yellow objects

    image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    lower = np.array([0, 208, 94], dtype="uint8")
    upper = np.array([179, 255, 232], dtype="uint8")
    mask = cv2.inRange(image, lower, upper)
    

    Next to determine the shape, we find contours and filter using the number of vertices. We use cv2.arcLength() and cv2.approxPolyDP() to obtain a list of vertices and approximate contours. We can check the number of entries in this list to determine the shape of an object. For instance, if the contour has three vertices, it must be a triangle. Similarly, if it has four vertices, it must be a square. So for this image, we can make the assumption the shape is a circle if it has greater than a certain number of vertices. Here's the result

    import numpy as np
    import cv2
    
    image = cv2.imread('1.png')
    original = image.copy()
    image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    lower = np.array([0, 208, 94], dtype="uint8")
    upper = np.array([179, 255, 232], dtype="uint8")
    mask = cv2.inRange(image, lower, upper)
    
    # Find contours
    cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # Extract contours depending on OpenCV version
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    
    # Iterate through contours and filter by the number of vertices 
    for c in cnts:
        perimeter = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * perimeter, True)
        if len(approx) > 5:
            cv2.drawContours(original, [c], -1, (36, 255, 12), -1)
    
    cv2.imshow('mask', mask)
    cv2.imshow('original', original)
    cv2.imwrite('mask.png', mask)
    cv2.imwrite('original.png', original)
    cv2.waitKey()