0

(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:

Yuchen Ren
  • 287
  • 5
  • 13
  • There was a recent question too: https://stackoverflow.com/questions/72124272/how-to-detect-the-exact-color-of-the-images-using-hsv-color-model-and-opencv/72138638#72138638 – Jeru Luke May 07 '22 at 08:03
  • 3
    why are you inRanging in RGB? that's nearly useless. why aren't you using HSV/HSL color space? red is near hue angle 0. you need **two** inRange calls, one for the hues **upto** 360/180 and one for the hues **from** 0 – Christoph Rackwitz May 07 '22 at 11:28
  • You might also need proper white balancing on top of a better red range. – Cris Luengo May 07 '22 at 14:31

0 Answers0