'How to detect the colors nicely using OpenCV python

(It is not the whole code, it's just the main part)

It's just a simple project I wanted to do, not school or anything.

I want to segment out the red parts nicely, but I can't because the light and the camera quality is always changing. I'm using this on camera on the picture. (I don't think it's necessary to put that in here)

I don't think this solution is the best for this kinda project:

lower_red = np.array([15, 15, 110], dtype="uint8")
upper_red = np.array([75, 75, 255], dtype="uint8")

So I want to know how to make it independent of the environment and detect what is necessary for me.

Also make it for the other colors too (black, blue, green, orange, yellow)

import cv2 as cv
import numpy as np


# just resizing the image if it's too big
def base(img):
    if img.shape[0] > 1000 or img.shape[1] > 1000:
        scale_percent = 20  # percent of original size
        width = int(img.shape[1] * scale_percent / 100)
        height = int(img.shape[0] * scale_percent / 100)
        dim = (width, height)
    else:
        dim = (img.shape[1], img.shape[0])

    img = cv.resize(img, dim, interpolation=cv.INTER_AREA)
    return img


def sort(img):
    lower_red = np.array([15, 15, 110], dtype="uint8")
    upper_red = np.array([75, 75, 255], dtype="uint8")

    # lower_blue = np.array([70, 15, 15], dtype="uint8")
    # upper_blue = np.array([255, 75, 75], dtype="uint8")
    
    mask_red = cv.inRange(img, lower_red, upper_red)
    # mask_blue = cv.inRange(img, lower_blue, upper_blue)

    red_detected_output = cv.bitwise_and(img, img, mask=mask_red)
    # blue_detected_output = cv.bitwise_and(img, img, mask=mask_blue)
    
    cv.imshow("color detection", red_detected_output)

    return red_detected_output


def contour(img, frame):
    _, thresh_gray = cv.threshold(cv.cvtColor(img, cv.COLOR_BGR2GRAY),
                                  1, 255, cv.THRESH_BINARY)

    kernel = np.ones((3, 3), np.uint8)
    morph = cv.morphologyEx(thresh_gray, cv.MORPH_OPEN, kernel)
    kernel = np.ones((5, 5), np.uint8)
    morph = cv.morphologyEx(morph, cv.MORPH_CLOSE, kernel)

    contours, _ = cv.findContours(morph,
                                  cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)

    for c in contours:
        # if the contour is not sufficiently large, ignore it
        if cv.contourArea(c) < 500:
            continue

        M = cv.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])

        # get the min area rect
        rect = cv.minAreaRect(c)
        box = cv.boxPoints(rect)
        # convert all coordinates floating point values to int
        box = np.int0(box)
        cv.putText(frame, "red", (cX - 20, cY - 20), cv.FONT_HERSHEY_COMPLEX, 1.0, (0, 0, 255))
        # draw a red 'nghien' rectangle
        cv.drawContours(frame, [box], 0, (0, 0, 255), 2)
    # cv.imshow('img', frame)

Here is the output:



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source